extract mismatched segments from aligned strings

    >>> list(mismatches(*align('pharmacy', 'farmácia'), context=1))
    [('pha', ' fa'), ('mac', 'mác'), ('c y', 'cia')]

    >>> list(mismatches(*align('constitution', 'constituição'), context=1))
    [('ution', 'uição')]

    >>> list(mismatches(*align('idea', 'ideia'), context=1))
    [('e a', 'eia')]

    >>> list(mismatches(*align('instructed', 'instruído'), context=1))
    [('ucted', 'u ído')]

    >>> list(mismatches(*align('concluded', 'concluído'), context=1))
    [('uded', 'uído')]

def mismatches(s1, s2, context=0, eq=operator.eq):
    '''extract mismatched segments from aligned strings

    >>> list(mismatches(*align('pharmacy', 'farmácia'), context=1))
    [('pha', ' fa'), ('mac', 'mác'), ('c y', 'cia')]

    >>> list(mismatches(*align('constitution', 'constituição'), context=1))
    [('ution', 'uição')]

    >>> list(mismatches(*align('idea', 'ideia'), context=1))
    [('e a', 'eia')]

    >>> list(mismatches(*align('instructed', 'instruído'), context=1))
    [('ucted', 'u ído')]

    >>> list(mismatches(*align('concluded', 'concluído'), context=1))
    [('uded', 'uído')]
    '''
    n = len(s1)
    assert(len(s2) == n)
    lct, rct = context, context if isinstance(context, int) else context
    i = None
    for j in range(n):
        if eq(s1[j], s2[j]):
            if i is not None:
                # report mismatch segment [i:j] with lct chars of left context
                # and rct chars of right context
                p, q = max(0, i-lct), min(j+rct, n)
                yield s1[p:q], s2[p:q]
                i = None
        elif i is None:
                i = j
    if i is not None:
        p = max(i-lct, 0)
        yield s1[p:], s2[p:]