
    d@<                        d dl mZ d dlmZmZmZ d dlmZ d dlm	Z	 d dl
mZmZ d$dZd$dZd%dZdddddd&dZdddddd&dZdddddd'dZdddddd'dZdddd(d!Zdddd)d#ZdS )*    )annotations)CallableHashableSequence)is_none)Indel)EditopsOpcodess1Sequence[Hashable]s2weightstuple[int, int, int]returnintc                    t          |           }t          |          }|\  }}}||z  ||z  z   }||k    rt          |||z  ||z
  |z  z             }nt          |||z  ||z
  |z  z             }|S )N)lenmin)	r   r   r   len1len2insertdeletereplacemax_dists	            e/home/feoh/.local/pipx/venvs/poetry/lib/python3.11/site-packages/rapidfuzz/distance/Levenshtein_py.py_levenshtein_maximumr      s     r77Dr77D%FFGf}tf},Ht||x4$;&2H!HIIx4$;&2H!HIIO    c                v   t          |           }|\  }}}t          t          d|dz   |z  |                    }|D ]v}|d         }	|dxx         |z  cc<   t          |          D ]L}
|	}| |
         |k    r)t          ||
         |z   ||
dz            |z   |	|z             }||
dz            }	|||
dz   <   Mw|d         S )Nr      )r   listranger   )r   r   r   r   r   r   r   cachech2tempixs               r   _uniform_genericr(      s     r77D%FFGq4!8v-v6677E  QxaFt 	 	AA!u||a6)5Q<&+@$.QQQ<DE!a%LL	 9r   c                   | st          |          S dt          |           z  dz
  }d}t          |           }dt          |           dz
  z  }i }|j        }d}| D ]}	 ||	d          |z  ||	<   |dz  }|D ]b}
 ||
d          }|}||z  |z   |z  |z  |z  }|||z   z  }||z  }|||z  dk    z  }|||z  dk    z  }|dz  dz  }|dz  }|||z   z  }||z  }c|S )Nr   r   )r   get)r   r   VPVNcurrDistmaskblock	block_getr'   ch1r$   PM_jXD0HPHNs                   r   _uniform_distancer7   2   sF    2ww
s2ww,!	B	
B2wwHR1D!#E	I	A  YsA&&*c
	a  ya  B"}"a'",BG*_"WR$Y1$$R$Y1$$Ag]1WBG*_"WOr   r   r   r   N)r   	processorscore_cutoff
score_hinttuple[int, int, int] | Noner9   (Callable[..., Sequence[Hashable]] | Noner:   
int | Noner;   c                   | ||           }  ||          }||dk    rt          | |          }n-|dk    rt          j        | |          }nt          | ||          }|||k    r|n|dz   S )a  
    Calculates the minimum number of insertions, deletions, and substitutions
    required to change one sequence into the other according to Levenshtein with custom
    costs for insertion, deletion and substitution

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    weights : Tuple[int, int, int] or None, optional
        The weights for the three operations in the form
        (insertion, deletion, substitution). Default is (1, 1, 1),
        which gives all three operations a weight of 1.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_cutoff : int, optional
        Maximum distance between s1 and s2, that is
        considered as a result. If the distance is bigger than score_cutoff,
        score_cutoff + 1 is returned instead. Default is None, which deactivates
        this behaviour.
    score_hint : int, optional
        Expected distance between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    distance : int
        distance between s1 and s2

    Raises
    ------
    ValueError
        If unsupported weights are provided a ValueError is thrown

    Examples
    --------
    Find the Levenshtein distance between two strings:

    >>> from rapidfuzz.distance import Levenshtein
    >>> Levenshtein.distance("lewenstein", "levenshtein")
    2

    Setting a maximum distance allows the implementation to select
    a more efficient implementation:

    >>> Levenshtein.distance("lewenstein", "levenshtein", score_cutoff=1)
    2

    It is possible to select different weights by passing a `weight`
    tuple.

    >>> Levenshtein.distance("lewenstein", "levenshtein", weights=(1,1,2))
    3
    Nr8   )r   r      r   )r7   r   distancer(   )r   r   r   r9   r:   r;   dists          r   rA   rA   V   s    D Yr]]Yr]]'Y.. R((	I		~b"%%B00 (DL,@,@44|VWGWWr   c                   | ||           }  ||          }|pd}t          | ||          }t          | ||          }||z
  }|||k    r|ndS )a  
    Calculates the levenshtein similarity in the range [max, 0] using custom
    costs for insertion, deletion and substitution.

    This is calculated as ``max - distance``, where max is the maximal possible
    Levenshtein distance given the lengths of the sequences s1/s2 and the weights.

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    weights : Tuple[int, int, int] or None, optional
        The weights for the three operations in the form
        (insertion, deletion, substitution). Default is (1, 1, 1),
        which gives all three operations a weight of 1.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_cutoff : int, optional
        Maximum distance between s1 and s2, that is
        considered as a result. If the similarity is smaller than score_cutoff,
        0 is returned instead. Default is None, which deactivates
        this behaviour.
    score_hint : int, optional
        Expected similarity between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    similarity : int
        similarity between s1 and s2

    Raises
    ------
    ValueError
        If unsupported weights are provided a ValueError is thrown
    Nr8   r   r   )r   rA   )	r   r   r   r9   r:   r;   maximumrB   sims	            r   
similarityrG      sv    ` Yr]]Yr]]"G"2r733GBG,,,D
D.C'3,+>+>33QFr   float | Nonefloatc                   t          |           st          |          rdS | ||           }  ||          }|pd}t          | ||          }t          | ||          }|r||z  nd}|||k    r|ndS )a  
    Calculates a normalized levenshtein distance in the range [1, 0] using custom
    costs for insertion, deletion and substitution.

    This is calculated as ``distance / max``, where max is the maximal possible
    Levenshtein distance given the lengths of the sequences s1/s2 and the weights.

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    weights : Tuple[int, int, int] or None, optional
        The weights for the three operations in the form
        (insertion, deletion, substitution). Default is (1, 1, 1),
        which gives all three operations a weight of 1.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_cutoff : float, optional
        Optional argument for a score threshold as a float between 0 and 1.0.
        For norm_dist > score_cutoff 1.0 is returned instead. Default is None,
        which deactivates this behaviour.
    score_hint : float, optional
        Expected normalized distance between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    norm_dist : float
        normalized distance between s1 and s2 as a float between 1.0 and 0.0

    Raises
    ------
    ValueError
        If unsupported weights are provided a ValueError is thrown
          ?Nr8   rD   r   r   )r   r   rA   )	r   r   r   r9   r:   r;   rE   rB   	norm_dists	            r   normalized_distancerM      s    ^ r{{ gbkk sYr]]Yr]]"G"2r733GBG,,,D")0wqI%-l1J1J99QRRr   c                   t          |           st          |          rdS | ||           }  ||          }|pd}t          | ||          }d|z
  }|||k    r|ndS )a  
    Calculates a normalized levenshtein similarity in the range [0, 1] using custom
    costs for insertion, deletion and substitution.

    This is calculated as ``1 - normalized_distance``

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    weights : Tuple[int, int, int] or None, optional
        The weights for the three operations in the form
        (insertion, deletion, substitution). Default is (1, 1, 1),
        which gives all three operations a weight of 1.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_cutoff : float, optional
        Optional argument for a score threshold as a float between 0 and 1.0.
        For norm_sim < score_cutoff 0 is returned instead. Default is None,
        which deactivates this behaviour.
    score_hint : int, optional
        Expected normalized similarity between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    norm_sim : float
        normalized similarity between s1 and s2 as a float between 0 and 1.0

    Raises
    ------
    ValueError
        If unsupported weights are provided a ValueError is thrown

    Examples
    --------
    Find the normalized Levenshtein similarity between two strings:

    >>> from rapidfuzz.distance import Levenshtein
    >>> Levenshtein.normalized_similarity("lewenstein", "levenshtein")
    0.81818181818181

    Setting a score_cutoff allows the implementation to select
    a more efficient implementation:

    >>> Levenshtein.normalized_similarity("lewenstein", "levenshtein", score_cutoff=0.85)
    0.0

    It is possible to select different weights by passing a `weight`
    tuple.

    >>> Levenshtein.normalized_similarity("lewenstein", "levenshtein", weights=(1,1,2))
    0.85714285714285

    When a different processor is used s1 and s2 do not have to be strings

    >>> Levenshtein.normalized_similarity(["lewenstein"], ["levenshtein"], processor=lambda s: s[0])
    0.81818181818181
    g        Nr8   rD   rK   r   )r   rM   )r   r   r   r9   r:   r;   rL   norm_sims           r   normalized_similarityrP     s    N r{{ gbkk sYr]]Yr]]"G#BG<<<IYH$,L0H0H88qPr   r9   r;   r	   c               @    | ||           }  ||          }t           )u  
    Return Editops describing how to turn s1 into s2.

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_hint : int, optional
        Expected distance between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    editops : Editops
        edit operations required to turn s1 into s2

    Notes
    -----
    The alignment is calculated using an algorithm of Heikki Hyyrö, which is
    described [8]_. It has a time complexity and memory usage of ``O([N/64] * M)``.

    References
    ----------
    .. [8] Hyyrö, Heikki. "A Note on Bit-Parallel Alignment Computation."
           Stringology (2004).

    Examples
    --------
    >>> from rapidfuzz.distance import Levenshtein
    >>> for tag, src_pos, dest_pos in Levenshtein.editops("qabxcd", "abycdf"):
    ...    print(("%7s s1[%d] s2[%d]" % (tag, src_pos, dest_pos)))
     delete s1[1] s2[0]
    replace s1[3] s2[2]
     insert s1[6] s2[5]
    )NotImplementedErrorr   r   r9   r;   s       r   editopsrU   r  s+    ^ Yr]]Yr]]
r   r
   c               L    t          | |||                                          S )u  
    Return Opcodes describing how to turn s1 into s2.

    Parameters
    ----------
    s1 : Sequence[Hashable]
        First string to compare.
    s2 : Sequence[Hashable]
        Second string to compare.
    processor : callable, optional
        Optional callable that is used to preprocess the strings before
        comparing them. Default is None, which deactivates this behaviour.
    score_hint : int, optional
        Expected distance between s1 and s2. This is used to select a
        faster implementation. Default is None, which deactivates this behaviour.

    Returns
    -------
    opcodes : Opcodes
        edit operations required to turn s1 into s2

    Notes
    -----
    The alignment is calculated using an algorithm of Heikki Hyyrö, which is
    described [9]_. It has a time complexity and memory usage of ``O([N/64] * M)``.

    References
    ----------
    .. [9] Hyyrö, Heikki. "A Note on Bit-Parallel Alignment Computation."
           Stringology (2004).

    Examples
    --------
    >>> from rapidfuzz.distance import Levenshtein

    >>> a = "qabxcd"
    >>> b = "abycdf"
    >>> for tag, i1, i2, j1, j2 in Levenshtein.opcodes("qabxcd", "abycdf"):
    ...    print(("%7s a[%d:%d] (%s) b[%d:%d] (%s)" %
    ...           (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2])))
     delete a[0:1] (q) b[0:0] ()
      equal a[1:3] (ab) b[0:2] (ab)
    replace a[3:4] (x) b[2:3] (y)
      equal a[4:6] (cd) b[3:5] (cd)
     insert a[6:6] () b[5:6] (f)
    rQ   )rU   
as_opcodesrT   s       r   opcodesrX     s(    j 2rY:FFFQQSSSr   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r   r   r   r<   r9   r=   r:   r>   r;   r>   r   r   )r   r   r   r   r   r<   r9   r=   r:   rH   r;   rH   r   rI   )
r   r   r   r   r9   r=   r;   r>   r   r	   )
r   r   r   r   r9   r=   r;   r>   r   r
   )
__future__r   typingr   r   r   rapidfuzz._utilsr   rapidfuzz.distancer   rapidfuzz.distance._initializer	   r
   r   r(   r7   rA   rG   rM   rP   rU   rX    r   r   <module>r_      s   # " " " " " / / / / / / / / / / $ $ $ $ $ $ $ $ $ $ $ $ ; ; ; ; ; ; ; ;   "   (! ! ! !P ,5:>#!MX MX MX MX MX MXh ,5:>#!8G 8G 8G 8G 8G 8G~ ,5:>!%#:S :S :S :S :S :SB ,5:>!%#QQ QQ QQ QQ QQ QQp ;?!3 3 3 3 3 3t ;?!5T 5T 5T 5T 5T 5T 5T 5Tr   