Instruction:
Create a Python 3 function to
return the Daitch - Mokotoff Soundex code for a word.

Response:
def encode(self, word, max_length=6, zero_pad=True):
        """Return the Daitch-Mokotoff Soundex code for a word.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The length of the code returned (defaults to 6; must be between 6
            and 64)
        zero_pad : bool
            Pad the end of the return value with 0s to achieve a max_length
            string

        Returns
        -------
        str
            The Daitch-Mokotoff Soundex value

        Examples
        --------
        >>> pe = DaitchMokotoff()
        >>> sorted(pe.encode('Christopher'))
        ['494379', '594379']
        >>> pe.encode('Niall')
        {'680000'}
        >>> pe.encode('Smith')
        {'463000'}
        >>> pe.encode('Schmidt')
        {'463000'}

        >>> sorted(pe.encode('The quick brown fox', max_length=20,
        ... zero_pad=False))
        ['35457976754', '3557976754']

        """
        dms = ['']  # initialize empty code list

        # Require a max_length of at least 6 and not more than 64
        if max_length != -1:
            max_length = min(max(6, max_length), 64)
        else:
            max_length = 64

        # uppercase, normalize, decompose, and filter non-A-Z
        word = unicode_normalize('NFKD', text_type(word.upper()))
        word = word.replace('ß', 'SS')
        word = ''.join(c for c in word if c in self._uc_set)

        # Nothing to convert, return base case
        if not word:
            if zero_pad:
                return {'0' * max_length}
            return {'0'}

        pos = 0
        while pos < len(word):
            # Iterate through _dms_order, which specifies the possible
            # substrings for which codes exist in the Daitch-Mokotoff coding
            for sstr in self._dms_order[word[pos]]:  # pragma: no branch
                if word[pos:].startswith(sstr):
                    # Having determined a valid substring start, retrieve the
                    # code
                    dm_val = self._dms_table[sstr]

                    # Having retried the code (triple), determine the correct
                    # positional variant (first, pre-vocalic, elsewhere)
                    if pos == 0:
                        dm_val = dm_val[0]
                    elif (
                        pos + len(sstr) < len(word)
                        and word[pos + len(sstr)] in self._uc_v_set
                    ):
                        dm_val = dm_val[1]
                    else:
                        dm_val = dm_val[2]

                    # Build the code strings
                    if isinstance(dm_val, tuple):
                        dms = [_ + text_type(dm_val[0]) for _ in dms] + [
                            _ + text_type(dm_val[1]) for _ in dms
                        ]
                    else:
                        dms = [_ + text_type(dm_val) for _ in dms]
                    pos += len(sstr)
                    break

        # Filter out double letters and _ placeholders
        dms = (
            ''.join(c for c in self._delete_consecutive_repeats(_) if c != '_')
            for _ in dms
        )

        # Trim codes and return set
        if zero_pad:
            dms = ((_ + ('0' * max_length))[:max_length] for _ in dms)
        else:
            dms = (_[:max_length] for _ in dms)
        return set(dms)


Instruction:
Here you have a function in Python 3, explain what it does
def encode(self, word):
        word = word.upper()

        code = ''
        skip = 0

        if word[0:2] == 'AA':
            code = 'Å'
            skip = 2
        elif word[0:2] == 'GI':
            code = 'J'
            skip = 2
        elif word[0:3] == 'SKY':
            code = 'X'
            skip = 3
        elif word[0:2] == 'EI':
            code = 'Æ'
            skip = 2
        elif word[0:2] == 'KY':
            code = 'X'
            skip = 2
        elif word[:1] == 'C':
            code = 'K'
            skip = 1
        elif word[:1] == 'Ä':
            code = 'Æ'
            skip = 1
        elif word[:1] == 'Ö':
            code = 'Ø'
            skip = 1

        if word[-2:] == 'DT':
            word = word[:-2] + 'T'
        # Though the rules indicate this rule applies in all positions, the
        # reference implementation indicates it applies only in final position.
        elif word[-2:-1] in self._uc_v_set and word[-1:] == 'D':
            word = word[:-2]

        for pos, char in enumerate(word):
            if skip:
                skip -= 1
            else:
                for length in sorted(self._replacements, reverse=True):
                    if word[pos : pos + length] in self._replacements[length]:
                        code += self._replacements[length][
                            word[pos : pos + length]
                        ]
                        skip = length - 1
                        break
                else:
                    if not pos or char not in self._uc_v_set:
                        code += char

        code = self._delete_consecutive_repeats(code)

        return code

Response: Encodes a string into a Norphone code.


Instruction:
How would you implement a function in Python 3 that
casts to tuple. Returns ------- tuple The confusion table as a 4-tuple (tp, tn, fp, fn) Example ------- >>> ct = ConfusionTable(120, 60, 20, 30) >>> ct.to_tuple() (120, 60, 20, 30)

Response:
def to_tuple(self):
        """Cast to tuple.

        Returns
        -------
        tuple
            The confusion table as a 4-tuple (tp, tn, fp, fn)

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.to_tuple()
        (120, 60, 20, 30)

        """
        return self._tp, self._tn, self._fp, self._fn


Instruction:
Can you write a function in Python 3 where it
casts to dict. Returns dict

Response:
def to_dict(self):
        """Cast to dict.

        Returns
        -------
        dict
            The confusion table as a dict

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> import pprint
        >>> pprint.pprint(ct.to_dict())
        {'fn': 30, 'fp': 20, 'tn': 60, 'tp': 120}

        """
        return {'tp': self._tp, 'tn': self._tn, 'fp': self._fp, 'fn': self._fn}


Instruction:
Can you generate the documentation for the following Python 3 function
def population(self):
        return self._tp + self._tn + self._fp + self._fn

Response: Return the population of the confusion table.


Instruction:
Given the following Python 3 function, write the documentation
def precision(self):
        if self._tp + self._fp == 0:
            return float('NaN')
        return self._tp / (self._tp + self._fp)

Response: Return precision of the confusion table.


Instruction:
How would you explain what the following Python 3 function does
def precision_gain(self):
        if self.population() == 0:
            return float('NaN')
        random_precision = self.cond_pos_pop() / self.population()
        return self.precision() / random_precision

Response: Return gain in precision.


Instruction:
Can you create a Python 3 function that
returns recall of the confusion table entry.

Response:
def recall(self):
        r"""Return recall.

        Recall is defined as :math:`\frac{tp}{tp + fn}`

        AKA sensitivity

        AKA true positive rate (TPR)

        Cf. https://en.wikipedia.org/wiki/Precision_and_recall

        Cf. https://en.wikipedia.org/wiki/Sensitivity_(test)

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Recall

        Returns
        -------
        float
            The recall of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.recall()
        0.8

        """
        if self._tp + self._fn == 0:
            return float('NaN')
        return self._tp / (self._tp + self._fn)


Instruction:
Can you tell what is the following Python 3 function doing
def specificity(self):
        if self._tn + self._fp == 0:
            return float('NaN')
        return self._tn / (self._tn + self._fp)

Response: Return specificity of the confusion table.


Instruction:
Can you write a function in Python 3 where it
returns negative predictive value of the confusion table.

Response:
def npv(self):
        r"""Return negative predictive value (NPV).

        NPV is defined as :math:`\frac{tn}{tn + fn}`

        Cf. https://en.wikipedia.org/wiki/Negative_predictive_value

        Returns
        -------
        float
            The negative predictive value of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.npv()
        0.6666666666666666

        """
        if self._tn + self._fn == 0:
            return float('NaN')
        return self._tn / (self._tn + self._fn)


Instruction:
Write a Python 3 script for
returning the fall - out of the confusion table.

Response:
def fallout(self):
        r"""Return fall-out.

        Fall-out is defined as :math:`\frac{fp}{fp + tn}`

        AKA false positive rate (FPR)

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Fall-out

        Returns
        -------
        float
            The fall-out of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.fallout()
        0.25

        """
        if self._fp + self._tn == 0:
            return float('NaN')
        return self._fp / (self._fp + self._tn)


Instruction:
Can you tell what is the following Python 3 function doing
def fdr(self):
        if self._fp + self._tp == 0:
            return float('NaN')
        return self._fp / (self._fp + self._tp)

Response: Return the false discovery rate of the confusion table.


Instruction:
Write a Python 3 script to
return the accuracy of the confusion table.

Response:
def accuracy(self):
        r"""Return accuracy.

        Accuracy is defined as :math:`\frac{tp + tn}{population}`

        Cf. https://en.wikipedia.org/wiki/Accuracy

        Returns
        -------
        float
            The accuracy of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.accuracy()
        0.782608695652174

        """
        if self.population() == 0:
            return float('NaN')
        return (self._tp + self._tn) / self.population()


Instruction:
Can you tell what is the following Python 3 function doing
def accuracy_gain(self):
        if self.population() == 0:
            return float('NaN')
        random_accuracy = (self.cond_pos_pop() / self.population()) ** 2 + (
            self.cond_neg_pop() / self.population()
        ) ** 2
        return self.accuracy() / random_accuracy

Response: Return gain in accuracy.


Instruction:
Make a summary of the following Python 3 code
def pr_lmean(self):
        precision = self.precision()
        recall = self.recall()
        if not precision or not recall:
            return 0.0
        elif precision == recall:
            return precision
        return (precision - recall) / (math.log(precision) - math.log(recall))

Response: Return logarithmic mean of precision & recall.


Instruction:
Can you tell what is the following Python 3 function doing
def mcc(self):
        if (
            (
                (self._tp + self._fp)
                * (self._tp + self._fn)
                * (self._tn + self._fp)
                * (self._tn + self._fn)
            )
        ) == 0:
            return float('NaN')
        return ((self._tp * self._tn) - (self._fp * self._fn)) / math.sqrt(
            (self._tp + self._fp)
            * (self._tp + self._fn)
            * (self._tn + self._fp)
            * (self._tn + self._fn)
        )

Response: Return Matthews correlation coefficient of the confusion table entry.


Instruction:
Given the following Python 3 function, write the documentation
def significance(self):
        if (
            (
                (self._tp + self._fp)
                * (self._tp + self._fn)
                * (self._tn + self._fp)
                * (self._tn + self._fn)
            )
        ) == 0:
            return float('NaN')
        return (
            (self._tp * self._tn - self._fp * self._fn) ** 2
            * (self._tp + self._tn + self._fp + self._fn)
        ) / (
            (self._tp + self._fp)
            * (self._tp + self._fn)
            * (self._tn + self._fp)
            * (self._tn + self._fn)
        )

Response: Return the significance of the confusion table.


Instruction:
Write a Python 3 function that can
return κ statistic of the confusion table.

Response:
def kappa_statistic(self):
        r"""Return κ statistic.

        The κ statistic is defined as:
        :math:`\kappa = \frac{accuracy - random~ accuracy}
        {1 - random~ accuracy}`

        The κ statistic compares the performance of the classifier relative to
        the performance of a random classifier. :math:`\kappa` = 0 indicates
        performance identical to random. :math:`\kappa` = 1 indicates perfect
        predictive success. :math:`\kappa` = -1 indicates perfect predictive
        failure.

        Returns
        -------
        float
            The κ statistic of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.kappa_statistic()
        0.5344129554655871

        """
        if self.population() == 0:
            return float('NaN')
        random_accuracy = (
            (self._tn + self._fp) * (self._tn + self._fn)
            + (self._fn + self._tp) * (self._fp + self._tp)
        ) / self.population() ** 2
        return (self.accuracy() - random_accuracy) / (1 - random_accuracy)


Instruction:
How would you explain what the following Python 3 function does
def encode(self, word, max_length=-1):
        # Require a max_length of at least 4
        if max_length != -1:
            max_length = max(4, max_length)

        primary = ''
        secondary = ''

        def _slavo_germanic():
            """Return True if the word appears to be Slavic or Germanic.

            Returns
            -------
            bool
                True if the word appears to be Slavic or Germanic

            """
            if 'W' in word or 'K' in word or 'CZ' in word:
                return True
            return False

        def _metaph_add(pri, sec=''):
            """Return a new metaphone tuple with the supplied elements.

            Parameters
            ----------
            pri : str
                The primary element
            sec : str
                The secondary element

            Returns
            -------
            tuple
                A new metaphone tuple with the supplied elements

            """
            newpri = primary
            newsec = secondary
            if pri:
                newpri += pri
            if sec:
                if sec != ' ':
                    newsec += sec
            else:
                newsec += pri
            return newpri, newsec

        def _is_vowel(pos):
            """Return True if the character at word[pos] is a vowel.

            Parameters
            ----------
            pos : int
                Position in the word

            Returns
            -------
            bool
                True if the character is a vowel

            """
            if pos >= 0 and word[pos] in {'A', 'E', 'I', 'O', 'U', 'Y'}:
                return True
            return False

        def _get_at(pos):
            """Return the character at word[pos].

            Parameters
            ----------
            pos : int
                Position in the word

            Returns
            -------
            str
                Character at word[pos]

            """
            return word[pos]

        def _string_at(pos, slen, substrings):
            """Return True if word[pos:pos+slen] is in substrings.

            Parameters
            ----------
            pos : int
                Position in the word
            slen : int
                Substring length
            substrings : set
                Substrings to search

            Returns
            -------
            bool
                True if word[pos:pos+slen] is in substrings

            """
            if pos < 0:
                return False
            return word[pos : pos + slen] in substrings

        current = 0
        length = len(word)
        if length < 1:
            return '', ''
        last = length - 1

        word = word.upper()
        word = word.replace('ß', 'SS')

        # Pad the original string so that we can index beyond the edge of the
        # world
        word += '     '

        # Skip these when at start of word
        if word[0:2] in {'GN', 'KN', 'PN', 'WR', 'PS'}:
            current += 1

        # Initial 'X' is pronounced 'Z' e.g. 'Xavier'
        if _get_at(0) == 'X':
            primary, secondary = _metaph_add('S')  # 'Z' maps to 'S'
            current += 1

        # Main loop
        while True:
            if current >= length:
                break

            if _get_at(current) in {'A', 'E', 'I', 'O', 'U', 'Y'}:
                if current == 0:
                    # All init vowels now map to 'A'
                    primary, secondary = _metaph_add('A')
                current += 1
                continue

            elif _get_at(current) == 'B':
                # "-mb", e.g", "dumb", already skipped over...
                primary, secondary = _metaph_add('P')
                if _get_at(current + 1) == 'B':
                    current += 2
                else:
                    current += 1
                continue

            elif _get_at(current) == 'Ç':
                primary, secondary = _metaph_add('S')
                current += 1
                continue

            elif _get_at(current) == 'C':
                # Various Germanic
                if (
                    current > 1
                    and not _is_vowel(current - 2)
                    and _string_at((current - 1), 3, {'ACH'})
                    and (
                        (_get_at(current + 2) != 'I')
                        and (
                            (_get_at(current + 2) != 'E')
                            or _string_at(
                                (current - 2), 6, {'BACHER', 'MACHER'}
                            )
                        )
                    )
                ):
                    primary, secondary = _metaph_add('K')
                    current += 2
                    continue

                # Special case 'caesar'
                elif current == 0 and _string_at(current, 6, {'CAESAR'}):
                    primary, secondary = _metaph_add('S')
                    current += 2
                    continue

                # Italian 'chianti'
                elif _string_at(current, 4, {'CHIA'}):
                    primary, secondary = _metaph_add('K')
                    current += 2
                    continue

                elif _string_at(current, 2, {'CH'}):
                    # Find 'Michael'
                    if current > 0 and _string_at(current, 4, {'CHAE'}):
                        primary, secondary = _metaph_add('K', 'X')
                        current += 2
                        continue

                    # Greek roots e.g. 'chemistry', 'chorus'
                    elif (
                        current == 0
                        and (
                            _string_at((current + 1), 5, {'HARAC', 'HARIS'})
                            or _string_at(
                                (current + 1), 3, {'HOR', 'HYM', 'HIA', 'HEM'}
                            )
                        )
                        and not _string_at(0, 5, {'CHORE'})
                    ):
                        primary, secondary = _metaph_add('K')
                        current += 2
                        continue

                    # Germanic, Greek, or otherwise 'ch' for 'kh' sound
                    elif (
                        (
                            _string_at(0, 4, {'VAN ', 'VON '})
                            or _string_at(0, 3, {'SCH'})
                        )
                        or
                        # 'architect but not 'arch', 'orchestra', 'orchid'
                        _string_at(
                            (current - 2), 6, {'ORCHES', 'ARCHIT', 'ORCHID'}
                        )
                        or _string_at((current + 2), 1, {'T', 'S'})
                        or (
                            (
                                _string_at(
                                    (current - 1), 1, {'A', 'O', 'U', 'E'}
                                )
                                or (current == 0)
                            )
                            and
                            # e.g., 'wachtler', 'wechsler', but not 'tichner'
                            _string_at(
                                (current + 2),
                                1,
                                {
                                    'L',
                                    'R',
                                    'N',
                                    'M',
                                    'B',
                                    'H',
                                    'F',
                                    'V',
                                    'W',
                                    ' ',
                                },
                            )
                        )
                    ):
                        primary, secondary = _metaph_add('K')

                    else:
                        if current > 0:
                            if _string_at(0, 2, {'MC'}):
                                # e.g., "McHugh"
                                primary, secondary = _metaph_add('K')
                            else:
                                primary, secondary = _metaph_add('X', 'K')
                        else:
                            primary, secondary = _metaph_add('X')

                    current += 2
                    continue

                # e.g, 'czerny'
                elif _string_at(current, 2, {'CZ'}) and not _string_at(
                    (current - 2), 4, {'WICZ'}
                ):
                    primary, secondary = _metaph_add('S', 'X')
                    current += 2
                    continue

                # e.g., 'focaccia'
                elif _string_at((current + 1), 3, {'CIA'}):
                    primary, secondary = _metaph_add('X')
                    current += 3

                # double 'C', but not if e.g. 'McClellan'
                elif _string_at(current, 2, {'CC'}) and not (
                    (current == 1) and (_get_at(0) == 'M')
                ):
                    # 'bellocchio' but not 'bacchus'
                    if _string_at(
                        (current + 2), 1, {'I', 'E', 'H'}
                    ) and not _string_at((current + 2), 2, {'HU'}):
                        # 'accident', 'accede' 'succeed'
                        if (
                            (current == 1) and _get_at(current - 1) == 'A'
                        ) or _string_at((current - 1), 5, {'UCCEE', 'UCCES'}):
                            primary, secondary = _metaph_add('KS')
                        # 'bacci', 'bertucci', other italian
                        else:
                            primary, secondary = _metaph_add('X')
                        current += 3
                        continue
                    else:  # Pierce's rule
                        primary, secondary = _metaph_add('K')
                        current += 2
                        continue

                elif _string_at(current, 2, {'CK', 'CG', 'CQ'}):
                    primary, secondary = _metaph_add('K')
                    current += 2
                    continue

                elif _string_at(current, 2, {'CI', 'CE', 'CY'}):
                    # Italian vs. English
                    if _string_at(current, 3, {'CIO', 'CIE', 'CIA'}):
                        primary, secondary = _metaph_add('S', 'X')
                    else:
                        primary, secondary = _metaph_add('S')
                    current += 2
                    continue

                # else
                else:
                    primary, secondary = _metaph_add('K')

                    # name sent in 'mac caffrey', 'mac gregor
                    if _string_at((current + 1), 2, {' C', ' Q', ' G'}):
                        current += 3
                    elif _string_at(
                        (current + 1), 1, {'C', 'K', 'Q'}
                    ) and not _string_at((current + 1), 2, {'CE', 'CI'}):
                        current += 2
                    else:
                        current += 1
                    continue

            elif _get_at(current) == 'D':
                if _string_at(current, 2, {'DG'}):
                    if _string_at((current + 2), 1, {'I', 'E', 'Y'}):
                        # e.g. 'edge'
                        primary, secondary = _metaph_add('J')
                        current += 3
                        continue
                    else:
                        # e.g. 'edgar'
                        primary, secondary = _metaph_add('TK')
                        current += 2
                        continue

                elif _string_at(current, 2, {'DT', 'DD'}):
                    primary, secondary = _metaph_add('T')
                    current += 2
                    continue

                # else
                else:
                    primary, secondary = _metaph_add('T')
                    current += 1
                    continue

            elif _get_at(current) == 'F':
                if _get_at(current + 1) == 'F':
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('F')
                continue

            elif _get_at(current) == 'G':
                if _get_at(current + 1) == 'H':
                    if (current > 0) and not _is_vowel(current - 1):
                        primary, secondary = _metaph_add('K')
                        current += 2
                        continue

                    # 'ghislane', ghiradelli
                    elif current == 0:
                        if _get_at(current + 2) == 'I':
                            primary, secondary = _metaph_add('J')
                        else:
                            primary, secondary = _metaph_add('K')
                        current += 2
                        continue

                    # Parker's rule (with some further refinements) -
                    # e.g., 'hugh'
                    elif (
                        (
                            (current > 1)
                            and _string_at((current - 2), 1, {'B', 'H', 'D'})
                        )
                        or
                        # e.g., 'bough'
                        (
                            (current > 2)
                            and _string_at((current - 3), 1, {'B', 'H', 'D'})
                        )
                        or
                        # e.g., 'broughton'
                        (
                            (current > 3)
                            and _string_at((current - 4), 1, {'B', 'H'})
                        )
                    ):
                        current += 2
                        continue
                    else:
                        # e.g. 'laugh', 'McLaughlin', 'cough',
                        #      'gough', 'rough', 'tough'
                        if (
                            (current > 2)
                            and (_get_at(current - 1) == 'U')
                            and (
                                _string_at(
                                    (current - 3), 1, {'C', 'G', 'L', 'R', 'T'}
                                )
                            )
                        ):
                            primary, secondary = _metaph_add('F')
                        elif (current > 0) and _get_at(current - 1) != 'I':
                            primary, secondary = _metaph_add('K')
                        current += 2
                        continue

                elif _get_at(current + 1) == 'N':
                    if (
                        (current == 1)
                        and _is_vowel(0)
                        and not _slavo_germanic()
                    ):
                        primary, secondary = _metaph_add('KN', 'N')
                    # not e.g. 'cagney'
                    elif (
                        not _string_at((current + 2), 2, {'EY'})
                        and (_get_at(current + 1) != 'Y')
                        and not _slavo_germanic()
                    ):
                        primary, secondary = _metaph_add('N', 'KN')
                    else:
                        primary, secondary = _metaph_add('KN')
                    current += 2
                    continue

                # 'tagliaro'
                elif (
                    _string_at((current + 1), 2, {'LI'})
                    and not _slavo_germanic()
                ):
                    primary, secondary = _metaph_add('KL', 'L')
                    current += 2
                    continue

                # -ges-, -gep-, -gel-, -gie- at beginning
                elif (current == 0) and (
                    (_get_at(current + 1) == 'Y')
                    or _string_at(
                        (current + 1),
                        2,
                        {
                            'ES',
                            'EP',
                            'EB',
                            'EL',
                            'EY',
                            'IB',
                            'IL',
                            'IN',
                            'IE',
                            'EI',
                            'ER',
                        },
                    )
                ):
                    primary, secondary = _metaph_add('K', 'J')
                    current += 2
                    continue

                #  -ger-,  -gy-
                elif (
                    (
                        _string_at((current + 1), 2, {'ER'})
                        or (_get_at(current + 1) == 'Y')
                    )
                    and not _string_at(0, 6, {'DANGER', 'RANGER', 'MANGER'})
                    and not _string_at((current - 1), 1, {'E', 'I'})
                    and not _string_at((current - 1), 3, {'RGY', 'OGY'})
                ):
                    primary, secondary = _metaph_add('K', 'J')
                    current += 2
                    continue

                #  italian e.g, 'biaggi'
                elif _string_at(
                    (current + 1), 1, {'E', 'I', 'Y'}
                ) or _string_at((current - 1), 4, {'AGGI', 'OGGI'}):
                    # obvious germanic
                    if (
                        _string_at(0, 4, {'VAN ', 'VON '})
                        or _string_at(0, 3, {'SCH'})
                    ) or _string_at((current + 1), 2, {'ET'}):
                        primary, secondary = _metaph_add('K')
                    elif _string_at((current + 1), 4, {'IER '}):
                        primary, secondary = _metaph_add('J')
                    else:
                        primary, secondary = _metaph_add('J', 'K')
                    current += 2
                    continue

                else:
                    if _get_at(current + 1) == 'G':
                        current += 2
                    else:
                        current += 1
                    primary, secondary = _metaph_add('K')
                    continue

            elif _get_at(current) == 'H':
                # only keep if first & before vowel or btw. 2 vowels
                if ((current == 0) or _is_vowel(current - 1)) and _is_vowel(
                    current + 1
                ):
                    primary, secondary = _metaph_add('H')
                    current += 2
                else:  # also takes care of 'HH'
                    current += 1
                continue

            elif _get_at(current) == 'J':
                # obvious spanish, 'jose', 'san jacinto'
                if _string_at(current, 4, {'JOSE'}) or _string_at(
                    0, 4, {'SAN '}
                ):
                    if (
                        (current == 0) and (_get_at(current + 4) == ' ')
                    ) or _string_at(0, 4, {'SAN '}):
                        primary, secondary = _metaph_add('H')
                    else:
                        primary, secondary = _metaph_add('J', 'H')
                    current += 1
                    continue

                elif (current == 0) and not _string_at(current, 4, {'JOSE'}):
                    # Yankelovich/Jankelowicz
                    primary, secondary = _metaph_add('J', 'A')
                # Spanish pron. of e.g. 'bajador'
                elif (
                    _is_vowel(current - 1)
                    and not _slavo_germanic()
                    and (
                        (_get_at(current + 1) == 'A')
                        or (_get_at(current + 1) == 'O')
                    )
                ):
                    primary, secondary = _metaph_add('J', 'H')
                elif current == last:
                    primary, secondary = _metaph_add('J', ' ')
                elif not _string_at(
                    (current + 1), 1, {'L', 'T', 'K', 'S', 'N', 'M', 'B', 'Z'}
                ) and not _string_at((current - 1), 1, {'S', 'K', 'L'}):
                    primary, secondary = _metaph_add('J')

                if _get_at(current + 1) == 'J':  # it could happen!
                    current += 2
                else:
                    current += 1
                continue

            elif _get_at(current) == 'K':
                if _get_at(current + 1) == 'K':
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('K')
                continue

            elif _get_at(current) == 'L':
                if _get_at(current + 1) == 'L':
                    # Spanish e.g. 'cabrillo', 'gallegos'
                    if (
                        (current == (length - 3))
                        and _string_at(
                            (current - 1), 4, {'ILLO', 'ILLA', 'ALLE'}
                        )
                    ) or (
                        (
                            _string_at((last - 1), 2, {'AS', 'OS'})
                            or _string_at(last, 1, {'A', 'O'})
                        )
                        and _string_at((current - 1), 4, {'ALLE'})
                    ):
                        primary, secondary = _metaph_add('L', ' ')
                        current += 2
                        continue
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('L')
                continue

            elif _get_at(current) == 'M':
                if (
                    (
                        _string_at((current - 1), 3, {'UMB'})
                        and (
                            ((current + 1) == last)
                            or _string_at((current + 2), 2, {'ER'})
                        )
                    )
                    or
                    # 'dumb', 'thumb'
                    (_get_at(current + 1) == 'M')
                ):
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('M')
                continue

            elif _get_at(current) == 'N':
                if _get_at(current + 1) == 'N':
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('N')
                continue

            elif _get_at(current) == 'Ñ':
                current += 1
                primary, secondary = _metaph_add('N')
                continue

            elif _get_at(current) == 'P':
                if _get_at(current + 1) == 'H':
                    primary, secondary = _metaph_add('F')
                    current += 2
                    continue

                # also account for "campbell", "raspberry"
                elif _string_at((current + 1), 1, {'P', 'B'}):
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('P')
                continue

            elif _get_at(current) == 'Q':
                if _get_at(current + 1) == 'Q':
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('K')
                continue

            elif _get_at(current) == 'R':
                # french e.g. 'rogier', but exclude 'hochmeier'
                if (
                    (current == last)
                    and not _slavo_germanic()
                    and _string_at((current - 2), 2, {'IE'})
                    and not _string_at((current - 4), 2, {'ME', 'MA'})
                ):
                    primary, secondary = _metaph_add('', 'R')
                else:
                    primary, secondary = _metaph_add('R')

                if _get_at(current + 1) == 'R':
                    current += 2
                else:
                    current += 1
                continue

            elif _get_at(current) == 'S':
                # special cases 'island', 'isle', 'carlisle', 'carlysle'
                if _string_at((current - 1), 3, {'ISL', 'YSL'}):
                    current += 1
                    continue

                # special case 'sugar-'
                elif (current == 0) and _string_at(current, 5, {'SUGAR'}):
                    primary, secondary = _metaph_add('X', 'S')
                    current += 1
                    continue

                elif _string_at(current, 2, {'SH'}):
                    # Germanic
                    if _string_at(
                        (current + 1), 4, {'HEIM', 'HOEK', 'HOLM', 'HOLZ'}
                    ):
                        primary, secondary = _metaph_add('S')
                    else:
                        primary, secondary = _metaph_add('X')
                    current += 2
                    continue

                # Italian & Armenian
                elif _string_at(current, 3, {'SIO', 'SIA'}) or _string_at(
                    current, 4, {'SIAN'}
                ):
                    if not _slavo_germanic():
                        primary, secondary = _metaph_add('S', 'X')
                    else:
                        primary, secondary = _metaph_add('S')
                    current += 3
                    continue

                # German & anglicisations, e.g. 'smith' match 'schmidt',
                #                               'snider' match 'schneider'
                # also, -sz- in Slavic language although in Hungarian it is
                #       pronounced 's'
                elif (
                    (current == 0)
                    and _string_at((current + 1), 1, {'M', 'N', 'L', 'W'})
                ) or _string_at((current + 1), 1, {'Z'}):
                    primary, secondary = _metaph_add('S', 'X')
                    if _string_at((current + 1), 1, {'Z'}):
                        current += 2
                    else:
                        current += 1
                    continue

                elif _string_at(current, 2, {'SC'}):
                    # Schlesinger's rule
                    if _get_at(current + 2) == 'H':
                        # dutch origin, e.g. 'school', 'schooner'
                        if _string_at(
                            (current + 3),
                            2,
                            {'OO', 'ER', 'EN', 'UY', 'ED', 'EM'},
                        ):
                            # 'schermerhorn', 'schenker'
                            if _string_at((current + 3), 2, {'ER', 'EN'}):
                                primary, secondary = _metaph_add('X', 'SK')
                            else:
                                primary, secondary = _metaph_add('SK')
                            current += 3
                            continue
                        else:
                            if (
                                (current == 0)
                                and not _is_vowel(3)
                                and (_get_at(3) != 'W')
                            ):
                                primary, secondary = _metaph_add('X', 'S')
                            else:
                                primary, secondary = _metaph_add('X')
                            current += 3
                            continue

                    elif _string_at((current + 2), 1, {'I', 'E', 'Y'}):
                        primary, secondary = _metaph_add('S')
                        current += 3
                        continue

                    # else
                    else:
                        primary, secondary = _metaph_add('SK')
                        current += 3
                        continue

                else:
                    # french e.g. 'resnais', 'artois'
                    if (current == last) and _string_at(
                        (current - 2), 2, {'AI', 'OI'}
                    ):
                        primary, secondary = _metaph_add('', 'S')
                    else:
                        primary, secondary = _metaph_add('S')

                    if _string_at((current + 1), 1, {'S', 'Z'}):
                        current += 2
                    else:
                        current += 1
                    continue

            elif _get_at(current) == 'T':
                if _string_at(current, 4, {'TION'}):
                    primary, secondary = _metaph_add('X')
                    current += 3
                    continue

                elif _string_at(current, 3, {'TIA', 'TCH'}):
                    primary, secondary = _metaph_add('X')
                    current += 3
                    continue

                elif _string_at(current, 2, {'TH'}) or _string_at(
                    current, 3, {'TTH'}
                ):
                    # special case 'thomas', 'thames' or germanic
                    if (
                        _string_at((current + 2), 2, {'OM', 'AM'})
                        or _string_at(0, 4, {'VAN ', 'VON '})
                        or _string_at(0, 3, {'SCH'})
                    ):
                        primary, secondary = _metaph_add('T')
                    else:
                        primary, secondary = _metaph_add('0', 'T')
                    current += 2
                    continue

                elif _string_at((current + 1), 1, {'T', 'D'}):
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('T')
                continue

            elif _get_at(current) == 'V':
                if _get_at(current + 1) == 'V':
                    current += 2
                else:
                    current += 1
                primary, secondary = _metaph_add('F')
                continue

            elif _get_at(current) == 'W':
                # can also be in middle of word
                if _string_at(current, 2, {'WR'}):
                    primary, secondary = _metaph_add('R')
                    current += 2
                    continue
                elif (current == 0) and (
                    _is_vowel(current + 1) or _string_at(current, 2, {'WH'})
                ):
                    # Wasserman should match Vasserman
                    if _is_vowel(current + 1):
                        primary, secondary = _metaph_add('A', 'F')
                    else:
                        # need Uomo to match Womo
                        primary, secondary = _metaph_add('A')

                # Arnow should match Arnoff
                if (
                    ((current == last) and _is_vowel(current - 1))
                    or _string_at(
                        (current - 1), 5, {'EWSKI', 'EWSKY', 'OWSKI', 'OWSKY'}
                    )
                    or _string_at(0, 3, {'SCH'})
                ):
                    primary, secondary = _metaph_add('', 'F')
                    current += 1
                    continue
                # Polish e.g. 'filipowicz'
                elif _string_at(current, 4, {'WICZ', 'WITZ'}):
                    primary, secondary = _metaph_add('TS', 'FX')
                    current += 4
                    continue
                # else skip it
                else:
                    current += 1
                    continue

            elif _get_at(current) == 'X':
                # French e.g. breaux
                if not (
                    (current == last)
                    and (
                        _string_at((current - 3), 3, {'IAU', 'EAU'})
                        or _string_at((current - 2), 2, {'AU', 'OU'})
                    )
                ):
                    primary, secondary = _metaph_add('KS')

                if _string_at((current + 1), 1, {'C', 'X'}):
                    current += 2
                else:
                    current += 1
                continue

            elif _get_at(current) == 'Z':
                # Chinese Pinyin e.g. 'zhao'
                if _get_at(current + 1) == 'H':
                    primary, secondary = _metaph_add('J')
                    current += 2
                    continue
                elif _string_at((current + 1), 2, {'ZO', 'ZI', 'ZA'}) or (
                    _slavo_germanic()
                    and ((current > 0) and _get_at(current - 1) != 'T')
                ):
                    primary, secondary = _metaph_add('S', 'TS')
                else:
                    primary, secondary = _metaph_add('S')

                if _get_at(current + 1) == 'Z':
                    current += 2
                else:
                    current += 1
                continue

            else:
                current += 1

        if max_length > 0:
            primary = primary[:max_length]
            secondary = secondary[:max_length]
        if primary == secondary:
            secondary = ''

        return primary, secondary

Response: Encodes a word into a Double Metaphone code.


Instruction:
Can you create a Python 3 function that
returns the stemmed version of the given word.

Response:
def stem(self, word):
        """Return CLEF German stem.

        Parameters
        ----------
        word : str
            The word to stem

        Returns
        -------
        str
            Word stem

        Examples
        --------
        >>> stmr = CLEFGerman()
        >>> stmr.stem('lesen')
        'lese'
        >>> stmr.stem('graues')
        'grau'
        >>> stmr.stem('buchstabieren')
        'buchstabier'

        """
        # lowercase, normalize, and compose
        word = normalize('NFC', text_type(word.lower()))

        # remove umlauts
        word = word.translate(self._umlauts)

        # remove plurals
        wlen = len(word) - 1

        if wlen > 3:
            if wlen > 5:
                if word[-3:] == 'nen':
                    return word[:-3]
            if wlen > 4:
                if word[-2:] in {'en', 'se', 'es', 'er'}:
                    return word[:-2]
            if word[-1] in {'e', 'n', 'r', 's'}:
                return word[:-1]
        return word


Instruction:
Here you have a function in Python 3, explain what it does
def encode(self, word, mode=1, lang='de'):
        phonet_hash = Counter()
        alpha_pos = Counter()

        phonet_hash_1 = Counter()
        phonet_hash_2 = Counter()

        def _initialize_phonet(lang):
            """Initialize phonet variables.

            Parameters
            ----------
            lang : str
                Language to use for rules

            """
            if lang == 'none':
                _phonet_rules = self._rules_no_lang
            else:
                _phonet_rules = self._rules_german

            phonet_hash[''] = -1

            # German and international umlauts
            for j in {
                'À',
                'Á',
                'Â',
                'Ã',
                'Ä',
                'Å',
                'Æ',
                'Ç',
                'È',
                'É',
                'Ê',
                'Ë',
                'Ì',
                'Í',
                'Î',
                'Ï',
                'Ð',
                'Ñ',
                'Ò',
                'Ó',
                'Ô',
                'Õ',
                'Ö',
                'Ø',
                'Ù',
                'Ú',
                'Û',
                'Ü',
                'Ý',
                'Þ',
                'ß',
                'Œ',
                'Š',
                'Ÿ',
            }:
                alpha_pos[j] = 1
                phonet_hash[j] = -1

            # "normal" letters ('A'-'Z')
            for i, j in enumerate('ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
                alpha_pos[j] = i + 2
                phonet_hash[j] = -1

            for i in range(26):
                for j in range(28):
                    phonet_hash_1[i, j] = -1
                    phonet_hash_2[i, j] = -1

            # for each phonetc rule
            for i in range(len(_phonet_rules)):
                rule = _phonet_rules[i]

                if rule and i % 3 == 0:
                    # calculate first hash value
                    k = _phonet_rules[i][0]

                    if phonet_hash[k] < 0 and (
                        _phonet_rules[i + 1] or _phonet_rules[i + 2]
                    ):
                        phonet_hash[k] = i

                    # calculate second hash values
                    if k and alpha_pos[k] >= 2:
                        k = alpha_pos[k]

                        j = k - 2
                        rule = rule[1:]

                        if not rule:
                            rule = ' '
                        elif rule[0] == '(':
                            rule = rule[1:]
                        else:
                            rule = rule[0]

                        while rule and (rule[0] != ')'):
                            k = alpha_pos[rule[0]]

                            if k > 0:
                                # add hash value for this letter
                                if phonet_hash_1[j, k] < 0:
                                    phonet_hash_1[j, k] = i
                                    phonet_hash_2[j, k] = i

                                if phonet_hash_2[j, k] >= (i - 30):
                                    phonet_hash_2[j, k] = i
                                else:
                                    k = -1

                            if k <= 0:
                                # add hash value for all letters
                                if phonet_hash_1[j, 0] < 0:
                                    phonet_hash_1[j, 0] = i

                                phonet_hash_2[j, 0] = i

                            rule = rule[1:]

        def _phonet(term, mode, lang):
            """Return the phonet coded form of a term.

            Parameters
            ----------
            term : str
                Term to transform
            mode : int
                The ponet variant to employ (1 or 2)
            lang : str
                ``de`` (default) for German, ``none`` for no language

            Returns
            -------
            str
                The phonet value

            """
            if lang == 'none':
                _phonet_rules = self._rules_no_lang
            else:
                _phonet_rules = self._rules_german

            char0 = ''
            dest = term

            if not term:
                return ''

            term_length = len(term)

            # convert input string to upper-case
            src = term.translate(self._upper_trans)

            # check "src"
            i = 0
            j = 0
            zeta = 0

            while i < len(src):
                char = src[i]

                pos = alpha_pos[char]

                if pos >= 2:
                    xpos = pos - 2

                    if i + 1 == len(src):
                        pos = alpha_pos['']
                    else:
                        pos = alpha_pos[src[i + 1]]

                    start1 = phonet_hash_1[xpos, pos]
                    start2 = phonet_hash_1[xpos, 0]
                    end1 = phonet_hash_2[xpos, pos]
                    end2 = phonet_hash_2[xpos, 0]

                    # preserve rule priorities
                    if (start2 >= 0) and ((start1 < 0) or (start2 < start1)):
                        pos = start1
                        start1 = start2
                        start2 = pos
                        pos = end1
                        end1 = end2
                        end2 = pos

                    if (end1 >= start2) and (start2 >= 0):
                        if end2 > end1:
                            end1 = end2

                        start2 = -1
                        end2 = -1
                else:
                    pos = phonet_hash[char]
                    start1 = pos
                    end1 = 10000
                    start2 = -1
                    end2 = -1

                pos = start1
                zeta0 = 0

                if pos >= 0:
                    # check rules for this char
                    while (_phonet_rules[pos] is None) or (
                        _phonet_rules[pos][0] == char
                    ):
                        if pos > end1:
                            if start2 > 0:
                                pos = start2
                                start1 = start2
                                start2 = -1
                                end1 = end2
                                end2 = -1
                                continue

                            break

                        if (_phonet_rules[pos] is None) or (
                            _phonet_rules[pos + mode] is None
                        ):
                            # no conversion rule available
                            pos += 3
                            continue

                        # check whole string
                        matches = 1  # number of matching letters
                        priority = 5  # default priority
                        rule = _phonet_rules[pos]
                        rule = rule[1:]

                        while (
                            rule
                            and (len(src) > (i + matches))
                            and (src[i + matches] == rule[0])
                            and not rule[0].isdigit()
                            and (rule not in '(-<^$')
                        ):
                            matches += 1
                            rule = rule[1:]

                        if rule and (rule[0] == '('):
                            # check an array of letters
                            if (
                                (len(src) > (i + matches))
                                and src[i + matches].isalpha()
                                and (src[i + matches] in rule[1:])
                            ):
                                matches += 1

                                while rule and rule[0] != ')':
                                    rule = rule[1:]

                                # if rule[0] == ')':
                                rule = rule[1:]

                        if rule:
                            priority0 = ord(rule[0])
                        else:
                            priority0 = 0

                        matches0 = matches

                        while rule and rule[0] == '-' and matches > 1:
                            matches -= 1
                            rule = rule[1:]

                        if rule and rule[0] == '<':
                            rule = rule[1:]

                        if rule and rule[0].isdigit():
                            # read priority
                            priority = int(rule[0])
                            rule = rule[1:]

                        if rule and rule[0:2] == '^^':
                            rule = rule[1:]

                        if (
                            not rule
                            or (
                                (rule[0] == '^')
                                and ((i == 0) or not src[i - 1].isalpha())
                                and (
                                    (rule[1:2] != '$')
                                    or (
                                        not (
                                            src[
                                                i + matches0 : i + matches0 + 1
                                            ].isalpha()
                                        )
                                        and (
                                            src[
                                                i + matches0 : i + matches0 + 1
                                            ]
                                            != '.'
                                        )
                                    )
                                )
                            )
                            or (
                                (rule[0] == '$')
                                and (i > 0)
                                and src[i - 1].isalpha()
                                and (
                                    (
                                        not src[
                                            i + matches0 : i + matches0 + 1
                                        ].isalpha()
                                    )
                                    and (
                                        src[i + matches0 : i + matches0 + 1]
                                        != '.'
                                    )
                                )
                            )
                        ):
                            # look for continuation, if:
                            # matches > 1 und NO '-' in first string */
                            pos0 = -1

                            start3 = 0
                            start4 = 0
                            end3 = 0
                            end4 = 0

                            if (
                                (matches > 1)
                                and src[i + matches : i + matches + 1]
                                and (priority0 != ord('-'))
                            ):
                                char0 = src[i + matches - 1]
                                pos0 = alpha_pos[char0]

                                if pos0 >= 2 and src[i + matches]:
                                    xpos = pos0 - 2
                                    pos0 = alpha_pos[src[i + matches]]
                                    start3 = phonet_hash_1[xpos, pos0]
                                    start4 = phonet_hash_1[xpos, 0]
                                    end3 = phonet_hash_2[xpos, pos0]
                                    end4 = phonet_hash_2[xpos, 0]

                                    # preserve rule priorities
                                    if (start4 >= 0) and (
                                        (start3 < 0) or (start4 < start3)
                                    ):
                                        pos0 = start3
                                        start3 = start4
                                        start4 = pos0
                                        pos0 = end3
                                        end3 = end4
                                        end4 = pos0

                                    if (end3 >= start4) and (start4 >= 0):
                                        if end4 > end3:
                                            end3 = end4

                                        start4 = -1
                                        end4 = -1
                                else:
                                    pos0 = phonet_hash[char0]
                                    start3 = pos0
                                    end3 = 10000
                                    start4 = -1
                                    end4 = -1

                                pos0 = start3

                            # check continuation rules for src[i+matches]
                            if pos0 >= 0:
                                while (_phonet_rules[pos0] is None) or (
                                    _phonet_rules[pos0][0] == char0
                                ):
                                    if pos0 > end3:
                                        if start4 > 0:
                                            pos0 = start4
                                            start3 = start4
                                            start4 = -1
                                            end3 = end4
                                            end4 = -1
                                            continue

                                        priority0 = -1

                                        # important
                                        break

                                    if (_phonet_rules[pos0] is None) or (
                                        _phonet_rules[pos0 + mode] is None
                                    ):
                                        # no conversion rule available
                                        pos0 += 3
                                        continue

                                    # check whole string
                                    matches0 = matches
                                    priority0 = 5
                                    rule = _phonet_rules[pos0]
                                    rule = rule[1:]

                                    while (
                                        rule
                                        and (
                                            src[
                                                i + matches0 : i + matches0 + 1
                                            ]
                                            == rule[0]
                                        )
                                        and (
                                            not rule[0].isdigit()
                                            or (rule in '(-<^$')
                                        )
                                    ):
                                        matches0 += 1
                                        rule = rule[1:]

                                    if rule and rule[0] == '(':
                                        # check an array of letters
                                        if src[
                                            i + matches0 : i + matches0 + 1
                                        ].isalpha() and (
                                            src[i + matches0] in rule[1:]
                                        ):
                                            matches0 += 1

                                            while rule and rule[0] != ')':
                                                rule = rule[1:]

                                            # if rule[0] == ')':
                                            rule = rule[1:]

                                    while rule and rule[0] == '-':
                                        # "matches0" is NOT decremented
                                        # because of
                                        #    "if (matches0 == matches)"
                                        rule = rule[1:]

                                    if rule and rule[0] == '<':
                                        rule = rule[1:]

                                    if rule and rule[0].isdigit():
                                        priority0 = int(rule[0])
                                        rule = rule[1:]

                                    if (
                                        not rule
                                        or
                                        # rule == '^' is not possible here
                                        (
                                            (rule[0] == '$')
                                            and not src[
                                                i + matches0 : i + matches0 + 1
                                            ].isalpha()
                                            and (
                                                src[
                                                    i
                                                    + matches0 : i
                                                    + matches0
                                                    + 1
                                                ]
                                                != '.'
                                            )
                                        )
                                    ):
                                        if matches0 == matches:
                                            # this is only a partial string
                                            pos0 += 3
                                            continue

                                        if priority0 < priority:
                                            # priority is too low
                                            pos0 += 3
                                            continue

                                        # continuation rule found
                                        break

                                    pos0 += 3

                                # end of "while"
                                if (priority0 >= priority) and (
                                    (_phonet_rules[pos0] is not None)
                                    and (_phonet_rules[pos0][0] == char0)
                                ):

                                    pos += 3
                                    continue

                            # replace string
                            if _phonet_rules[pos] and (
                                '<' in _phonet_rules[pos][1:]
                            ):
                                priority0 = 1
                            else:
                                priority0 = 0

                            rule = _phonet_rules[pos + mode]

                            if (priority0 == 1) and (zeta == 0):
                                # rule with '<' is applied
                                if (
                                    (j > 0)
                                    and rule
                                    and (
                                        (dest[j - 1] == char)
                                        or (dest[j - 1] == rule[0])
                                    )
                                ):
                                    j -= 1

                                zeta0 = 1
                                zeta += 1
                                matches0 = 0

                                while rule and src[i + matches0]:
                                    src = (
                                        src[0 : i + matches0]
                                        + rule[0]
                                        + src[i + matches0 + 1 :]
                                    )
                                    matches0 += 1
                                    rule = rule[1:]

                                if matches0 < matches:
                                    src = (
                                        src[0 : i + matches0]
                                        + src[i + matches :]
                                    )

                                char = src[i]
                            else:
                                i = i + matches - 1
                                zeta = 0

                                while len(rule) > 1:
                                    if (j == 0) or (dest[j - 1] != rule[0]):
                                        dest = (
                                            dest[0:j]
                                            + rule[0]
                                            + dest[min(len(dest), j + 1) :]
                                        )
                                        j += 1

                                    rule = rule[1:]

                                # new "current char"
                                if not rule:
                                    rule = ''
                                    char = ''
                                else:
                                    char = rule[0]

                                if (
                                    _phonet_rules[pos]
                                    and '^^' in _phonet_rules[pos][1:]
                                ):
                                    if char:
                                        dest = (
                                            dest[0:j]
                                            + char
                                            + dest[min(len(dest), j + 1) :]
                                        )
                                        j += 1

                                    src = src[i + 1 :]
                                    i = 0
                                    zeta0 = 1

                            break

                        pos += 3

                        if pos > end1 and start2 > 0:
                            pos = start2
                            start1 = start2
                            end1 = end2
                            start2 = -1
                            end2 = -1

                if zeta0 == 0:
                    if char and ((j == 0) or (dest[j - 1] != char)):
                        # delete multiple letters only
                        dest = (
                            dest[0:j] + char + dest[min(j + 1, term_length) :]
                        )
                        j += 1

                    i += 1
                    zeta = 0

            dest = dest[0:j]

            return dest

        _initialize_phonet(lang)

        word = unicode_normalize('NFKC', text_type(word))
        return _phonet(word, mode, lang)

Response: Encodes a word into a set of phonet code.


Instruction:
Here you have a function in Python 3, explain what it does
def stem(self, word):
        # lowercase, normalize, and compose
        word = normalize('NFC', text_type(word.lower()))

        r1_start = min(max(3, self._sb_r1(word)), len(word))

        # Step 1
        _r1 = word[r1_start:]
        if _r1[-7:] == 'erendes':
            word = word[:-7]
        elif _r1[-6:] in {'erende', 'hedens'}:
            word = word[:-6]
        elif _r1[-5:] in {
            'ethed',
            'erede',
            'heden',
            'heder',
            'endes',
            'ernes',
            'erens',
            'erets',
        }:
            word = word[:-5]
        elif _r1[-4:] in {
            'ered',
            'ende',
            'erne',
            'eren',
            'erer',
            'heds',
            'enes',
            'eres',
            'eret',
        }:
            word = word[:-4]
        elif _r1[-3:] in {'hed', 'ene', 'ere', 'ens', 'ers', 'ets'}:
            word = word[:-3]
        elif _r1[-2:] in {'en', 'er', 'es', 'et'}:
            word = word[:-2]
        elif _r1[-1:] == 'e':
            word = word[:-1]
        elif _r1[-1:] == 's':
            if len(word) > 1 and word[-2] in self._s_endings:
                word = word[:-1]

        # Step 2
        if word[r1_start:][-2:] in {'gd', 'dt', 'gt', 'kt'}:
            word = word[:-1]

        # Step 3
        if word[-4:] == 'igst':
            word = word[:-2]

        _r1 = word[r1_start:]
        repeat_step2 = False
        if _r1[-4:] == 'elig':
            word = word[:-4]
            repeat_step2 = True
        elif _r1[-4:] == 'løst':
            word = word[:-1]
        elif _r1[-3:] in {'lig', 'els'}:
            word = word[:-3]
            repeat_step2 = True
        elif _r1[-2:] == 'ig':
            word = word[:-2]
            repeat_step2 = True

        if repeat_step2:
            if word[r1_start:][-2:] in {'gd', 'dt', 'gt', 'kt'}:
                word = word[:-1]

        # Step 4
        if (
            len(word[r1_start:]) >= 1
            and len(word) >= 2
            and word[-1] == word[-2]
            and word[-1] not in self._vowels
        ):
            word = word[:-1]

        return word

Response: Return Snowball Danish stem.


Instruction:
Implement a Python 3 function for
returning the Snowball German stem.

Response:
def stem(self, word, alternate_vowels=False):
        """Return Snowball German stem.

        Parameters
        ----------
        word : str
            The word to stem
        alternate_vowels : bool
            Composes ae as ä, oe as ö, and ue as ü before running the algorithm

        Returns
        -------
        str
            Word stem

        Examples
        --------
        >>> stmr = SnowballGerman()
        >>> stmr.stem('lesen')
        'les'
        >>> stmr.stem('graues')
        'grau'
        >>> stmr.stem('buchstabieren')
        'buchstabi'

        """
        # lowercase, normalize, and compose
        word = normalize('NFC', word.lower())
        word = word.replace('ß', 'ss')

        if len(word) > 2:
            for i in range(2, len(word)):
                if word[i] in self._vowels and word[i - 2] in self._vowels:
                    if word[i - 1] == 'u':
                        word = word[: i - 1] + 'U' + word[i:]
                    elif word[i - 1] == 'y':
                        word = word[: i - 1] + 'Y' + word[i:]

        if alternate_vowels:
            word = word.replace('ae', 'ä')
            word = word.replace('oe', 'ö')
            word = word.replace('que', 'Q')
            word = word.replace('ue', 'ü')
            word = word.replace('Q', 'que')

        r1_start = max(3, self._sb_r1(word))
        r2_start = self._sb_r2(word)

        # Step 1
        niss_flag = False
        if word[-3:] == 'ern':
            if len(word[r1_start:]) >= 3:
                word = word[:-3]
        elif word[-2:] == 'em':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
        elif word[-2:] == 'er':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
        elif word[-2:] == 'en':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
                niss_flag = True
        elif word[-2:] == 'es':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
                niss_flag = True
        elif word[-1:] == 'e':
            if len(word[r1_start:]) >= 1:
                word = word[:-1]
                niss_flag = True
        elif word[-1:] == 's':
            if (
                len(word[r1_start:]) >= 1
                and len(word) >= 2
                and word[-2] in self._s_endings
            ):
                word = word[:-1]

        if niss_flag and word[-4:] == 'niss':
            word = word[:-1]

        # Step 2
        if word[-3:] == 'est':
            if len(word[r1_start:]) >= 3:
                word = word[:-3]
        elif word[-2:] == 'en':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
        elif word[-2:] == 'er':
            if len(word[r1_start:]) >= 2:
                word = word[:-2]
        elif word[-2:] == 'st':
            if (
                len(word[r1_start:]) >= 2
                and len(word) >= 6
                and word[-3] in self._st_endings
            ):
                word = word[:-2]

        # Step 3
        if word[-4:] == 'isch':
            if len(word[r2_start:]) >= 4 and word[-5] != 'e':
                word = word[:-4]
        elif word[-4:] in {'lich', 'heit'}:
            if len(word[r2_start:]) >= 4:
                word = word[:-4]
                if word[-2:] in {'er', 'en'} and len(word[r1_start:]) >= 2:
                    word = word[:-2]
        elif word[-4:] == 'keit':
            if len(word[r2_start:]) >= 4:
                word = word[:-4]
                if word[-4:] == 'lich' and len(word[r2_start:]) >= 4:
                    word = word[:-4]
                elif word[-2:] == 'ig' and len(word[r2_start:]) >= 2:
                    word = word[:-2]
        elif word[-3:] in {'end', 'ung'}:
            if len(word[r2_start:]) >= 3:
                word = word[:-3]
                if (
                    word[-2:] == 'ig'
                    and len(word[r2_start:]) >= 2
                    and word[-3] != 'e'
                ):
                    word = word[:-2]
        elif word[-2:] in {'ig', 'ik'}:
            if len(word[r2_start:]) >= 2 and word[-3] != 'e':
                word = word[:-2]

        # Change 'Y' and 'U' back to lowercase if survived stemming
        for i in range(0, len(word)):
            if word[i] == 'Y':
                word = word[:i] + 'y' + word[i + 1 :]
            elif word[i] == 'U':
                word = word[:i] + 'u' + word[i + 1 :]

        # Remove umlauts
        _umlauts = dict(zip((ord(_) for _ in 'äöü'), 'aou'))
        word = word.translate(_umlauts)

        return word


Instruction:
Explain what the following Python 3 code does
def dist_abs(self, src, tar, max_offset=5):
        if not src:
            return len(tar)

        if not tar:
            return len(src)

        src_len = len(src)
        tar_len = len(tar)

        src_cur = 0
        tar_cur = 0
        lcss = 0
        local_cs = 0

        while (src_cur < src_len) and (tar_cur < tar_len):
            if src[src_cur] == tar[tar_cur]:
                local_cs += 1
            else:
                lcss += local_cs
                local_cs = 0
                if src_cur != tar_cur:
                    src_cur = tar_cur = max(src_cur, tar_cur)
                for i in range(max_offset):
                    if not (
                        (src_cur + i < src_len) or (tar_cur + i < tar_len)
                    ):
                        break
                    if (src_cur + i < src_len) and (
                        src[src_cur + i] == tar[tar_cur]
                    ):
                        src_cur += i
                        local_cs += 1
                        break
                    if (tar_cur + i < tar_len) and (
                        src[src_cur] == tar[tar_cur + i]
                    ):
                        tar_cur += i
                        local_cs += 1
                        break

            src_cur += 1
            tar_cur += 1

        lcss += local_cs
        return round(max(src_len, tar_len) - lcss)

Response: Return the simplest Sift4 distance between two strings src and tar.


Instruction:
Can you generate the documentation for the following Python 3 function
def typo(src, tar, metric='euclidean', cost=(1, 1, 0.5, 0.5), layout='QWERTY'):
    return Typo().dist_abs(src, tar, metric, cost, layout)

Response: Return the typo distance between two strings.


Instruction:
How would you code a function in Python 3 to
return the normalized typo distance between two strings.

Response:
def dist_typo(
    src, tar, metric='euclidean', cost=(1, 1, 0.5, 0.5), layout='QWERTY'
):
    """Return the normalized typo distance between two strings.

    This is a wrapper for :py:meth:`Typo.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Normalized typo distance

    Examples
    --------
    >>> round(dist_typo('cat', 'hat'), 12)
    0.527046283086
    >>> round(dist_typo('Niall', 'Neil'), 12)
    0.565028142929
    >>> round(dist_typo('Colin', 'Cuilen'), 12)
    0.569035609563
    >>> dist_typo('ATCG', 'TAGC')
    0.625

    """
    return Typo().dist(src, tar, metric, cost, layout)


Instruction:
Make a summary of the following Python 3 code
def sim_typo(
    src, tar, metric='euclidean', cost=(1, 1, 0.5, 0.5), layout='QWERTY'
):
    """Return the normalized typo similarity between two strings.

    This is a wrapper for :py:meth:`Typo.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Normalized typo similarity

    Examples
    --------
    >>> round(sim_typo('cat', 'hat'), 12)
    0.472953716914
    >>> round(sim_typo('Niall', 'Neil'), 12)
    0.434971857071
    >>> round(sim_typo('Colin', 'Cuilen'), 12)
    0.430964390437
    >>> sim_typo('ATCG', 'TAGC')
    0.375

    """
    return Typo().sim(src, tar, metric, cost, layout)

Response: Return the normalized typo similarity between two strings.


Instruction:
Here you have a function in Python 3, explain what it does
def dist_abs(
        self,
        src,
        tar,
        metric='euclidean',
        cost=(1, 1, 0.5, 0.5),
        layout='QWERTY',
    ):
        """Return the typo distance between two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        metric : str
            Supported values include: ``euclidean``, ``manhattan``,
            ``log-euclidean``, and ``log-manhattan``
        cost : tuple
            A 4-tuple representing the cost of the four possible edits:
            inserts, deletes, substitutions, and shift, respectively (by
            default: (1, 1, 0.5, 0.5)) The substitution & shift costs should be
            significantly less than the cost of an insertion & deletion unless
            a log metric is used.
        layout : str
            Name of the keyboard layout to use (Currently supported:
            ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

        Returns
        -------
        float
            Typo distance

        Raises
        ------
        ValueError
            char not found in any keyboard layouts

        Examples
        --------
        >>> cmp = Typo()
        >>> cmp.dist_abs('cat', 'hat')
        1.5811388
        >>> cmp.dist_abs('Niall', 'Neil')
        2.8251407
        >>> cmp.dist_abs('Colin', 'Cuilen')
        3.4142137
        >>> cmp.dist_abs('ATCG', 'TAGC')
        2.5

        >>> cmp.dist_abs('cat', 'hat', metric='manhattan')
        2.0
        >>> cmp.dist_abs('Niall', 'Neil', metric='manhattan')
        3.0
        >>> cmp.dist_abs('Colin', 'Cuilen', metric='manhattan')
        3.5
        >>> cmp.dist_abs('ATCG', 'TAGC', metric='manhattan')
        2.5

        >>> cmp.dist_abs('cat', 'hat', metric='log-manhattan')
        0.804719
        >>> cmp.dist_abs('Niall', 'Neil', metric='log-manhattan')
        2.2424533
        >>> cmp.dist_abs('Colin', 'Cuilen', metric='log-manhattan')
        2.2424533
        >>> cmp.dist_abs('ATCG', 'TAGC', metric='log-manhattan')
        2.3465736

        """
        ins_cost, del_cost, sub_cost, shift_cost = cost

        if src == tar:
            return 0.0
        if not src:
            return len(tar) * ins_cost
        if not tar:
            return len(src) * del_cost

        keyboard = self._keyboard[layout]
        lowercase = {item for sublist in keyboard[0] for item in sublist}
        uppercase = {item for sublist in keyboard[1] for item in sublist}

        def _kb_array_for_char(char):
            """Return the keyboard layout that contains ch.

            Parameters
            ----------
            char : str
                The character to lookup

            Returns
            -------
            tuple
                A keyboard

            Raises
            ------
            ValueError
                char not found in any keyboard layouts

            """
            if char in lowercase:
                return keyboard[0]
            elif char in uppercase:
                return keyboard[1]
            raise ValueError(char + ' not found in any keyboard layouts')

        def _substitution_cost(char1, char2):
            cost = sub_cost
            cost *= metric_dict[metric](char1, char2) + shift_cost * (
                _kb_array_for_char(char1) != _kb_array_for_char(char2)
            )
            return cost

        def _get_char_coord(char, kb_array):
            """Return the row & column of char in the keyboard.

            Parameters
            ----------
            char : str
                The character to search for
            kb_array : tuple of tuples
                The array of key positions

            Returns
            -------
            tuple
                The row & column of the key

            """
            for row in kb_array:  # pragma: no branch
                if char in row:
                    return kb_array.index(row), row.index(char)

        def _euclidean_keyboard_distance(char1, char2):
            row1, col1 = _get_char_coord(char1, _kb_array_for_char(char1))
            row2, col2 = _get_char_coord(char2, _kb_array_for_char(char2))
            return ((row1 - row2) ** 2 + (col1 - col2) ** 2) ** 0.5

        def _manhattan_keyboard_distance(char1, char2):
            row1, col1 = _get_char_coord(char1, _kb_array_for_char(char1))
            row2, col2 = _get_char_coord(char2, _kb_array_for_char(char2))
            return abs(row1 - row2) + abs(col1 - col2)

        def _log_euclidean_keyboard_distance(char1, char2):
            return log(1 + _euclidean_keyboard_distance(char1, char2))

        def _log_manhattan_keyboard_distance(char1, char2):
            return log(1 + _manhattan_keyboard_distance(char1, char2))

        metric_dict = {
            'euclidean': _euclidean_keyboard_distance,
            'manhattan': _manhattan_keyboard_distance,
            'log-euclidean': _log_euclidean_keyboard_distance,
            'log-manhattan': _log_manhattan_keyboard_distance,
        }

        d_mat = np_zeros((len(src) + 1, len(tar) + 1), dtype=np_float32)
        for i in range(len(src) + 1):
            d_mat[i, 0] = i * del_cost
        for j in range(len(tar) + 1):
            d_mat[0, j] = j * ins_cost

        for i in range(len(src)):
            for j in range(len(tar)):
                d_mat[i + 1, j + 1] = min(
                    d_mat[i + 1, j] + ins_cost,  # ins
                    d_mat[i, j + 1] + del_cost,  # del
                    d_mat[i, j]
                    + (
                        _substitution_cost(src[i], tar[j])
                        if src[i] != tar[j]
                        else 0
                    ),  # sub/==
                )

        return d_mat[len(src), len(tar)]

Response: Return the typo distance between two strings.


Instruction:
Here you have a function in Python 3, explain what it does
def dist(
        self,
        src,
        tar,
        metric='euclidean',
        cost=(1, 1, 0.5, 0.5),
        layout='QWERTY',
    ):
        """Return the normalized typo distance between two strings.

        This is typo distance, normalized to [0, 1].

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        metric : str
            Supported values include: ``euclidean``, ``manhattan``,
            ``log-euclidean``, and ``log-manhattan``
        cost : tuple
            A 4-tuple representing the cost of the four possible edits:
            inserts, deletes, substitutions, and shift, respectively (by
            default: (1, 1, 0.5, 0.5)) The substitution & shift costs should be
            significantly less than the cost of an insertion & deletion unless
            a log metric is used.
        layout : str
            Name of the keyboard layout to use (Currently supported:
            ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

        Returns
        -------
        float
            Normalized typo distance

        Examples
        --------
        >>> cmp = Typo()
        >>> round(cmp.dist('cat', 'hat'), 12)
        0.527046283086
        >>> round(cmp.dist('Niall', 'Neil'), 12)
        0.565028142929
        >>> round(cmp.dist('Colin', 'Cuilen'), 12)
        0.569035609563
        >>> cmp.dist('ATCG', 'TAGC')
        0.625

        """
        if src == tar:
            return 0.0
        ins_cost, del_cost = cost[:2]
        return self.dist_abs(src, tar, metric, cost, layout) / (
            max(len(src) * del_cost, len(tar) * ins_cost)
        )

Response: Return the normalized typo distance between two strings.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def manhattan(src, tar, qval=2, normalized=False, alphabet=None):
    return Manhattan().dist_abs(src, tar, qval, normalized, alphabet)

Response: Return the Manhattan distance between two strings.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def dist_manhattan(src, tar, qval=2, alphabet=None):
    return Manhattan().dist(src, tar, qval, alphabet)

Response: Return the normalized Manhattan distance between two strings.


Instruction:
Create a Python 3 function for
returning the normalized Manhattan similarity of two strings.

Response:
def sim_manhattan(src, tar, qval=2, alphabet=None):
    """Return the normalized Manhattan similarity of two strings.

    This is a wrapper for :py:meth:`Manhattan.sim`.

    Parameters
    ----------
    src : str
        Source string (or QGrams/Counter objects) for comparison
    tar : str
        Target string (or QGrams/Counter objects) for comparison
    qval : int
        The length of each q-gram; 0 for non-q-gram version
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The normalized Manhattan similarity

    Examples
    --------
    >>> sim_manhattan('cat', 'hat')
    0.5
    >>> round(sim_manhattan('Niall', 'Neil'), 12)
    0.363636363636
    >>> round(sim_manhattan('Colin', 'Cuilen'), 12)
    0.307692307692
    >>> sim_manhattan('ATCG', 'TAGC')
    0.0

    """
    return Manhattan().sim(src, tar, qval, alphabet)


Instruction:
Here you have a function in Python 3, explain what it does
def sim_jaro_winkler(
    src,
    tar,
    qval=1,
    mode='winkler',
    long_strings=False,
    boost_threshold=0.7,
    scaling_factor=0.1,
):
    """Return the Jaro or Jaro-Winkler similarity of two strings.

    This is a wrapper for :py:meth:`JaroWinkler.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    qval : int
        The length of each q-gram (defaults to 1: character-wise matching)
    mode : str
        Indicates which variant of this distance metric to compute:

            - ``winkler`` -- computes the Jaro-Winkler distance (default) which
              increases the score for matches near the start of the word
            - ``jaro`` -- computes the Jaro distance

    long_strings : bool
        Set to True to "Increase the probability of a match when the number of
        matched characters is large. This option allows for a little more
        tolerance when the strings are large. It is not an appropriate test
        when comparing fixedlength fields such as phone and social security
        numbers." (Used in 'winkler' mode only.)
    boost_threshold : float
        A value between 0 and 1, below which the Winkler boost is not applied
        (defaults to 0.7). (Used in 'winkler' mode only.)
    scaling_factor : float
        A value between 0 and 0.25, indicating by how much to boost scores for
        matching prefixes (defaults to 0.1). (Used in 'winkler' mode only.)

    Returns
    -------
    float
        Jaro or Jaro-Winkler similarity

    Examples
    --------
    >>> round(sim_jaro_winkler('cat', 'hat'), 12)
    0.777777777778
    >>> round(sim_jaro_winkler('Niall', 'Neil'), 12)
    0.805
    >>> round(sim_jaro_winkler('aluminum', 'Catalan'), 12)
    0.60119047619
    >>> round(sim_jaro_winkler('ATCG', 'TAGC'), 12)
    0.833333333333

    >>> round(sim_jaro_winkler('cat', 'hat', mode='jaro'), 12)
    0.777777777778
    >>> round(sim_jaro_winkler('Niall', 'Neil', mode='jaro'), 12)
    0.783333333333
    >>> round(sim_jaro_winkler('aluminum', 'Catalan', mode='jaro'), 12)
    0.60119047619
    >>> round(sim_jaro_winkler('ATCG', 'TAGC', mode='jaro'), 12)
    0.833333333333

    """
    return JaroWinkler().sim(
        src, tar, qval, mode, long_strings, boost_threshold, scaling_factor
    )

Response: Return the Jaro or Jaro - Winkler similarity of two strings.


Instruction:
Can you generate the documentation for the following Python 3 function
def dist_jaro_winkler(
    src,
    tar,
    qval=1,
    mode='winkler',
    long_strings=False,
    boost_threshold=0.7,
    scaling_factor=0.1,
):
    """Return the Jaro or Jaro-Winkler distance between two strings.

    This is a wrapper for :py:meth:`JaroWinkler.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    qval : int
        The length of each q-gram (defaults to 1: character-wise matching)
    mode : str
        Indicates which variant of this distance metric to compute:

            - ``winkler`` -- computes the Jaro-Winkler distance (default) which
              increases the score for matches near the start of the word
            - ``jaro`` -- computes the Jaro distance

    long_strings : bool
        Set to True to "Increase the probability of a match when the number of
        matched characters is large. This option allows for a little more
        tolerance when the strings are large. It is not an appropriate test
        when comparing fixedlength fields such as phone and social security
        numbers." (Used in 'winkler' mode only.)
    boost_threshold : float
        A value between 0 and 1, below which the Winkler boost is not applied
        (defaults to 0.7). (Used in 'winkler' mode only.)
    scaling_factor : float
        A value between 0 and 0.25, indicating by how much to boost scores for
        matching prefixes (defaults to 0.1). (Used in 'winkler' mode only.)

    Returns
    -------
    float
        Jaro or Jaro-Winkler distance

    Examples
    --------
    >>> round(dist_jaro_winkler('cat', 'hat'), 12)
    0.222222222222
    >>> round(dist_jaro_winkler('Niall', 'Neil'), 12)
    0.195
    >>> round(dist_jaro_winkler('aluminum', 'Catalan'), 12)
    0.39880952381
    >>> round(dist_jaro_winkler('ATCG', 'TAGC'), 12)
    0.166666666667

    >>> round(dist_jaro_winkler('cat', 'hat', mode='jaro'), 12)
    0.222222222222
    >>> round(dist_jaro_winkler('Niall', 'Neil', mode='jaro'), 12)
    0.216666666667
    >>> round(dist_jaro_winkler('aluminum', 'Catalan', mode='jaro'), 12)
    0.39880952381
    >>> round(dist_jaro_winkler('ATCG', 'TAGC', mode='jaro'), 12)
    0.166666666667

    """
    return JaroWinkler().dist(
        src, tar, qval, mode, long_strings, boost_threshold, scaling_factor
    )

Response: Return the Jaro or Jaro - Winkler distance between two strings.