tossi/tolerance.py
def generate_tolerances(morph1, morph2):
    """Generates all reasonable tolerant particle morphs::

    >>> set(generate_tolerances(u'이', u'가'))
    set([u'이(가)', u'(이)가', u'가(이)', u'(가)이'])
    >>> set(generate_tolerances(u'이면', u'면'))
    set([u'(이)면'])

    """
    if morph1 == morph2:
        # Tolerance not required.
        return
    if not (morph1 and morph2):
        # Null allomorph exists.
        yield u'(%s)' % (morph1 or morph2)
        return
    len1, len2 = len(morph1), len(morph2)
    if len1 != len2:
        longer, shorter = (morph1, morph2) if len1 > len2 else (morph2, morph1)
        if longer.endswith(shorter):
            # Longer morph ends with shorter morph.
            yield u'(%s)%s' % (longer[:-len(shorter)], shorter)
            return
    # Find common suffix between two morphs.
    for x, (let1, let2) in enumerate(zip(reversed(morph1), reversed(morph2))):
        if let1 != let2:
            break
    if x:
        # They share the common suffix.
        x1, x2 = len(morph1) - x, len(morph2) - x
        common_suffix = morph1[x1:]
        morph1, morph2 = morph1[:x1], morph2[:x2]
    else:
        # No similarity with each other.
        common_suffix = ''
    for morph1, morph2 in [(morph1, morph2), (morph2, morph1)]:
        yield u'%s(%s)%s' % (morph1, morph2, common_suffix)
        yield u'(%s)%s%s' % (morph1, morph2, common_suffix)
def generate_tolerances(morph1, morph2):
    """Generates all reasonable tolerant particle morphs::

    >>> set(generate_tolerances(u'이', u'가'))
    set([u'이(가)', u'(이)가', u'가(이)', u'(가)이'])
    >>> set(generate_tolerances(u'이면', u'면'))
    set([u'(이)면'])

    """
    if morph1 == morph2:
        # Tolerance not required.
        return
    if not (morph1 and morph2):
        # Null allomorph exists.
        yield u'(%s)' % (morph1 or morph2)
        return
    len1, len2 = len(morph1), len(morph2)
    if len1 != len2:
        longer, shorter = (morph1, morph2) if len1 > len2 else (morph2, morph1)
        if longer.endswith(shorter):
            # Longer morph ends with shorter morph.
            yield u'(%s)%s' % (longer[:-len(shorter)], shorter)
            return
    # Find common suffix between two morphs.
    for x, (let1, let2) in enumerate(zip(reversed(morph1), reversed(morph2))):
        if let1 != let2:
            break
    if x:
        # They share the common suffix.
        x1, x2 = len(morph1) - x, len(morph2) - x
        common_suffix = morph1[x1:]
        morph1, morph2 = morph1[:x1], morph2[:x2]
    else:
        # No similarity with each other.
        common_suffix = ''
    for morph1, morph2 in [(morph1, morph2), (morph2, morph1)]:
        yield u'%s(%s)%s' % (morph1, morph2, common_suffix)
        yield u'(%s)%s%s' % (morph1, morph2, common_suffix)
Generates all reasonable tolerant particle morphs::

    >>> set(generate_tolerances(u'이', u'가'))
    set([u'이(가)', u'(이)가', u'가(이)', u'(가)이'])
    >>> set(generate_tolerances(u'이면', u'면'))
    set([u'(이)면'])