





from __future__ import annotations


def     SCREAMING_SNAKE_CASE			(      lowerCAmelCase    ,       lowerCAmelCase = None    ,       lowerCAmelCase = None    ,       lowerCAmelCase = False    ,       ):
       _UpperCamelCase              =						cipher_alphabet or [chr(lowerCAmelCase					) for i in range(97    ,       123					)]

       # If the argument is None or the user provided an empty dictionary
       if not frequencies_dict:
              # Frequencies of letters in the english language (how much they show up)
              _UpperCamelCase              =						{
                  '''a''': 0.0_8_4_9_7,
                  '''b''': 0.0_1_4_9_2,
                  '''c''': 0.0_2_2_0_2,
                  '''d''': 0.0_4_2_5_3,
                  '''e''': 0.1_1_1_6_2,
                  '''f''': 0.0_2_2_2_8,
                  '''g''': 0.0_2_0_1_5,
                  '''h''': 0.0_6_0_9_4,
                  '''i''': 0.0_7_5_4_6,
                  '''j''': 0.0_0_1_5_3,
                  '''k''': 0.0_1_2_9_2,
                  '''l''': 0.0_4_0_2_5,
                  '''m''': 0.0_2_4_0_6,
                  '''n''': 0.0_6_7_4_9,
                  '''o''': 0.0_7_5_0_7,
                  '''p''': 0.0_1_9_2_9,
                  '''q''': 0.0_0_0_9_5,
                  '''r''': 0.0_7_5_8_7,
                  '''s''': 0.0_6_3_2_7,
                  '''t''': 0.0_9_3_5_6,
                  '''u''': 0.0_2_7_5_8,
                  '''v''': 0.0_0_9_7_8,
                  '''w''': 0.0_2_5_6_0,
                  '''x''': 0.0_0_1_5_0,
                  '''y''': 0.0_1_9_9_4,
                  '''z''': 0.0_0_0_7_7,
              }
       else:
              # Custom frequencies dictionary
              _UpperCamelCase              =						frequencies_dict

       if not case_sensitive:
              _UpperCamelCase              =						ciphertext.lower()

       # Chi squared statistic values
       _UpperCamelCase              =						{}

       # cycle through all of the shifts
       for shift in range(len(lowerCAmelCase					)					):
              _UpperCamelCase              =						''''''

              # decrypt the message with the shift
              for letter in ciphertext:
                     try:
                            # Try to index the letter in the alphabet
                            _UpperCamelCase              =						(alphabet_letters.index(letter.lower()					) - shift) % len(
                                lowerCAmelCase					)
                            decrypted_with_shift += (
                                alphabet_letters[new_key].upper()
                                if case_sensitive and letter.isupper()
                                else alphabet_letters[new_key]
                            )
                     except ValueError:
                            # Append the character if it isn't in the alphabet
                            decrypted_with_shift += letter

              _UpperCamelCase              =						0.0

              # Loop through each letter in the decoded message with the shift
              for letter in decrypted_with_shift:
                     if case_sensitive:
                            _UpperCamelCase              =						letter.lower()
                            if letter in frequencies:
                                   # Get the amount of times the letter occurs in the message
                                   _UpperCamelCase              =						decrypted_with_shift.lower().count(lowerCAmelCase					)

                                   # Get the excepcted amount of times the letter should appear based
                                   # on letter frequencies
                                   _UpperCamelCase              =						frequencies[letter] * occurrences

                                   # Complete the chi squared statistic formula
                                   _UpperCamelCase              =						((occurrences - expected) ** 2) / expected

                                   # Add the margin of error to the total chi squared statistic
                                   chi_squared_statistic += chi_letter_value
                     else:
                            if letter.lower() in frequencies:
                                   # Get the amount of times the letter occurs in the message
                                   _UpperCamelCase              =						decrypted_with_shift.count(lowerCAmelCase					)

                                   # Get the excepcted amount of times the letter should appear based
                                   # on letter frequencies
                                   _UpperCamelCase              =						frequencies[letter] * occurrences

                                   # Complete the chi squared statistic formula
                                   _UpperCamelCase              =						((occurrences - expected) ** 2) / expected

                                   # Add the margin of error to the total chi squared statistic
                                   chi_squared_statistic += chi_letter_value

        # Add the data to the chi_squared_statistic_values dictionary
              _UpperCamelCase              =						(
                  chi_squared_statistic,
                  decrypted_with_shift,
              )

       # Get the most likely cipher by finding the cipher with the smallest chi squared
       # statistic
       def chi_squared_statistic_values_sorting_key(lowerCAmelCase					) -> tuple[float, str]:
              return chi_squared_statistic_values[key]

       _UpperCamelCase              =						min(
           lowerCAmelCase    ,       key=lowerCAmelCase    ,       )

       # Get all the data from the most likely cipher (key, decoded message)
       (
           (
           _UpperCamelCase
       )       ,		(
           _UpperCamelCase
       )       ,		
       )              =						chi_squared_statistic_values[most_likely_cipher]

       # Return the data on the most likely shift
       return (
           most_likely_cipher,
           most_likely_cipher_chi_squared_value,
           decoded_most_likely_cipher,
       )













from __future__ import annotations

import math

import numpy as np
from numpy.linalg import norm


def     SCREAMING_SNAKE_CASE			(      lowerCAmelCase    ,       lowerCAmelCase					):
       return math.sqrt(sum(pow(a - b    ,       2					) for a, b in zip(lowerCAmelCase    ,       lowerCAmelCase					)					)					)


def     SCREAMING_SNAKE_CASE			(      lowerCAmelCase    ,       lowerCAmelCase					):

       if dataset.ndim != value_array.ndim:
              _UpperCamelCase              =						(
                  '''Wrong input data\'s dimensions... '''
                  f'''dataset : {dataset.ndim}, value_array : {value_array.ndim}'''
              )
              raise ValueError(lowerCAmelCase					)

       try:
              if dataset.shape[1] != value_array.shape[1]:
                     _UpperCamelCase              =						(
                         '''Wrong input data\'s shape... '''
                         f'''dataset : {dataset.shape[1]}, value_array : {value_array.shape[1]}'''
                     )
                     raise ValueError(lowerCAmelCase					)
       except IndexError:
              if dataset.ndim != value_array.ndim:
                     raise TypeError('''Wrong shape'''					)

       if dataset.dtype != value_array.dtype:
              _UpperCamelCase              =						(
                  '''Input data have different datatype... '''
                  f'''dataset : {dataset.dtype}, value_array : {value_array.dtype}'''
              )
              raise TypeError(lowerCAmelCase					)

       _UpperCamelCase              =						[]

       for value in value_array:
              _UpperCamelCase              =						euclidean(lowerCAmelCase    ,       dataset[0]					)
              _UpperCamelCase              =						dataset[0].tolist()

              for dataset_value in dataset[1:]:
                     _UpperCamelCase              =						euclidean(lowerCAmelCase    ,       lowerCAmelCase					)

                     if dist > temp_dist:
                            _UpperCamelCase              =						temp_dist
                            _UpperCamelCase              =						dataset_value.tolist()

              answer.append([vector, dist]					)

       return answer


def     SCREAMING_SNAKE_CASE			(      lowerCAmelCase    ,       lowerCAmelCase					):
       return np.dot(lowerCAmelCase    ,       lowerCAmelCase					) / (norm(lowerCAmelCase					) * norm(lowerCAmelCase					))


if __name__ == "__main__":
       import doctest

       doctest.testmod()






