



from __future__ import annotations





def   __snake_case			(    _UpperCAmelCase     ,				_UpperCAmelCase = None     ,				_UpperCAmelCase = None     ,				_UpperCAmelCase = False     ,				)     ->   Tuple:
    __a		 =       cipher_alphabet or [chr(_UpperCAmelCase       ) 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)
        __a		 =       {
            '''a''': 0.0_84_97,
            '''b''': 0.0_14_92,
            '''c''': 0.0_22_02,
            '''d''': 0.0_42_53,
            '''e''': 0.1_11_62,
            '''f''': 0.0_22_28,
            '''g''': 0.0_20_15,
            '''h''': 0.0_60_94,
            '''i''': 0.0_75_46,
            '''j''': 0.0_01_53,
            '''k''': 0.0_12_92,
            '''l''': 0.0_40_25,
            '''m''': 0.0_24_06,
            '''n''': 0.0_67_49,
            '''o''': 0.0_75_07,
            '''p''': 0.0_19_29,
            '''q''': 0.0_00_95,
            '''r''': 0.0_75_87,
            '''s''': 0.0_63_27,
            '''t''': 0.0_93_56,
            '''u''': 0.0_27_58,
            '''v''': 0.0_09_78,
            '''w''': 0.0_25_60,
            '''x''': 0.0_01_50,
            '''y''': 0.0_19_94,
            '''z''': 0.0_00_77,
        }
    else:
        # Custom frequencies dictionary
        __a		 =       frequencies_dict

    if not case_sensitive:
        __a		 =       ciphertext.lower()

    # Chi squared statistic values
    __a		 =       {}

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

        # decrypt the message with the shift
        for letter in ciphertext:
            try:
                # Try to index the letter in the alphabet
                __a		 =       (alphabet_letters.index(letter.lower()       ) - shift) % len(
                    _UpperCAmelCase       )
                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

        __a		 =       0.0

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

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

                    # Complete the chi squared statistic formula
                    __a		 =       ((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
                    __a		 =       decrypted_with_shift.count(_UpperCAmelCase       )

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

                    # Complete the chi squared statistic formula
                    __a		 =       ((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
        __a		 =       (
            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(_UpperCAmelCase       ) -> tuple[float, str]:
        return chi_squared_statistic_values[key]

    __a		 =       min(
        _UpperCAmelCase     ,				key=_UpperCAmelCase     ,				)

    # Get all the data from the most likely cipher (key, decoded message)
    (
        (
        __a		
    ) ,     (
        __a		
    ) ,     		
    )		 =       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,
    )










def   __snake_case			(    _UpperCAmelCase     ,				_UpperCAmelCase = False       ):

    if not isinstance(_UpperCAmelCase     ,				_UpperCAmelCase       ):
        __a		 =       f'Expected string as input, found {type(_UpperCAmelCase       )}'
        raise ValueError(_UpperCAmelCase       )
    if not isinstance(_UpperCAmelCase     ,				_UpperCAmelCase       ):
        __a		 =       f'Expected boolean as use_pascal parameter, found {type(_UpperCAmelCase       )}'
        raise ValueError(_UpperCAmelCase       )

    __a		 =       input_str.split('''_'''       )

    __a		 =       0 if use_pascal else 1

    __a		 =       words[start_index:]

    __a		 =       [word[0].upper() + word[1:] for word in words_to_capitalize]

    __a		 =       '''''' if use_pascal else words[0]

    return "".join([initial_word, *capitalized_words]       )


if __name__ == "__main__":
 from doctest import testmod

 testmod()





