Instruction:
Here you have a function in Python 3, explain what it does
def sim(
        self,
        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.

        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 fixed length 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

        Raises
        ------
        ValueError
            Unsupported boost_threshold assignment; boost_threshold must be
            between 0 and 1.
        ValueError
            Unsupported scaling_factor assignment; scaling_factor must be
            between 0 and 0.25.'

        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

        """
        if mode == 'winkler':
            if boost_threshold > 1 or boost_threshold < 0:
                raise ValueError(
                    'Unsupported boost_threshold assignment; '
                    + 'boost_threshold must be between 0 and 1.'
                )
            if scaling_factor > 0.25 or scaling_factor < 0:
                raise ValueError(
                    'Unsupported scaling_factor assignment; '
                    + 'scaling_factor must be between 0 and 0.25.'
                )

        if src == tar:
            return 1.0

        src = QGrams(src.strip(), qval)._ordered_list
        tar = QGrams(tar.strip(), qval)._ordered_list

        lens = len(src)
        lent = len(tar)

        # If either string is blank - return - added in Version 2
        if lens == 0 or lent == 0:
            return 0.0

        if lens > lent:
            search_range = lens
            minv = lent
        else:
            search_range = lent
            minv = lens

        # Zero out the flags
        src_flag = [0] * search_range
        tar_flag = [0] * search_range
        search_range = max(0, search_range // 2 - 1)

        # Looking only within the search range,
        # count and flag the matched pairs.
        num_com = 0
        yl1 = lent - 1
        for i in range(lens):
            low_lim = (i - search_range) if (i >= search_range) else 0
            hi_lim = (i + search_range) if ((i + search_range) <= yl1) else yl1
            for j in range(low_lim, hi_lim + 1):
                if (tar_flag[j] == 0) and (tar[j] == src[i]):
                    tar_flag[j] = 1
                    src_flag[i] = 1
                    num_com += 1
                    break

        # If no characters in common - return
        if num_com == 0:
            return 0.0

        # Count the number of transpositions
        k = n_trans = 0
        for i in range(lens):
            if src_flag[i] != 0:
                j = 0
                for j in range(k, lent):  # pragma: no branch
                    if tar_flag[j] != 0:
                        k = j + 1
                        break
                if src[i] != tar[j]:
                    n_trans += 1
        n_trans //= 2

        # Main weight computation for Jaro distance
        weight = (
            num_com / lens + num_com / lent + (num_com - n_trans) / num_com
        )
        weight /= 3.0

        # Continue to boost the weight if the strings are similar
        # This is the Winkler portion of Jaro-Winkler distance
        if mode == 'winkler' and weight > boost_threshold:

            # Adjust for having up to the first 4 characters in common
            j = 4 if (minv >= 4) else minv
            i = 0
            while (i < j) and (src[i] == tar[i]):
                i += 1
            weight += i * scaling_factor * (1.0 - weight)

            # Optionally adjust for long strings.

            # After agreeing beginning chars, at least two more must agree and
            # the agreeing characters must be > .5 of remaining characters.
            if (
                long_strings
                and (minv > 4)
                and (num_com > i + 1)
                and (2 * num_com >= minv + i)
            ):
                weight += (1.0 - weight) * (
                    (num_com - i - 1) / (lens + lent - i * 2 + 2)
                )

        return weight

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


Instruction:
Given the following Python 3 function, write the documentation
def hamming(src, tar, diff_lens=True):
    return Hamming().dist_abs(src, tar, diff_lens)

Response: Returns the Hamming distance between two strings.


Instruction:
Here you have a function in Python 3, explain what it does
def dist_hamming(src, tar, diff_lens=True):
    return Hamming().dist(src, tar, diff_lens)

Response: Return the normalized Hamming distance between two strings.


Instruction:
Can you generate the documentation for the following Python 3 function
def sim_hamming(src, tar, diff_lens=True):
    return Hamming().sim(src, tar, diff_lens)

Response: Return the normalized Hamming similarity of two strings.


Instruction:
Explain what the following Python 3 code does
def dist_abs(self, src, tar, diff_lens=True):
        if not diff_lens and len(src) != len(tar):
            raise ValueError(
                'Undefined for sequences of unequal length; set diff_lens '
                + 'to True for Hamming distance between strings of unequal '
                + 'lengths.'
            )

        hdist = 0
        if diff_lens:
            hdist += abs(len(src) - len(tar))
        hdist += sum(c1 != c2 for c1, c2 in zip(src, tar))

        return hdist

Response: Return the Hamming distance between two strings.


Instruction:
Make a summary of the following Python 3 code
def dist(self, src, tar, diff_lens=True):
        if src == tar:
            return 0.0
        return self.dist_abs(src, tar, diff_lens) / max(len(src), len(tar))

Response: Return the normalized Hamming distance between two strings.


Instruction:
Implement a Python 3 function for
returning the Metaphone code for a word.

Response:
def encode(self, word, max_length=-1):
        """Return the Metaphone code for a word.

        Based on Lawrence Philips' Pick BASIC code from 1990
        :cite:`Philips:1990`, as described in :cite:`Philips:1990b`.
        This incorporates some corrections to the above code, particularly
        some of those suggested by Michael Kuhn in :cite:`Kuhn:1995`.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The maximum length of the returned Metaphone code (defaults to 64,
            but in Philips' original implementation this was 4)

        Returns
        -------
        str
            The Metaphone value

        Examples
        --------
        >>> pe = Metaphone()
        >>> pe.encode('Christopher')
        'KRSTFR'
        >>> pe.encode('Niall')
        'NL'
        >>> pe.encode('Smith')
        'SM0'
        >>> pe.encode('Schmidt')
        'SKMTT'

        """
        # Require a max_length of at least 4
        if max_length != -1:
            max_length = max(4, max_length)
        else:
            max_length = 64

        # As in variable sound--those modified by adding an "h"
        ename = ''.join(c for c in word.upper() if c.isalnum())
        ename = ename.replace('ß', 'SS')

        # Delete non-alphanumeric characters and make all caps
        if not ename:
            return ''
        if ename[0:2] in {'PN', 'AE', 'KN', 'GN', 'WR'}:
            ename = ename[1:]
        elif ename[0] == 'X':
            ename = 'S' + ename[1:]
        elif ename[0:2] == 'WH':
            ename = 'W' + ename[2:]

        # Convert to metaphone
        elen = len(ename) - 1
        metaph = ''
        for i in range(len(ename)):
            if len(metaph) >= max_length:
                break
            if (
                ename[i] not in {'G', 'T'}
                and i > 0
                and ename[i - 1] == ename[i]
            ):
                continue

            if ename[i] in self._uc_v_set and i == 0:
                metaph = ename[i]

            elif ename[i] == 'B':
                if i != elen or ename[i - 1] != 'M':
                    metaph += ename[i]

            elif ename[i] == 'C':
                if not (
                    i > 0
                    and ename[i - 1] == 'S'
                    and ename[i + 1 : i + 2] in self._frontv
                ):
                    if ename[i + 1 : i + 3] == 'IA':
                        metaph += 'X'
                    elif ename[i + 1 : i + 2] in self._frontv:
                        metaph += 'S'
                    elif i > 0 and ename[i - 1 : i + 2] == 'SCH':
                        metaph += 'K'
                    elif ename[i + 1 : i + 2] == 'H':
                        if (
                            i == 0
                            and i + 1 < elen
                            and ename[i + 2 : i + 3] not in self._uc_v_set
                        ):
                            metaph += 'K'
                        else:
                            metaph += 'X'
                    else:
                        metaph += 'K'

            elif ename[i] == 'D':
                if (
                    ename[i + 1 : i + 2] == 'G'
                    and ename[i + 2 : i + 3] in self._frontv
                ):
                    metaph += 'J'
                else:
                    metaph += 'T'

            elif ename[i] == 'G':
                if ename[i + 1 : i + 2] == 'H' and not (
                    i + 1 == elen or ename[i + 2 : i + 3] not in self._uc_v_set
                ):
                    continue
                elif i > 0 and (
                    (i + 1 == elen and ename[i + 1] == 'N')
                    or (i + 3 == elen and ename[i + 1 : i + 4] == 'NED')
                ):
                    continue
                elif (
                    i - 1 > 0
                    and i + 1 <= elen
                    and ename[i - 1] == 'D'
                    and ename[i + 1] in self._frontv
                ):
                    continue
                elif ename[i + 1 : i + 2] == 'G':
                    continue
                elif ename[i + 1 : i + 2] in self._frontv:
                    if i == 0 or ename[i - 1] != 'G':
                        metaph += 'J'
                    else:
                        metaph += 'K'
                else:
                    metaph += 'K'

            elif ename[i] == 'H':
                if (
                    i > 0
                    and ename[i - 1] in self._uc_v_set
                    and ename[i + 1 : i + 2] not in self._uc_v_set
                ):
                    continue
                elif i > 0 and ename[i - 1] in self._varson:
                    continue
                else:
                    metaph += 'H'

            elif ename[i] in {'F', 'J', 'L', 'M', 'N', 'R'}:
                metaph += ename[i]

            elif ename[i] == 'K':
                if i > 0 and ename[i - 1] == 'C':
                    continue
                else:
                    metaph += 'K'

            elif ename[i] == 'P':
                if ename[i + 1 : i + 2] == 'H':
                    metaph += 'F'
                else:
                    metaph += 'P'

            elif ename[i] == 'Q':
                metaph += 'K'

            elif ename[i] == 'S':
                if (
                    i > 0
                    and i + 2 <= elen
                    and ename[i + 1] == 'I'
                    and ename[i + 2] in 'OA'
                ):
                    metaph += 'X'
                elif ename[i + 1 : i + 2] == 'H':
                    metaph += 'X'
                else:
                    metaph += 'S'

            elif ename[i] == 'T':
                if (
                    i > 0
                    and i + 2 <= elen
                    and ename[i + 1] == 'I'
                    and ename[i + 2] in {'A', 'O'}
                ):
                    metaph += 'X'
                elif ename[i + 1 : i + 2] == 'H':
                    metaph += '0'
                elif ename[i + 1 : i + 3] != 'CH':
                    if ename[i - 1 : i] != 'T':
                        metaph += 'T'

            elif ename[i] == 'V':
                metaph += 'F'

            elif ename[i] in 'WY':
                if ename[i + 1 : i + 2] in self._uc_v_set:
                    metaph += ename[i]

            elif ename[i] == 'X':
                metaph += 'KS'

            elif ename[i] == 'Z':
                metaph += 'S'

        return metaph


Instruction:
How would you explain what the following Python 3 function does
def pshp_soundex_last(lname, max_length=4, german=False):
    return PSHPSoundexLast().encode(lname, max_length, german)

Response: This function returns the PSHP Soundex Last code for a given last name.


Instruction:
Given the following Python 3 function, write the documentation
def encode(self, lname, max_length=4, german=False):
        lname = unicode_normalize('NFKD', text_type(lname.upper()))
        lname = lname.replace('ß', 'SS')
        lname = ''.join(c for c in lname if c in self._uc_set)

        # A. Prefix treatment
        if lname[:3] == 'VON' or lname[:3] == 'VAN':
            lname = lname[3:].strip()

        # The rule implemented below says "MC, MAC become 1". I believe it
        # meant to say they become M except in German data (where superscripted
        # 1 indicates "except in German data"). It doesn't make sense for them
        # to become 1 (BPFV -> 1) or to apply outside German. Unfortunately,
        # both articles have this error(?).
        if not german:
            if lname[:3] == 'MAC':
                lname = 'M' + lname[3:]
            elif lname[:2] == 'MC':
                lname = 'M' + lname[2:]

        # The non-German-only rule to strip ' is unnecessary due to filtering

        if lname[:1] in {'E', 'I', 'O', 'U'}:
            lname = 'A' + lname[1:]
        elif lname[:2] in {'GE', 'GI', 'GY'}:
            lname = 'J' + lname[1:]
        elif lname[:2] in {'CE', 'CI', 'CY'}:
            lname = 'S' + lname[1:]
        elif lname[:3] == 'CHR':
            lname = 'K' + lname[1:]
        elif lname[:1] == 'C' and lname[:2] != 'CH':
            lname = 'K' + lname[1:]

        if lname[:2] == 'KN':
            lname = 'N' + lname[1:]
        elif lname[:2] == 'PH':
            lname = 'F' + lname[1:]
        elif lname[:3] in {'WIE', 'WEI'}:
            lname = 'V' + lname[1:]

        if german and lname[:1] in {'W', 'M', 'Y', 'Z'}:
            lname = {'W': 'V', 'M': 'N', 'Y': 'J', 'Z': 'S'}[lname[0]] + lname[
                1:
            ]

        code = lname[:1]

        # B. Postfix treatment
        if german:  # moved from end of postfix treatment due to blocking
            if lname[-3:] == 'TES':
                lname = lname[:-3]
            elif lname[-2:] == 'TS':
                lname = lname[:-2]
            if lname[-3:] == 'TZE':
                lname = lname[:-3]
            elif lname[-2:] == 'ZE':
                lname = lname[:-2]
            if lname[-1:] == 'Z':
                lname = lname[:-1]
            elif lname[-2:] == 'TE':
                lname = lname[:-2]

        if lname[-1:] == 'R':
            lname = lname[:-1] + 'N'
        elif lname[-2:] in {'SE', 'CE'}:
            lname = lname[:-2]
        if lname[-2:] == 'SS':
            lname = lname[:-2]
        elif lname[-1:] == 'S':
            lname = lname[:-1]

        if not german:
            l5_repl = {'STOWN': 'SAWON', 'MPSON': 'MASON'}
            l4_repl = {
                'NSEN': 'ASEN',
                'MSON': 'ASON',
                'STEN': 'SAEN',
                'STON': 'SAON',
            }
            if lname[-5:] in l5_repl:
                lname = lname[:-5] + l5_repl[lname[-5:]]
            elif lname[-4:] in l4_repl:
                lname = lname[:-4] + l4_repl[lname[-4:]]

        if lname[-2:] in {'NG', 'ND'}:
            lname = lname[:-1]
        if not german and lname[-3:] in {'GAN', 'GEN'}:
            lname = lname[:-3] + 'A' + lname[-2:]

        # C. Infix Treatment
        lname = lname.replace('CK', 'C')
        lname = lname.replace('SCH', 'S')
        lname = lname.replace('DT', 'T')
        lname = lname.replace('ND', 'N')
        lname = lname.replace('NG', 'N')
        lname = lname.replace('LM', 'M')
        lname = lname.replace('MN', 'M')
        lname = lname.replace('WIE', 'VIE')
        lname = lname.replace('WEI', 'VEI')

        # D. Soundexing
        # code for X & Y are unspecified, but presumably are 2 & 0

        lname = lname.translate(self._trans)
        lname = self._delete_consecutive_repeats(lname)

        code += lname[1:]
        code = code.replace('0', '')  # rule 1

        if max_length != -1:
            if len(code) < max_length:
                code += '0' * (max_length - len(code))
            else:
                code = code[:max_length]

        return code

Response: This function encodes a last name into a set of PSHP soundex and viewex codes.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def fingerprint(self, word):
        word = unicode_normalize('NFKD', text_type(word.upper()))
        word = ''.join(c for c in word if c in self._letters)
        start = word[0:1]
        consonant_part = ''
        vowel_part = ''

        # add consonants & vowels to to separate strings
        # (omitting the first char & duplicates)
        for char in word[1:]:
            if char != start:
                if char in self._vowels:
                    if char not in vowel_part:
                        vowel_part += char
                elif char not in consonant_part:
                    consonant_part += char
        # return the first char followed by consonants followed by vowels
        return start + consonant_part + vowel_part

Response: Return the skeleton key for the given word.


Instruction:
Here you have a function in Python 3, explain what it does
def nysiis(word, max_length=6, modified=False):
    return NYSIIS().encode(word, max_length, modified)

Response: Return the NYSIIS code for a word.


Instruction:
Implement a Python 3 function for
encoding a string into a NYSIIS code.

Response:
def encode(self, word, max_length=6, modified=False):
        """Return the NYSIIS code for a word.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The maximum length (default 6) of the code to return
        modified : bool
            Indicates whether to use USDA modified NYSIIS

        Returns
        -------
        str
            The NYSIIS value

        Examples
        --------
        >>> pe = NYSIIS()
        >>> pe.encode('Christopher')
        'CRASTA'
        >>> pe.encode('Niall')
        'NAL'
        >>> pe.encode('Smith')
        'SNAT'
        >>> pe.encode('Schmidt')
        'SNAD'

        >>> pe.encode('Christopher', max_length=-1)
        'CRASTAFAR'

        >>> pe.encode('Christopher', max_length=8, modified=True)
        'CRASTAFA'
        >>> pe.encode('Niall', max_length=8, modified=True)
        'NAL'
        >>> pe.encode('Smith', max_length=8, modified=True)
        'SNAT'
        >>> pe.encode('Schmidt', max_length=8, modified=True)
        'SNAD'

        """
        # Require a max_length of at least 6
        if max_length > -1:
            max_length = max(6, max_length)

        word = ''.join(c for c in word.upper() if c.isalpha())
        word = word.replace('ß', 'SS')

        # exit early if there are no alphas
        if not word:
            return ''

        original_first_char = word[0]

        if word[:3] == 'MAC':
            word = 'MCC' + word[3:]
        elif word[:2] == 'KN':
            word = 'NN' + word[2:]
        elif word[:1] == 'K':
            word = 'C' + word[1:]
        elif word[:2] in {'PH', 'PF'}:
            word = 'FF' + word[2:]
        elif word[:3] == 'SCH':
            word = 'SSS' + word[3:]
        elif modified:
            if word[:2] == 'WR':
                word = 'RR' + word[2:]
            elif word[:2] == 'RH':
                word = 'RR' + word[2:]
            elif word[:2] == 'DG':
                word = 'GG' + word[2:]
            elif word[:1] in self._uc_v_set:
                word = 'A' + word[1:]

        if modified and word[-1:] in {'S', 'Z'}:
            word = word[:-1]

        if (
            word[-2:] == 'EE'
            or word[-2:] == 'IE'
            or (modified and word[-2:] == 'YE')
        ):
            word = word[:-2] + 'Y'
        elif word[-2:] in {'DT', 'RT', 'RD'}:
            word = word[:-2] + 'D'
        elif word[-2:] in {'NT', 'ND'}:
            word = word[:-2] + ('N' if modified else 'D')
        elif modified:
            if word[-2:] == 'IX':
                word = word[:-2] + 'ICK'
            elif word[-2:] == 'EX':
                word = word[:-2] + 'ECK'
            elif word[-2:] in {'JR', 'SR'}:
                return 'ERROR'

        key = word[:1]

        skip = 0
        for i in range(1, len(word)):
            if i >= len(word):
                continue
            elif skip:
                skip -= 1
                continue
            elif word[i : i + 2] == 'EV':
                word = word[:i] + 'AF' + word[i + 2 :]
                skip = 1
            elif word[i] in self._uc_v_set:
                word = word[:i] + 'A' + word[i + 1 :]
            elif modified and i != len(word) - 1 and word[i] == 'Y':
                word = word[:i] + 'A' + word[i + 1 :]
            elif word[i] == 'Q':
                word = word[:i] + 'G' + word[i + 1 :]
            elif word[i] == 'Z':
                word = word[:i] + 'S' + word[i + 1 :]
            elif word[i] == 'M':
                word = word[:i] + 'N' + word[i + 1 :]
            elif word[i : i + 2] == 'KN':
                word = word[:i] + 'N' + word[i + 2 :]
            elif word[i] == 'K':
                word = word[:i] + 'C' + word[i + 1 :]
            elif modified and i == len(word) - 3 and word[i : i + 3] == 'SCH':
                word = word[:i] + 'SSA'
                skip = 2
            elif word[i : i + 3] == 'SCH':
                word = word[:i] + 'SSS' + word[i + 3 :]
                skip = 2
            elif modified and i == len(word) - 2 and word[i : i + 2] == 'SH':
                word = word[:i] + 'SA'
                skip = 1
            elif word[i : i + 2] == 'SH':
                word = word[:i] + 'SS' + word[i + 2 :]
                skip = 1
            elif word[i : i + 2] == 'PH':
                word = word[:i] + 'FF' + word[i + 2 :]
                skip = 1
            elif modified and word[i : i + 3] == 'GHT':
                word = word[:i] + 'TTT' + word[i + 3 :]
                skip = 2
            elif modified and word[i : i + 2] == 'DG':
                word = word[:i] + 'GG' + word[i + 2 :]
                skip = 1
            elif modified and word[i : i + 2] == 'WR':
                word = word[:i] + 'RR' + word[i + 2 :]
                skip = 1
            elif word[i] == 'H' and (
                word[i - 1] not in self._uc_v_set
                or word[i + 1 : i + 2] not in self._uc_v_set
            ):
                word = word[:i] + word[i - 1] + word[i + 1 :]
            elif word[i] == 'W' and word[i - 1] in self._uc_v_set:
                word = word[:i] + word[i - 1] + word[i + 1 :]

            if word[i : i + skip + 1] != key[-1:]:
                key += word[i : i + skip + 1]

        key = self._delete_consecutive_repeats(key)

        if key[-1:] == 'S':
            key = key[:-1]
        if key[-2:] == 'AY':
            key = key[:-2] + 'Y'
        if key[-1:] == 'A':
            key = key[:-1]
        if modified and key[:1] == 'A':
            key = original_first_char + key[1:]

        if max_length > 0:
            key = key[:max_length]

        return key


Instruction:
Can you tell what is the following Python 3 function doing
def chebyshev(src, tar, qval=2, alphabet=None):
    return Chebyshev().dist_abs(src, tar, qval, alphabet)

Response: r Return the Chebyshev distance between two strings.


Instruction:
Explain what the following Python 3 code does
def dist_abs(self, src, tar, qval=2, alphabet=None):
        return super(self.__class__, self).dist_abs(
            src, tar, qval, float('inf'), False, alphabet
        )

Response: Return the Chebyshev distance between two strings.


Instruction:
Can you tell what is the following Python 3 function doing
def mean_pairwise_similarity(
    collection, metric=sim, mean_func=hmean, symmetric=False
):
    """Calculate the mean pairwise similarity of a collection of strings.

    Takes the mean of the pairwise similarity between each member of a
    collection, optionally in both directions (for asymmetric similarity
    metrics.

    Parameters
    ----------
    collection : list
        A collection of terms or a string that can be split
    metric : function
        A similarity metric function
    mean_func : function
        A mean function that takes a list of values and returns a float
    symmetric : bool
        Set to True if all pairwise similarities should be calculated in both
        directions

    Returns
    -------
    float
        The mean pairwise similarity of a collection of strings

    Raises
    ------
    ValueError
        mean_func must be a function
    ValueError
        metric must be a function
    ValueError
        collection is neither a string nor iterable type
    ValueError
        collection has fewer than two members

    Examples
    --------
    >>> round(mean_pairwise_similarity(['Christopher', 'Kristof',
    ... 'Christobal']), 12)
    0.519801980198
    >>> round(mean_pairwise_similarity(['Niall', 'Neal', 'Neil']), 12)
    0.545454545455

    """
    if not callable(mean_func):
        raise ValueError('mean_func must be a function')
    if not callable(metric):
        raise ValueError('metric must be a function')

    if hasattr(collection, 'split'):
        collection = collection.split()
    if not hasattr(collection, '__iter__'):
        raise ValueError('collection is neither a string nor iterable type')
    elif len(collection) < 2:
        raise ValueError('collection has fewer than two members')

    collection = list(collection)

    pairwise_values = []

    for i in range(len(collection)):
        for j in range(i + 1, len(collection)):
            pairwise_values.append(metric(collection[i], collection[j]))
            if symmetric:
                pairwise_values.append(metric(collection[j], collection[i]))

    return mean_func(pairwise_values)

Response: Calculates the mean pairwise similarity between each member of a list of strings.


Instruction:
Create a Python 3 function for
calculating the pairwise similarity statistics of a collection of strings.

Response:
def pairwise_similarity_statistics(
    src_collection,
    tar_collection,
    metric=sim,
    mean_func=amean,
    symmetric=False,
):
    """Calculate the pairwise similarity statistics a collection of strings.

    Calculate pairwise similarities among members of two collections,
    returning the maximum, minimum, mean (according to a supplied function,
    arithmetic mean, by default), and (population) standard deviation
    of those similarities.

    Parameters
    ----------
    src_collection : list
        A collection of terms or a string that can be split
    tar_collection : list
        A collection of terms or a string that can be split
    metric : function
        A similarity metric function
    mean_func : function
        A mean function that takes a list of values and returns a float
    symmetric : bool
        Set to True if all pairwise similarities should be calculated in both
        directions

    Returns
    -------
    tuple
        The max, min, mean, and standard deviation of similarities

    Raises
    ------
    ValueError
        mean_func must be a function
    ValueError
        metric must be a function
    ValueError
        src_collection is neither a string nor iterable
    ValueError
        tar_collection is neither a string nor iterable

    Example
    -------
    >>> tuple(round(_, 12) for _ in pairwise_similarity_statistics(
    ... ['Christopher', 'Kristof', 'Christobal'], ['Niall', 'Neal', 'Neil']))
    (0.2, 0.0, 0.118614718615, 0.075070477184)

    """
    if not callable(mean_func):
        raise ValueError('mean_func must be a function')
    if not callable(metric):
        raise ValueError('metric must be a function')

    if hasattr(src_collection, 'split'):
        src_collection = src_collection.split()
    if not hasattr(src_collection, '__iter__'):
        raise ValueError('src_collection is neither a string nor iterable')

    if hasattr(tar_collection, 'split'):
        tar_collection = tar_collection.split()
    if not hasattr(tar_collection, '__iter__'):
        raise ValueError('tar_collection is neither a string nor iterable')

    src_collection = list(src_collection)
    tar_collection = list(tar_collection)

    pairwise_values = []

    for src in src_collection:
        for tar in tar_collection:
            pairwise_values.append(metric(src, tar))
            if symmetric:
                pairwise_values.append(metric(tar, src))

    return (
        max(pairwise_values),
        min(pairwise_values),
        mean_func(pairwise_values),
        std(pairwise_values, mean_func, 0),
    )


Instruction:
Can you generate the documentation for the following Python 3 function
def stem(self, word, early_english=False):
        # lowercase, normalize, and compose
        word = normalize('NFC', text_type(word.lower()))
        # replace apostrophe-like characters with U+0027, per
        # http://snowball.tartarus.org/texts/apostrophe.html
        word = word.replace('’', '\'')
        word = word.replace('’', '\'')

        # Exceptions 1
        if word in self._exception1dict:
            return self._exception1dict[word]
        elif word in self._exception1set:
            return word

        # Return word if stem is shorter than 3
        if len(word) < 3:
            return word

        # Remove initial ', if present.
        while word and word[0] == '\'':
            word = word[1:]
            # Return word if stem is shorter than 2
            if len(word) < 2:
                return word

        # Re-map vocalic Y to y (Y will be C, y will be V)
        if word[0] == 'y':
            word = 'Y' + word[1:]
        for i in range(1, len(word)):
            if word[i] == 'y' and word[i - 1] in self._vowels:
                word = word[:i] + 'Y' + word[i + 1 :]

        r1_start = self._sb_r1(word, self._r1_prefixes)
        r2_start = self._sb_r2(word, self._r1_prefixes)

        # Step 0
        if word[-3:] == '\'s\'':
            word = word[:-3]
        elif word[-2:] == '\'s':
            word = word[:-2]
        elif word[-1:] == '\'':
            word = word[:-1]
        # Return word if stem is shorter than 2
        if len(word) < 3:
            return word

        # Step 1a
        if word[-4:] == 'sses':
            word = word[:-2]
        elif word[-3:] in {'ied', 'ies'}:
            if len(word) > 4:
                word = word[:-2]
            else:
                word = word[:-1]
        elif word[-2:] in {'us', 'ss'}:
            pass
        elif word[-1] == 's':
            if self._sb_has_vowel(word[:-2]):
                word = word[:-1]

        # Exceptions 2
        if word in self._exception2set:
            return word

        # Step 1b
        step1b_flag = False
        if word[-5:] == 'eedly':
            if len(word[r1_start:]) >= 5:
                word = word[:-3]
        elif word[-5:] == 'ingly':
            if self._sb_has_vowel(word[:-5]):
                word = word[:-5]
                step1b_flag = True
        elif word[-4:] == 'edly':
            if self._sb_has_vowel(word[:-4]):
                word = word[:-4]
                step1b_flag = True
        elif word[-3:] == 'eed':
            if len(word[r1_start:]) >= 3:
                word = word[:-1]
        elif word[-3:] == 'ing':
            if self._sb_has_vowel(word[:-3]):
                word = word[:-3]
                step1b_flag = True
        elif word[-2:] == 'ed':
            if self._sb_has_vowel(word[:-2]):
                word = word[:-2]
                step1b_flag = True
        elif early_english:
            if word[-3:] == 'est':
                if self._sb_has_vowel(word[:-3]):
                    word = word[:-3]
                    step1b_flag = True
            elif word[-3:] == 'eth':
                if self._sb_has_vowel(word[:-3]):
                    word = word[:-3]
                    step1b_flag = True

        if step1b_flag:
            if word[-2:] in {'at', 'bl', 'iz'}:
                word += 'e'
            elif word[-2:] in self._doubles:
                word = word[:-1]
            elif self._sb_short_word(word, self._r1_prefixes):
                word += 'e'

        # Step 1c
        if (
            len(word) > 2
            and word[-1] in {'Y', 'y'}
            and word[-2] not in self._vowels
        ):
            word = word[:-1] + 'i'

        # Step 2
        if word[-2] == 'a':
            if word[-7:] == 'ational':
                if len(word[r1_start:]) >= 7:
                    word = word[:-5] + 'e'
            elif word[-6:] == 'tional':
                if len(word[r1_start:]) >= 6:
                    word = word[:-2]
        elif word[-2] == 'c':
            if word[-4:] in {'enci', 'anci'}:
                if len(word[r1_start:]) >= 4:
                    word = word[:-1] + 'e'
        elif word[-2] == 'e':
            if word[-4:] == 'izer':
                if len(word[r1_start:]) >= 4:
                    word = word[:-1]
        elif word[-2] == 'g':
            if word[-3:] == 'ogi':
                if (
                    r1_start >= 1
                    and len(word[r1_start:]) >= 3
                    and word[-4] == 'l'
                ):
                    word = word[:-1]
        elif word[-2] == 'l':
            if word[-6:] == 'lessli':
                if len(word[r1_start:]) >= 6:
                    word = word[:-2]
            elif word[-5:] in {'entli', 'fulli', 'ousli'}:
                if len(word[r1_start:]) >= 5:
                    word = word[:-2]
            elif word[-4:] == 'abli':
                if len(word[r1_start:]) >= 4:
                    word = word[:-1] + 'e'
            elif word[-4:] == 'alli':
                if len(word[r1_start:]) >= 4:
                    word = word[:-2]
            elif word[-3:] == 'bli':
                if len(word[r1_start:]) >= 3:
                    word = word[:-1] + 'e'
            elif word[-2:] == 'li':
                if (
                    r1_start >= 1
                    and len(word[r1_start:]) >= 2
                    and word[-3] in self._li
                ):
                    word = word[:-2]
        elif word[-2] == 'o':
            if word[-7:] == 'ization':
                if len(word[r1_start:]) >= 7:
                    word = word[:-5] + 'e'
            elif word[-5:] == 'ation':
                if len(word[r1_start:]) >= 5:
                    word = word[:-3] + 'e'
            elif word[-4:] == 'ator':
                if len(word[r1_start:]) >= 4:
                    word = word[:-2] + 'e'
        elif word[-2] == 's':
            if word[-7:] in {'fulness', 'ousness', 'iveness'}:
                if len(word[r1_start:]) >= 7:
                    word = word[:-4]
            elif word[-5:] == 'alism':
                if len(word[r1_start:]) >= 5:
                    word = word[:-3]
        elif word[-2] == 't':
            if word[-6:] == 'biliti':
                if len(word[r1_start:]) >= 6:
                    word = word[:-5] + 'le'
            elif word[-5:] == 'aliti':
                if len(word[r1_start:]) >= 5:
                    word = word[:-3]
            elif word[-5:] == 'iviti':
                if len(word[r1_start:]) >= 5:
                    word = word[:-3] + 'e'

        # Step 3
        if word[-7:] == 'ational':
            if len(word[r1_start:]) >= 7:
                word = word[:-5] + 'e'
        elif word[-6:] == 'tional':
            if len(word[r1_start:]) >= 6:
                word = word[:-2]
        elif word[-5:] in {'alize', 'icate', 'iciti'}:
            if len(word[r1_start:]) >= 5:
                word = word[:-3]
        elif word[-5:] == 'ative':
            if len(word[r2_start:]) >= 5:
                word = word[:-5]
        elif word[-4:] == 'ical':
            if len(word[r1_start:]) >= 4:
                word = word[:-2]
        elif word[-4:] == 'ness':
            if len(word[r1_start:]) >= 4:
                word = word[:-4]
        elif word[-3:] == 'ful':
            if len(word[r1_start:]) >= 3:
                word = word[:-3]

        # Step 4
        for suffix in (
            'ement',
            'ance',
            'ence',
            'able',
            'ible',
            'ment',
            'ant',
            'ent',
            'ism',
            'ate',
            'iti',
            'ous',
            'ive',
            'ize',
            'al',
            'er',
            'ic',
        ):
            if word[-len(suffix) :] == suffix:
                if len(word[r2_start:]) >= len(suffix):
                    word = word[: -len(suffix)]
                break
        else:
            if word[-3:] == 'ion':
                if (
                    len(word[r2_start:]) >= 3
                    and len(word) >= 4
                    and word[-4] in tuple('st')
                ):
                    word = word[:-3]

        # Step 5
        if word[-1] == 'e':
            if len(word[r2_start:]) >= 1 or (
                len(word[r1_start:]) >= 1
                and not self._sb_ends_in_short_syllable(word[:-1])
            ):
                word = word[:-1]
        elif word[-1] == 'l':
            if len(word[r2_start:]) >= 1 and word[-2] == 'l':
                word = word[:-1]

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

        return word

Response: Returns the Porter2 stem.


Instruction:
Implement a function in Python 3 to
return the Synoname toolcode for the given name.

Response:
def synoname_toolcode(lname, fname='', qual='', normalize=0):
    """Build the Synoname toolcode.

    This is a wrapper for :py:meth:`SynonameToolcode.fingerprint`.

    Parameters
    ----------
    lname : str
        Last name
    fname : str
        First name (can be blank)
    qual : str
        Qualifier
    normalize : int
        Normalization mode (0, 1, or 2)

    Returns
    -------
    tuple
        The transformed names and the synoname toolcode

    Examples
    --------
    >>> synoname_toolcode('hat')
    ('hat', '', '0000000003$$h')
    >>> synoname_toolcode('niall')
    ('niall', '', '0000000005$$n')
    >>> synoname_toolcode('colin')
    ('colin', '', '0000000005$$c')
    >>> synoname_toolcode('atcg')
    ('atcg', '', '0000000004$$a')
    >>> synoname_toolcode('entreatment')
    ('entreatment', '', '0000000011$$e')

    >>> synoname_toolcode('Ste.-Marie', 'Count John II', normalize=2)
    ('ste.-marie ii', 'count john', '0200491310$015b049a127c$smcji')
    >>> synoname_toolcode('Michelangelo IV', '', 'Workshop of')
    ('michelangelo iv', '', '3000550015$055b$mi')

    """
    return SynonameToolcode().fingerprint(lname, fname, qual, normalize)


Instruction:
How would you code a function in Python 3 to
return the synoname toolcode for a given set of names.

Response:
def fingerprint(self, lname, fname='', qual='', normalize=0):
        """Build the Synoname toolcode.

        Parameters
        ----------
        lname : str
            Last name
        fname : str
            First name (can be blank)
        qual : str
            Qualifier
        normalize : int
            Normalization mode (0, 1, or 2)

        Returns
        -------
        tuple
            The transformed names and the synoname toolcode

        Examples
        --------
        >>> st = SynonameToolcode()
        >>> st.fingerprint('hat')
        ('hat', '', '0000000003$$h')
        >>> st.fingerprint('niall')
        ('niall', '', '0000000005$$n')
        >>> st.fingerprint('colin')
        ('colin', '', '0000000005$$c')
        >>> st.fingerprint('atcg')
        ('atcg', '', '0000000004$$a')
        >>> st.fingerprint('entreatment')
        ('entreatment', '', '0000000011$$e')

        >>> st.fingerprint('Ste.-Marie', 'Count John II', normalize=2)
        ('ste.-marie ii', 'count john', '0200491310$015b049a127c$smcji')
        >>> st.fingerprint('Michelangelo IV', '', 'Workshop of')
        ('michelangelo iv', '', '3000550015$055b$mi')

        """
        lname = lname.lower()
        fname = fname.lower()
        qual = qual.lower()

        # Start with the basic code
        toolcode = ['0', '0', '0', '000', '00', '00', '$', '', '$', '']

        full_name = ' '.join((lname, fname))

        if qual in self._qual_3:
            toolcode[0] = '3'
        elif qual in self._qual_2:
            toolcode[0] = '2'
        elif qual in self._qual_1:
            toolcode[0] = '1'

        # Fill field 1 (punctuation)
        if '.' in full_name:
            toolcode[1] = '2'
        else:
            for punct in ',-/:;"&\'()!{|}?$%*+<=>[\\]^_`~':
                if punct in full_name:
                    toolcode[1] = '1'
                    break

        elderyounger = ''  # save elder/younger for possible movement later
        for gen in self._gen_1:
            if gen in full_name:
                toolcode[2] = '1'
                elderyounger = gen
                break
        else:
            for gen in self._gen_2:
                if gen in full_name:
                    toolcode[2] = '2'
                    elderyounger = gen
                    break

        # do comma flip
        if normalize:
            comma = lname.find(',')
            if comma != -1:
                lname_end = lname[comma + 1 :]
                while lname_end[0] in {' ', ','}:
                    lname_end = lname_end[1:]
                fname = lname_end + ' ' + fname
                lname = lname[:comma].strip()

        # do elder/younger move
        if normalize == 2 and elderyounger:
            elderyounger_loc = fname.find(elderyounger)
            if elderyounger_loc != -1:
                lname = ' '.join((lname, elderyounger.strip()))
                fname = ' '.join(
                    (
                        fname[:elderyounger_loc].strip(),
                        fname[elderyounger_loc + len(elderyounger) :],
                    )
                ).strip()

        toolcode[4] = '{:02d}'.format(len(fname))
        toolcode[5] = '{:02d}'.format(len(lname))

        # strip punctuation
        for char in ',/:;"&()!{|}?$%*+<=>[\\]^_`~':
            full_name = full_name.replace(char, '')
        for pos, char in enumerate(full_name):
            if char == '-' and full_name[pos - 1 : pos + 2] != 'b-g':
                full_name = full_name[:pos] + ' ' + full_name[pos + 1 :]

        # Fill field 9 (search range)
        for letter in [_[0] for _ in full_name.split()]:
            if letter not in toolcode[9]:
                toolcode[9] += letter
            if len(toolcode[9]) == 15:
                break

        def roman_check(numeral, fname, lname):
            """Move Roman numerals from first name to last.

            Parameters
            ----------
            numeral : str
                Roman numeral
            fname : str
                First name
            lname : str
                Last name

            Returns
            -------
            tuple
                First and last names with Roman numeral moved

            """
            loc = fname.find(numeral)
            if fname and (
                loc != -1
                and (len(fname[loc:]) == len(numeral))
                or fname[loc + len(numeral)] in {' ', ','}
            ):
                lname = ' '.join((lname, numeral))
                fname = ' '.join(
                    (
                        fname[:loc].strip(),
                        fname[loc + len(numeral) :].lstrip(' ,'),
                    )
                )
            return fname.strip(), lname.strip()

        # Fill fields 7 (specials) and 3 (roman numerals)
        for num, special in enumerate(self._synoname_special_table):
            roman, match, extra, method = special
            if method & self._method_dict['end']:
                match_context = ' ' + match
                loc = full_name.find(match_context)
                if (len(full_name) > len(match_context)) and (
                    loc == len(full_name) - len(match_context)
                ):
                    if roman:
                        if not any(
                            abbr in fname for abbr in ('i.', 'v.', 'x.')
                        ):
                            full_name = full_name[:loc]
                            toolcode[7] += '{:03d}'.format(num) + 'a'
                            if toolcode[3] == '000':
                                toolcode[3] = '{:03d}'.format(num)
                            if normalize == 2:
                                fname, lname = roman_check(match, fname, lname)
                    else:
                        full_name = full_name[:loc]
                        toolcode[7] += '{:03d}'.format(num) + 'a'
            if method & self._method_dict['middle']:
                match_context = ' ' + match + ' '
                loc = 0
                while loc != -1:
                    loc = full_name.find(match_context, loc + 1)
                    if loc > 0:
                        if roman:
                            if not any(
                                abbr in fname for abbr in ('i.', 'v.', 'x.')
                            ):
                                full_name = (
                                    full_name[:loc]
                                    + full_name[loc + len(match) + 1 :]
                                )
                                toolcode[7] += '{:03d}'.format(num) + 'b'
                                if toolcode[3] == '000':
                                    toolcode[3] = '{:03d}'.format(num)
                                if normalize == 2:
                                    fname, lname = roman_check(
                                        match, fname, lname
                                    )
                        else:
                            full_name = (
                                full_name[:loc]
                                + full_name[loc + len(match) + 1 :]
                            )
                            toolcode[7] += '{:03d}'.format(num) + 'b'
            if method & self._method_dict['beginning']:
                match_context = match + ' '
                loc = full_name.find(match_context)
                if loc == 0:
                    full_name = full_name[len(match) + 1 :]
                    toolcode[7] += '{:03d}'.format(num) + 'c'
            if method & self._method_dict['beginning_no_space']:
                loc = full_name.find(match)
                if loc == 0:
                    toolcode[7] += '{:03d}'.format(num) + 'd'
                    if full_name[: len(match)] not in toolcode[9]:
                        toolcode[9] += full_name[: len(match)]

            if extra:
                loc = full_name.find(extra)
                if loc != -1:
                    toolcode[7] += '{:03d}'.format(num) + 'X'
                    # Since extras are unique, we only look for each of them
                    # once, and they include otherwise impossible characters
                    # for this field, it's not possible for the following line
                    # to have ever been false.
                    # if full_name[loc:loc+len(extra)] not in toolcode[9]:
                    toolcode[9] += full_name[loc : loc + len(match)]

        return lname, fname, ''.join(toolcode)


Instruction:
Can you generate the documentation for the following Python 3 function
def uealite(
    word,
    max_word_length=20,
    max_acro_length=8,
    return_rule_no=False,
    var='standard',
):
    """Return UEA-Lite stem.

    This is a wrapper for :py:meth:`UEALite.stem`.

    Parameters
    ----------
    word : str
        The word to stem
    max_word_length : int
        The maximum word length allowed
    max_acro_length : int
        The maximum acronym length allowed
    return_rule_no : bool
        If True, returns the stem along with rule number
    var : str
        Variant rules to use:

            - ``Adams`` to use Jason Adams' rules
            - ``Perl`` to use the original Perl rules

    Returns
    -------
    str or (str, int)
        Word stem

    Examples
    --------
    >>> uealite('readings')
    'read'
    >>> uealite('insulted')
    'insult'
    >>> uealite('cussed')
    'cuss'
    >>> uealite('fancies')
    'fancy'
    >>> uealite('eroded')
    'erode'

    """
    return UEALite().stem(
        word, max_word_length, max_acro_length, return_rule_no, var
    )

Response: Return UEA - Lite stem.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def stem(
        self,
        word,
        max_word_length=20,
        max_acro_length=8,
        return_rule_no=False,
        var='standard',
    ):
        """Return UEA-Lite stem.

        Parameters
        ----------
        word : str
            The word to stem
        max_word_length : int
            The maximum word length allowed
        max_acro_length : int
            The maximum acronym length allowed
        return_rule_no : bool
            If True, returns the stem along with rule number
        var : str
            Variant rules to use:

                - ``Adams`` to use Jason Adams' rules
                - ``Perl`` to use the original Perl rules

        Returns
        -------
        str or (str, int)
            Word stem

        Examples
        --------
        >>> uealite('readings')
        'read'
        >>> uealite('insulted')
        'insult'
        >>> uealite('cussed')
        'cuss'
        >>> uealite('fancies')
        'fancy'
        >>> uealite('eroded')
        'erode'

        """

        def _stem_with_duplicate_character_check(word, del_len):
            if word[-1] == 's':
                del_len += 1
            stemmed_word = word[:-del_len]
            if re_match(r'.*(\w)\1$', stemmed_word):
                stemmed_word = stemmed_word[:-1]
            return stemmed_word

        def _stem(word):
            stemmed_word = word
            rule_no = 0

            if not word:
                return word, 0
            if word in self._problem_words or (
                word == 'menses' and var == 'Adams'
            ):
                return word, 90
            if max_word_length and len(word) > max_word_length:
                return word, 95

            if "'" in word:
                if word[-2:] in {"'s", "'S"}:
                    stemmed_word = word[:-2]
                if word[-1:] == "'":
                    stemmed_word = word[:-1]
                stemmed_word = stemmed_word.replace("n't", 'not')
                stemmed_word = stemmed_word.replace("'ve", 'have')
                stemmed_word = stemmed_word.replace("'re", 'are')
                stemmed_word = stemmed_word.replace("'m", 'am')
                return stemmed_word, 94

            if word.isdigit():
                return word, 90.3
            else:
                hyphen = word.find('-')
                if len(word) > hyphen > 0:
                    if (
                        word[:hyphen].isalpha()
                        and word[hyphen + 1 :].isalpha()
                    ):
                        return word, 90.2
                    else:
                        return word, 90.1
                elif '_' in word:
                    return word, 90
                elif word[-1] == 's' and word[:-1].isupper():
                    if var == 'Adams' and len(word) - 1 > max_acro_length:
                        return word, 96
                    return word[:-1], 91.1
                elif word.isupper():
                    if var == 'Adams' and len(word) > max_acro_length:
                        return word, 96
                    return word, 91
                elif re_match(r'^.*[A-Z].*[A-Z].*$', word):
                    return word, 92
                elif word[0].isupper():
                    return word, 93
                elif var == 'Adams' and re_match(
                    r'^[a-z](|[rl])(ing|ed)$', word
                ):
                    return word, 97

            for n in range(7, 1, -1):
                if word[-n:] in self._rules[var][n]:
                    rule_no, del_len, add_str = self._rules[var][n][word[-n:]]
                    if del_len:
                        stemmed_word = word[:-del_len]
                    else:
                        stemmed_word = word
                    if add_str:
                        stemmed_word += add_str
                    break

            if not rule_no:
                if re_match(r'.*\w\wings?$', word):  # rule 58
                    stemmed_word = _stem_with_duplicate_character_check(
                        word, 3
                    )
                    rule_no = 58
                elif re_match(r'.*\w\weds?$', word):  # rule 62
                    stemmed_word = _stem_with_duplicate_character_check(
                        word, 2
                    )
                    rule_no = 62
                elif word[-1] == 's':  # rule 68
                    stemmed_word = word[:-1]
                    rule_no = 68

            return stemmed_word, rule_no

        stem, rule_no = _stem(word)
        if return_rule_no:
            return stem, rule_no
        return stem

Response: Return UEA - Lite stem.


Instruction:
Implement a Python 3 function for
returning the R1 region as defined in the Porter2 specification.

Response:
def _sb_r1(self, term, r1_prefixes=None):
        """Return the R1 region, as defined in the Porter2 specification.

        Parameters
        ----------
        term : str
            The term to examine
        r1_prefixes : set
            Prefixes to consider

        Returns
        -------
        int
            Length of the R1 region

        """
        vowel_found = False
        if hasattr(r1_prefixes, '__iter__'):
            for prefix in r1_prefixes:
                if term[: len(prefix)] == prefix:
                    return len(prefix)

        for i in range(len(term)):
            if not vowel_found and term[i] in self._vowels:
                vowel_found = True
            elif vowel_found and term[i] not in self._vowels:
                return i + 1
        return len(term)


Instruction:
Explain what the following Python 3 code does
def _sb_r2(self, term, r1_prefixes=None):
        r1_start = self._sb_r1(term, r1_prefixes)
        return r1_start + self._sb_r1(term[r1_start:])

Response: Return the R2 region as defined in the Porter2 specification.


Instruction:
How would you implement a function in Python 3 that
returns True iff term ends in a short syllable.

Response:
def _sb_ends_in_short_syllable(self, term):
        """Return True iff term ends in a short syllable.

        (...according to the Porter2 specification.)

        NB: This is akin to the CVC test from the Porter stemmer. The
        description is unfortunately poor/ambiguous.

        Parameters
        ----------
        term : str
            The term to examine

        Returns
        -------
        bool
            True iff term ends in a short syllable

        """
        if not term:
            return False
        if len(term) == 2:
            if term[-2] in self._vowels and term[-1] not in self._vowels:
                return True
        elif len(term) >= 3:
            if (
                term[-3] not in self._vowels
                and term[-2] in self._vowels
                and term[-1] in self._codanonvowels
            ):
                return True
        return False


Instruction:
Create a Python 3 function to
return True iff term is a short word.

Response:
def _sb_short_word(self, term, r1_prefixes=None):
        """Return True iff term is a short word.

        (...according to the Porter2 specification.)

        Parameters
        ----------
        term : str
            The term to examine
        r1_prefixes : set
            Prefixes to consider

        Returns
        -------
        bool
            True iff term is a short word

        """
        if self._sb_r1(term, r1_prefixes) == len(
            term
        ) and self._sb_ends_in_short_syllable(term):
            return True
        return False


Instruction:
Implement a function in Python 3 to
return True iff a vowel exists in the term.

Response:
def _sb_has_vowel(self, term):
        """Return Porter helper function _sb_has_vowel value.

        Parameters
        ----------
        term : str
            The term to examine

        Returns
        -------
        bool
            True iff a vowel exists in the term (as defined in the Porter
            stemmer definition)

        """
        for letter in term:
            if letter in self._vowels:
                return True
        return False


Instruction:
Explain what the following Python 3 code does
def encode(self, word, max_length=8):
        # Lowercase input & filter unknown characters
        word = ''.join(
            char for char in word.lower() if char in self._initial_phones
        )

        if not word:
            word = '÷'

        # Perform initial eudex coding of each character
        values = [self._initial_phones[word[0]]]
        values += [self._trailing_phones[char] for char in word[1:]]

        # Right-shift by one to determine if second instance should be skipped
        shifted_values = [_ >> 1 for _ in values]
        condensed_values = [values[0]]
        for n in range(1, len(shifted_values)):
            if shifted_values[n] != shifted_values[n - 1]:
                condensed_values.append(values[n])

        # Add padding after first character & trim beyond max_length
        values = (
            [condensed_values[0]]
            + [0] * max(0, max_length - len(condensed_values))
            + condensed_values[1:max_length]
        )

        # Combine individual character values into eudex hash
        hash_value = 0
        for val in values:
            hash_value = (hash_value << 8) | val

        return hash_value

Response: Encodes a string into a set of eudex phonetic hash values.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def roger_root(word, max_length=5, zero_pad=True):
    return RogerRoot().encode(word, max_length, zero_pad)

Response: Return the Roger Root code for a word.


Instruction:
Can you write a function in Python 3 where it
returns the Roger Root code for a word.

Response:
def encode(self, word, max_length=5, zero_pad=True):
        """Return the Roger Root code for a word.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The maximum length (default 5) of the code to return
        zero_pad : bool
            Pad the end of the return value with 0s to achieve a max_length
            string

        Returns
        -------
        str
            The Roger Root code

        Examples
        --------
        >>> roger_root('Christopher')
        '06401'
        >>> roger_root('Niall')
        '02500'
        >>> roger_root('Smith')
        '00310'
        >>> roger_root('Schmidt')
        '06310'

        """
        # uppercase, normalize, decompose, and filter non-A-Z out
        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)

        code = ''
        pos = 0

        # Do first digit(s) first
        for num in range(4, 0, -1):
            if word[:num] in self._init_patterns[num]:
                code = self._init_patterns[num][word[:num]]
                pos += num
                break

        # Then code subsequent digits
        while pos < len(word):
            for num in range(4, 0, -1):  # pragma: no branch
                if word[pos : pos + num] in self._med_patterns[num]:
                    code += self._med_patterns[num][word[pos : pos + num]]
                    pos += num
                    break

        code = self._delete_consecutive_repeats(code)
        code = code.replace('*', '')

        if zero_pad:
            code += '0' * max_length

        return code[:max_length]


Instruction:
Explain what the following Python 3 code does
def encode(self, word):

        def _after(word, pos, letters):
            """Return True if word[pos] follows one of the supplied letters.

            Parameters
            ----------
            word : str
                The word to check
            pos : int
                Position within word to check
            letters : str
                Letters to confirm precede word[pos]

            Returns
            -------
            bool
                True if word[pos] follows a value in letters

            """
            return pos > 0 and word[pos - 1] in letters

        def _before(word, pos, letters):
            """Return True if word[pos] precedes one of the supplied letters.

            Parameters
            ----------
            word : str
                The word to check
            pos : int
                Position within word to check
            letters : str
                Letters to confirm follow word[pos]

            Returns
            -------
            bool
                True if word[pos] precedes a value in letters

            """
            return pos + 1 < len(word) and word[pos + 1] in letters

        sdx = ''

        word = unicode_normalize('NFKD', text_type(word.upper()))
        word = word.replace('ß', 'SS')

        word = word.replace('Ä', 'AE')
        word = word.replace('Ö', 'OE')
        word = word.replace('Ü', 'UE')
        word = ''.join(c for c in word if c in self._uc_set)

        # Nothing to convert, return base case
        if not word:
            return sdx

        for i in range(len(word)):
            if word[i] in self._uc_v_set:
                sdx += '0'
            elif word[i] == 'B':
                sdx += '1'
            elif word[i] == 'P':
                if _before(word, i, {'H'}):
                    sdx += '3'
                else:
                    sdx += '1'
            elif word[i] in {'D', 'T'}:
                if _before(word, i, {'C', 'S', 'Z'}):
                    sdx += '8'
                else:
                    sdx += '2'
            elif word[i] in {'F', 'V', 'W'}:
                sdx += '3'
            elif word[i] in {'G', 'K', 'Q'}:
                sdx += '4'
            elif word[i] == 'C':
                if _after(word, i, {'S', 'Z'}):
                    sdx += '8'
                elif i == 0:
                    if _before(
                        word, i, {'A', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'X'}
                    ):
                        sdx += '4'
                    else:
                        sdx += '8'
                elif _before(word, i, {'A', 'H', 'K', 'O', 'Q', 'U', 'X'}):
                    sdx += '4'
                else:
                    sdx += '8'
            elif word[i] == 'X':
                if _after(word, i, {'C', 'K', 'Q'}):
                    sdx += '8'
                else:
                    sdx += '48'
            elif word[i] == 'L':
                sdx += '5'
            elif word[i] in {'M', 'N'}:
                sdx += '6'
            elif word[i] == 'R':
                sdx += '7'
            elif word[i] in {'S', 'Z'}:
                sdx += '8'

        sdx = self._delete_consecutive_repeats(sdx)

        if sdx:
            sdx = sdx[:1] + sdx[1:].replace('0', '')

        return sdx

Response: Encodes a word into a Kölner Phonetik value.


Instruction:
How would you code a function in Python 3 to
convert a Kölner Phonetik code from numeric to alphabetic.

Response:
def _to_alpha(self, num):
        """Convert a Kölner Phonetik code from numeric to alphabetic.

        Parameters
        ----------
        num : str or int
            A numeric Kölner Phonetik representation

        Returns
        -------
        str
            An alphabetic representation of the same word

        Examples
        --------
        >>> pe = Koelner()
        >>> pe._to_alpha('862')
        'SNT'
        >>> pe._to_alpha('657')
        'NLR'
        >>> pe._to_alpha('86766')
        'SNRNN'

        """
        num = ''.join(c for c in text_type(num) if c in self._num_set)
        return num.translate(self._num_trans)


Instruction:
Can you tell what is the following Python 3 function doing
def main(argv):
    first_col = 3
    last_col = -1

    def print_usage():
        """Print usage statement."""
        sys.stdout.write(
            'features_csv_to_dict.py -i <inputfile> ' + '[-o <outputfile>]\n'
        )
        sys.exit(2)

    def binarize(num):
        """Replace 0, -1, 1, 2 with 00, 10, 01, 11.

        Parameters
        ----------
        num : str
            The number to binarize

        Returns
        -------
        str
            A binarized number

        """
        if num == '0':  # 0
            return '00'
        elif num == '-1':  # -
            return '10'
        elif num == '1':  # +
            return '01'
        elif num == '2':  # ± (segmental) or copy from base (non-segmental)
            return '11'

    def init_termdicts():
        """Initialize the terms dict.

        Returns
        -------
        (dict, dict)
            Term & feature mask dictionaries

        """
        ifile = codecs.open('features_terms.csv', 'r', 'utf-8')

        feature_mask = {}
        keyline = ifile.readline().strip().split(',')[first_col:last_col]
        mag = len(keyline)
        for i in range(len(keyline)):
            features = '0b' + ('00' * i) + '11' + ('00' * (mag - i - 1))
            feature_mask[keyline[i]] = int(features, 2)

        termdict = {}
        for line in ifile:
            line = line.strip().rstrip(',')
            if '#' in line:
                line = line[: line.find('#')].strip()
            if line:
                line = line.split(',')
                term = line[last_col]
                features = '0b' + ''.join(
                    [binarize(val) for val in line[first_col:last_col]]
                )
                termdict[term] = int(features, 2)

        return termdict, feature_mask

    def check_terms(sym, features, name, termdict):
        """Check terms.

        Check each term of the phone name to confirm that it matches
        the expected features implied by that feature.

        Parameters
        ----------
        sym : str
            Symbol to check
        features : int
            Phone features
        name : str
            Phone name
        termdict : dict
            Dictionary of terms

        """
        if '#' in name:
            name = name[: name.find('#')].strip()
        for term in name.split():
            if term in termdict:
                if termdict[term] & features != termdict[term]:
                    sys.stdout.write(
                        'Feature mismatch for term "'
                        + term
                        + '" in   '
                        + sym
                        + '\n'
                    )
            else:
                sys.stdout.write(
                    'Unknown term "'
                    + term
                    + '" in '
                    + name
                    + ' : '
                    + sym
                    + '\n'
                )

    def check_entailments(sym, features, feature_mask):
        """Check entailments.

        Check for necessary feature assignments (entailments)
        For example, [+round] necessitates [+labial].

        Parameters
        ----------
        sym : str
            Symbol to check
        features : int
            Phone features
        feature_mask : dict
            The feature mask

        """
        entailments = {
            '+labial': ('±round', '±protruded', '±compressed', '±labiodental'),
            '-labial': ('0round', '0protruded', '0compressed', '0labiodental'),
            '+coronal': ('±anterior', '±distributed'),
            '-coronal': ('0anterior', '0distributed'),
            '+dorsal': ('±high', '±low', '±front', '±back', '±tense'),
            '-dorsal': ('0high', '0low', '0front', '0back', '0tense'),
            '+pharyngeal': ('±atr', '±rtr'),
            '-pharyngeal': ('0atr', '0rtr'),
            '+protruded': ('+labial', '+round', '-compressed'),
            '+compressed': ('+labial', '+round', '-protruded'),
            '+glottalic_suction': ('-velaric_suction',),
            '+velaric_suction': ('-glottalic_suction',),
        }

        for feature in entailments:
            fname = feature[1:]
            if feature[0] == '+':
                fm = (feature_mask[fname] >> 1) & feature_mask[fname]
            else:
                fm = (feature_mask[fname] << 1) & feature_mask[fname]
            if (features & fm) == fm:
                for ent in entailments[feature]:
                    ename = ent[1:]
                    if ent[0] == '+':
                        efm = (feature_mask[ename] >> 1) & feature_mask[ename]
                    elif ent[0] == '-':
                        efm = (feature_mask[ename] << 1) & feature_mask[ename]
                    elif ent[0] == '0':
                        efm = 0
                    elif ent[0] == '±':
                        efm = feature_mask[ename]

                    if ent[0] == '±':
                        if (features & efm) == 0:
                            sys.stdout.write(
                                'Incorrect entailment for '
                                + sym
                                + ' for feature '
                                + fname
                                + ' and entailment '
                                + ename
                            )
                    else:
                        if (features & efm) != efm:
                            sys.stdout.write(
                                'Incorrect entailment for '
                                + sym
                                + ' for feature '
                                + fname
                                + ' and entailment '
                                + ename
                            )

    checkdict = {}  # a mapping of symbol to feature
    checkset_s = set()  # a set of the symbols seen
    checkset_f = set()  # a set of the feature values seen

    termdict, feature_mask = init_termdicts()

    ifile = ''
    ofile = ''
    try:
        opts = getopt.getopt(argv, 'hi:o:', ['ifile=', 'ofile='])[0]
    except getopt.GetoptError:
        print_usage()
    for opt, arg in opts:
        if opt == '-h':
            print_usage()
        elif opt in ('-i', '--ifile'):
            ifile = codecs.open(arg, 'r', 'utf-8')
        elif opt in ('-o', '--ofile'):
            ofile = codecs.open(arg, 'w', 'utf-8')
    if not ifile:
        print_usage()

    oline = 'PHONETIC_FEATURES = {'
    if not ofile:
        ofile = sys.stdout

    ofile.write(oline + '\n')

    keyline = ifile.readline().strip().split(',')[first_col:last_col]
    for line in ifile:
        line = line.strip().rstrip(',')

        if line.startswith('####'):
            break

        line = unicodedata.normalize('NFC', line)

        if not line or line.startswith('#'):
            oline = '                     ' + line

        else:
            line = line.strip().split(',')
            if '#' in line:
                line = line[: line.find('#')]
            symbol = line[0]
            variant = int(line[1])
            segmental = bool(line[2])
            features = '0b' + ''.join(
                [binarize(val) for val in line[first_col:last_col]]
            )
            name = line[-1].strip()
            if not segmental:
                features = '-' + features

            featint = int(features, 2)
            check_terms(symbol, featint, name, termdict)
            check_entailments(symbol, featint, feature_mask)
            if symbol in checkset_s:
                sys.stdout.write(
                    'Symbol ' + symbol + ' appears twice in CSV.\n'
                )
            else:
                checkset_s.add(symbol)

            if variant < 2:
                if featint in checkset_f:
                    sys.stdout.write(
                        'Feature set '
                        + str(featint)
                        + ' appears in CSV for two primary IPA '
                        + 'symbols: '
                        + symbol
                        + ' and '
                        + checkdict[featint]
                    )
                else:
                    checkdict[featint] = symbol
                    checkset_f.add(featint)

            if variant < 5:
                oline = '                     \'{}\': {},'.format(
                    symbol, featint
                )
            else:
                oline = ''

        if oline:
            ofile.write(oline + '\n')

    ofile.write('                    }\n\nFEATURE_MASK = {')

    mag = len(keyline)
    for i in range(len(keyline)):
        features = int('0b' + ('00' * i) + '11' + ('00' * (mag - i - 1)), 2)
        oline = '                \'{}\': {},'.format(keyline[i], features)
        ofile.write(oline + '\n')

    ofile.write('               }\n')

Response: This function is the main function of the features_terms. csv script.


Instruction:
Explain what the following Python 3 code does
def lein(word, max_length=4, zero_pad=True):
    return Lein().encode(word, max_length, zero_pad)

Response: Return the Lein code for a word.


Instruction:
Write a Python 3 function that can
return the Lein code for a word.

Response:
def encode(self, word, max_length=4, zero_pad=True):
        """Return the Lein code for a word.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The length of the code returned (defaults to 4)
        zero_pad : bool
            Pad the end of the return value with 0s to achieve a max_length
            string

        Returns
        -------
        str
            The Lein code

        Examples
        --------
        >>> pe = Lein()
        >>> pe.encode('Christopher')
        'C351'
        >>> pe.encode('Niall')
        'N300'
        >>> pe.encode('Smith')
        'S210'
        >>> pe.encode('Schmidt')
        'S521'

        """
        # uppercase, normalize, decompose, and filter non-A-Z out
        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)

        code = word[:1]  # Rule 1
        word = word[1:].translate(self._del_trans)  # Rule 2
        word = self._delete_consecutive_repeats(word)  # Rule 3
        code += word.translate(self._trans)  # Rule 4

        if zero_pad:
            code += '0' * max_length  # Rule 4

        return code[:max_length]


Instruction:
Create a Python 3 function to
return the Q - Grams in src & tar.

Response:
def _get_qgrams(self, src, tar, qval=0, skip=0):
        """Return the Q-Grams in src & tar.

        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
        skip : int
            The number of characters to skip (only works when src and tar are
            strings)

        Returns
        -------
        tuple of Counters
            Q-Grams

        Examples
        --------
        >>> pe = _TokenDistance()
        >>> pe._get_qgrams('AT', 'TT', qval=2)
        (QGrams({'$A': 1, 'AT': 1, 'T#': 1}),
         QGrams({'$T': 1, 'TT': 1, 'T#': 1}))

        """
        if isinstance(src, Counter) and isinstance(tar, Counter):
            return src, tar
        if qval > 0:
            return QGrams(src, qval, '$#', skip), QGrams(tar, qval, '$#', skip)
        return Counter(src.strip().split()), Counter(tar.strip().split())


Instruction:
Can you generate the documentation for the following Python 3 function
def rle_decode(text, use_bwt=True):
    text = RLE().decode(text)
    if use_bwt:
        text = BWT().decode(text)
    return text

Response: r A wrapper for RLE. decode that does the actual decoding.


Instruction:
How would you code a function in Python 3 to
perform encoding of run - length - encoding of a string.

Response:
def encode(self, text):
        r"""Perform encoding of run-length-encoding (RLE).

        Parameters
        ----------
        text : str
            A text string to encode

        Returns
        -------
        str
            Word decoded by RLE

        Examples
        --------
        >>> rle = RLE()
        >>> bwt = BWT()
        >>> rle.encode(bwt.encode('align'))
        'n\x00ilag'
        >>> rle.encode('align')
        'align'

        >>> rle.encode(bwt.encode('banana'))
        'annb\x00aa'
        >>> rle.encode('banana')
        'banana'

        >>> rle.encode(bwt.encode('aaabaabababa'))
        'ab\x00abbab5a'
        >>> rle.encode('aaabaabababa')
        '3abaabababa'

        """
        if text:
            text = ((len(list(g)), k) for k, g in groupby(text))
            text = (
                (str(n) + k if n > 2 else (k if n == 1 else 2 * k))
                for n, k in text
            )
        return ''.join(text)


Instruction:
Can you tell what is the following Python 3 function doing
def decode(self, text):
        mult = ''
        decoded = []
        for letter in list(text):
            if not letter.isdigit():
                if mult:
                    decoded.append(int(mult) * letter)
                    mult = ''
                else:
                    decoded.append(letter)
            else:
                mult += letter

        text = ''.join(decoded)
        return text

Response: Perform decoding of run - length - encoding of a string.


Instruction:
Write a Python 3 script for
returning the SoundD code for the given word.

Response:
def encode(self, word, max_length=4):
        """Return the SoundD code.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The length of the code returned (defaults to 4)

        Returns
        -------
        str
            The SoundD code

        Examples
        --------
        >>> sound_d('Gough')
        '2000'
        >>> sound_d('pneuma')
        '5500'
        >>> sound_d('knight')
        '5300'
        >>> sound_d('trice')
        '3620'
        >>> sound_d('judge')
        '2200'

        """
        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)

        if word[:2] in {'KN', 'GN', 'PN', 'AC', 'WR'}:
            word = word[1:]
        elif word[:1] == 'X':
            word = 'S' + word[1:]
        elif word[:2] == 'WH':
            word = 'W' + word[2:]

        word = (
            word.replace('DGE', '20').replace('DGI', '20').replace('GH', '0')
        )

        word = word.translate(self._trans)
        word = self._delete_consecutive_repeats(word)
        word = word.replace('0', '')

        if max_length != -1:
            if len(word) < max_length:
                word += '0' * (max_length - len(word))
            else:
                word = word[:max_length]

        return word


Instruction:
Can you generate the documentation for the following Python 3 function
def dist(self, src, tar):
        if src == tar:
            return 0.0

        src = src.encode('utf-8')
        tar = tar.encode('utf-8')

        if lzma is not None:
            src_comp = lzma.compress(src)[14:]
            tar_comp = lzma.compress(tar)[14:]
            concat_comp = lzma.compress(src + tar)[14:]
            concat_comp2 = lzma.compress(tar + src)[14:]
        else:  # pragma: no cover
            raise ValueError(
                'Install the PylibLZMA module in order to use LZMA'
            )

        return (
            min(len(concat_comp), len(concat_comp2))
            - min(len(src_comp), len(tar_comp))
        ) / max(len(src_comp), len(tar_comp))

Response: Return the NCD between two strings using LZMA compression.


Instruction:
Can you create a Python 3 function that
returns the Smith - Waterman score of two strings.

Response:
def smith_waterman(src, tar, gap_cost=1, sim_func=sim_ident):
    """Return the Smith-Waterman score of two strings.

    This is a wrapper for :py:meth:`SmithWaterman.dist_abs`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    gap_cost : float
        The cost of an alignment gap (1 by default)
    sim_func : function
        A function that returns the similarity of two characters (identity
        similarity by default)

    Returns
    -------
    float
        Smith-Waterman score

    Examples
    --------
    >>> smith_waterman('cat', 'hat')
    2.0
    >>> smith_waterman('Niall', 'Neil')
    1.0
    >>> smith_waterman('aluminum', 'Catalan')
    0.0
    >>> smith_waterman('ATCG', 'TAGC')
    1.0

    """
    return SmithWaterman().dist_abs(src, tar, gap_cost, sim_func)


Instruction:
Write a Python 3 script for
returning the Smith - Waterman score of two strings.

Response:
def dist_abs(self, src, tar, gap_cost=1, sim_func=sim_ident):
        """Return the Smith-Waterman score of two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        gap_cost : float
            The cost of an alignment gap (1 by default)
        sim_func : function
            A function that returns the similarity of two characters (identity
            similarity by default)

        Returns
        -------
        float
            Smith-Waterman score

        Examples
        --------
        >>> cmp = SmithWaterman()
        >>> cmp.dist_abs('cat', 'hat')
        2.0
        >>> cmp.dist_abs('Niall', 'Neil')
        1.0
        >>> cmp.dist_abs('aluminum', 'Catalan')
        0.0
        >>> cmp.dist_abs('ATCG', 'TAGC')
        1.0

        """
        d_mat = np_zeros((len(src) + 1, len(tar) + 1), dtype=np_float32)

        for i in range(len(src) + 1):
            d_mat[i, 0] = 0
        for j in range(len(tar) + 1):
            d_mat[0, j] = 0
        for i in range(1, len(src) + 1):
            for j in range(1, len(tar) + 1):
                match = d_mat[i - 1, j - 1] + sim_func(src[i - 1], tar[j - 1])
                delete = d_mat[i - 1, j] - gap_cost
                insert = d_mat[i, j - 1] - gap_cost
                d_mat[i, j] = max(0, match, delete, insert)
        return d_mat[d_mat.shape[0] - 1, d_mat.shape[1] - 1]


Instruction:
Implement a Python 3 function for
returning the Levenshtein distance between two strings.

Response:
def levenshtein(src, tar, mode='lev', cost=(1, 1, 1, 1)):
    """Return the Levenshtein distance between two strings.

    This is a wrapper of :py:meth:`Levenshtein.dist_abs`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    mode : str
        Specifies a mode for computing the Levenshtein distance:

            - ``lev`` (default) computes the ordinary Levenshtein distance, in
              which edits may include inserts, deletes, and substitutions
            - ``osa`` computes the Optimal String Alignment distance, in which
              edits may include inserts, deletes, substitutions, and
              transpositions but substrings may only be edited once

    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and transpositions, respectively (by default:
        (1, 1, 1, 1))

    Returns
    -------
    int (may return a float if cost has float values)
        The Levenshtein distance between src & tar

    Examples
    --------
    >>> levenshtein('cat', 'hat')
    1
    >>> levenshtein('Niall', 'Neil')
    3
    >>> levenshtein('aluminum', 'Catalan')
    7
    >>> levenshtein('ATCG', 'TAGC')
    3

    >>> levenshtein('ATCG', 'TAGC', mode='osa')
    2
    >>> levenshtein('ACTG', 'TAGC', mode='osa')
    4

    """
    return Levenshtein().dist_abs(src, tar, mode, cost)


Instruction:
Given the following Python 3 function, write the documentation
def dist_levenshtein(src, tar, mode='lev', cost=(1, 1, 1, 1)):
    return Levenshtein().dist(src, tar, mode, cost)

Response: Return the normalized Levenshtein distance between two strings.


Instruction:
How would you explain what the following Python 3 function does
def sim_levenshtein(src, tar, mode='lev', cost=(1, 1, 1, 1)):
    return Levenshtein().sim(src, tar, mode, cost)

Response: Return the Levenshtein similarity between two strings.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def dist_abs(self, src, tar, mode='lev', cost=(1, 1, 1, 1)):
        ins_cost, del_cost, sub_cost, trans_cost = cost

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

        d_mat = np_zeros((len(src) + 1, len(tar) + 1), dtype=np_int)
        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]
                    + (sub_cost if src[i] != tar[j] else 0),  # sub/==
                )

                if mode == 'osa':
                    if (
                        i + 1 > 1
                        and j + 1 > 1
                        and src[i] == tar[j - 1]
                        and src[i - 1] == tar[j]
                    ):
                        # transposition
                        d_mat[i + 1, j + 1] = min(
                            d_mat[i + 1, j + 1],
                            d_mat[i - 1, j - 1] + trans_cost,
                        )

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

Response: Return the Levenshtein distance between two strings.


Instruction:
Here you have a function in Python 3, explain what it does
def dist(self, src, tar, mode='lev', cost=(1, 1, 1, 1)):
        if src == tar:
            return 0
        ins_cost, del_cost = cost[:2]
        return levenshtein(src, tar, mode, cost) / (
            max(len(src) * del_cost, len(tar) * ins_cost)
        )

Response: Return the normalized Levenshtein distance between two strings src and tar.


Instruction:
Can you write a function in Python 3 where it
returns the omission key for the given word.

Response:
def fingerprint(self, word):
        """Return the omission key.

        Parameters
        ----------
        word : str
            The word to transform into its omission key

        Returns
        -------
        str
            The omission key

        Examples
        --------
        >>> ok = OmissionKey()
        >>> ok.fingerprint('The quick brown fox jumped over the lazy dog.')
        'JKQXZVWYBFMGPDHCLNTREUIOA'
        >>> ok.fingerprint('Christopher')
        'PHCTSRIOE'
        >>> ok.fingerprint('Niall')
        'LNIA'

        """
        word = unicode_normalize('NFKD', text_type(word.upper()))
        word = ''.join(c for c in word if c in self._letters)

        key = ''

        # add consonants in order supplied by _consonants (no duplicates)
        for char in self._consonants:
            if char in word:
                key += char

        # add vowels in order they appeared in the word (no duplicates)
        for char in word:
            if char not in self._consonants and char not in key:
                key += char

        return key


Instruction:
Write a Python 3 script to
return the Minkowski distance of two strings.

Response:
def minkowski(src, tar, qval=2, pval=1, normalized=False, alphabet=None):
    """Return the Minkowski distance (:math:`L^p`-norm) of two strings.

    This is a wrapper for :py:meth:`Minkowski.dist_abs`.

    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
    pval : int or float
        The :math:`p`-value of the :math:`L^p`-space
    normalized : bool
        Normalizes to [0, 1] if True
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The Minkowski distance

    Examples
    --------
    >>> minkowski('cat', 'hat')
    4.0
    >>> minkowski('Niall', 'Neil')
    7.0
    >>> minkowski('Colin', 'Cuilen')
    9.0
    >>> minkowski('ATCG', 'TAGC')
    10.0

    """
    return Minkowski().dist_abs(src, tar, qval, pval, normalized, alphabet)


Instruction:
Write a Python 3 function for
returning normalized Minkowski distance of two strings.

Response:
def dist_minkowski(src, tar, qval=2, pval=1, alphabet=None):
    """Return normalized Minkowski distance of two strings.

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

    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
    pval : int or float
        The :math:`p`-value of the :math:`L^p`-space
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The normalized Minkowski distance

    Examples
    --------
    >>> dist_minkowski('cat', 'hat')
    0.5
    >>> round(dist_minkowski('Niall', 'Neil'), 12)
    0.636363636364
    >>> round(dist_minkowski('Colin', 'Cuilen'), 12)
    0.692307692308
    >>> dist_minkowski('ATCG', 'TAGC')
    1.0

    """
    return Minkowski().dist(src, tar, qval, pval, alphabet)


Instruction:
Can you write a function in Python 3 where it
returns normalized Minkowski similarity of two strings.

Response:
def sim_minkowski(src, tar, qval=2, pval=1, alphabet=None):
    """Return normalized Minkowski similarity of two strings.

    This is a wrapper for :py:meth:`Minkowski.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
    pval : int or float
        The :math:`p`-value of the :math:`L^p`-space
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The normalized Minkowski similarity

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

    """
    return Minkowski().sim(src, tar, qval, pval, alphabet)


Instruction:
Explain what the following Python 3 code does
def dist_abs(
        self, src, tar, qval=2, pval=1, normalized=False, alphabet=None
    ):
        """Return the Minkowski distance (:math:`L^p`-norm) of two strings.

        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
        pval : int or float
            The :math:`p`-value of the :math:`L^p`-space
        normalized : bool
            Normalizes to [0, 1] if True
        alphabet : collection or int
            The values or size of the alphabet

        Returns
        -------
        float
            The Minkowski distance

        Examples
        --------
        >>> cmp = Minkowski()
        >>> cmp.dist_abs('cat', 'hat')
        4.0
        >>> cmp.dist_abs('Niall', 'Neil')
        7.0
        >>> cmp.dist_abs('Colin', 'Cuilen')
        9.0
        >>> cmp.dist_abs('ATCG', 'TAGC')
        10.0

        """
        q_src, q_tar = self._get_qgrams(src, tar, qval)
        diffs = ((q_src - q_tar) + (q_tar - q_src)).values()

        normalizer = 1
        if normalized:
            totals = (q_src + q_tar).values()
            if alphabet is not None:
                # noinspection PyTypeChecker
                normalizer = (
                    alphabet if isinstance(alphabet, Number) else len(alphabet)
                )
            elif pval == 0:
                normalizer = len(totals)
            else:
                normalizer = sum(_ ** pval for _ in totals) ** (1 / pval)

        if len(diffs) == 0:
            return 0.0
        if pval == float('inf'):
            # Chebyshev distance
            return max(diffs) / normalizer
        if pval == 0:
            # This is the l_0 "norm" as developed by David Donoho
            return len(diffs) / normalizer
        return sum(_ ** pval for _ in diffs) ** (1 / pval) / normalizer

Response: Return the Minkowski distance of two strings.


Instruction:
Implement a Python 3 function for
returning normalized Minkowski distance of two strings.

Response:
def dist(self, src, tar, qval=2, pval=1, alphabet=None):
        """Return normalized Minkowski distance of two strings.

        The normalized Minkowski distance :cite:`Minkowski:1910` is a distance
        metric in :math:`L^p`-space, normalized to [0, 1].

        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
        pval : int or float
            The :math:`p`-value of the :math:`L^p`-space
        alphabet : collection or int
            The values or size of the alphabet

        Returns
        -------
        float
            The normalized Minkowski distance

        Examples
        --------
        >>> cmp = Minkowski()
        >>> cmp.dist('cat', 'hat')
        0.5
        >>> round(cmp.dist('Niall', 'Neil'), 12)
        0.636363636364
        >>> round(cmp.dist('Colin', 'Cuilen'), 12)
        0.692307692308
        >>> cmp.dist('ATCG', 'TAGC')
        1.0

        """
        return self.dist_abs(src, tar, qval, pval, True, alphabet)


Instruction:
Given the following Python 3 function, write the documentation
def occurrence_halved_fingerprint(
    word, n_bits=16, most_common=MOST_COMMON_LETTERS_CG
):
    """Return the occurrence halved fingerprint.

    This is a wrapper for :py:meth:`OccurrenceHalved.fingerprint`.

    Parameters
    ----------
    word : str
        The word to fingerprint
    n_bits : int
        Number of bits in the fingerprint returned
    most_common : list
        The most common tokens in the target language, ordered by frequency

    Returns
    -------
    int
        The occurrence halved fingerprint

    Examples
    --------
    >>> bin(occurrence_halved_fingerprint('hat'))
    '0b1010000000010'
    >>> bin(occurrence_halved_fingerprint('niall'))
    '0b10010100000'
    >>> bin(occurrence_halved_fingerprint('colin'))
    '0b1001010000'
    >>> bin(occurrence_halved_fingerprint('atcg'))
    '0b10100000000000'
    >>> bin(occurrence_halved_fingerprint('entreatment'))
    '0b1111010000110000'

    """
    return OccurrenceHalved().fingerprint(word, n_bits, most_common)

Response: Return the occurrence halved fingerprint.