
def 						__magic_name__ (    __a			:       str						):



     '''simple docstring'''




     UpperCamelCase__				=				''''''
     for ch in key:
          if ch == " " or ch not in key_no_dups and ch.isalpha():
               key_no_dups += ch
     return key_no_dups






def 						__magic_name__ (    __a			:       int						):



     '''simple docstring'''




     UpperCamelCase__				=				[chr(i + 65						) for i in range(26						)]
     # Remove duplicate characters from key
     UpperCamelCase__				=				remove_duplicates(key.upper()						)
     UpperCamelCase__				=				len(__a						)
     # First fill cipher with key characters
     UpperCamelCase__				=				{alphabet[i]: char for i, char in enumerate(__a						)}
     # Then map remaining characters in alphabet to
     # the alphabet from the beginning
     for i in range(len(__a						)       ,		26						):
          UpperCamelCase__				=				alphabet[i - offset]
          # Ensure we are not mapping letters to letters previously mapped
          while char in key:
               offset -= 1
               UpperCamelCase__				=				alphabet[i - offset]
          UpperCamelCase__				=				char
     return cipher_alphabet






def 						__magic_name__ (    __a			:       Tuple       ,		__a			:       List[str]						):



     '''simple docstring'''




     return "".join(cipher_map.get(__a       ,		__a						) for ch in message.upper()						)






def 						__magic_name__ (    __a			:       Dict       ,		__a			:       Tuple						):



     '''simple docstring'''




     UpperCamelCase__				=				{v: k for k, v in cipher_map.items()}
     return "".join(rev_cipher_map.get(__a       ,		__a						) for ch in message.upper()						)






def 						__magic_name__ (    ):



     '''simple docstring'''




     UpperCamelCase__				=				input("""Enter message to encode or decode: """						).strip()
     UpperCamelCase__				=				input("""Enter keyword: """						).strip()
     UpperCamelCase__				=				input("""Encipher or decipher? E/D:"""						).strip()[0].lower()
     try:
          UpperCamelCase__				=				{'''e''': encipher, '''d''': decipher}[option]
     except KeyError:
          raise KeyError("""invalid input option"""						)
     UpperCamelCase__				=				create_cipher_map(__a						)
     print(func(__a       ,		__a						)						)


if __name__ == "__main__":
    import doctest

    doctest.testmod()
    main()






'''simple docstring'''

import logging

import numpy as np
import pytest
from scipy.linalg import eigh

logging.basicConfig(level=logging.INFO, format="""%(message)s""")
def 			__UpperCamelCase       (   UpperCAmelCase     ):
 return input_array.reshape((input_array.size, 1)     )
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 lowercase__				:    Dict  =					np.nan
 for i in range(UpperCAmelCase     ):
  lowercase__				:    Optional[Any]  =					features[:, labels == i]
  lowercase__				:    Optional[Any]  =					data.mean(1     )
  # Centralize the data of class i
  lowercase__				:    Dict  =					data - column_reshape(UpperCAmelCase     )
  if i > 0:
   # If covariance_sum is not None
   covariance_sum += np.dot(UpperCAmelCase		,     centered_data.T     )
  else:
   # If covariance_sum is np.nan (i.e. first loop)
   lowercase__				:    List[str]  =					np.dot(UpperCAmelCase		,     centered_data.T     )

 return covariance_sum / features.shape[1]
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 lowercase__				:    Tuple  =					features.mean(1     )
 lowercase__				:    Dict  =					np.nan
 for i in range(UpperCAmelCase     ):
  lowercase__				:    List[str]  =					features[:, labels == i]
  lowercase__				:    int  =					data.shape[1]
  lowercase__				:    Optional[int]  =					data.mean(1     )
  if i > 0:
   # If covariance_sum is not None
   covariance_sum += device_data * np.dot(
       column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )		,     (column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )).T		,     )
  else:
   # If covariance_sum is np.nan (i.e. first loop)
   lowercase__				:    Optional[int]  =					device_data * np.dot(
       column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )		,     (column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )).T		,     )

 return covariance_sum / features.shape[1]
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase     ):

 # Check if the features have been loaded
 if features.any():
  lowercase__				:    Optional[Any]  =					features.mean(1     )
  # Center the dataset
  lowercase__				:    List[str]  =					features - np.reshape(UpperCAmelCase		,     (data_mean.size, 1)     )
  lowercase__				:    Optional[Any]  =					np.dot(UpperCAmelCase		,     centered_data.T     ) / features.shape[1]
  lowercase__ ,							lowercase__				:    Tuple  =					np.linalg.eigh(UpperCAmelCase     )
  # Take all the columns in the reverse order (-1), and then takes only the first
  lowercase__				:    str  =					eigenvectors[:, ::-1][:, 0:dimensions]
  # Project the database on the new space
  lowercase__				:    Tuple  =					np.dot(filtered_eigenvectors.T		,     UpperCAmelCase     )
  logging.info('''Principal Component Analysis computed'''     )

  return projected_data
 else:
  logging.basicConfig(level=logging.ERROR		,     format='''%(message)s'''		,     force=UpperCAmelCase     )
  logging.error('''Dataset empty'''     )
  raise AssertionError
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 assert classes > dimensions

 # Check if features have been already loaded
 if features.any:
  lowercase__ ,							lowercase__				:    Any  =					eigh(
      covariance_between_classes(UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )		,     covariance_within_classes(UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )		,     )
  lowercase__				:    Optional[int]  =					eigenvectors[:, ::-1][:, :dimensions]
  lowercase__ ,							lowercase__ ,							lowercase__				:    Optional[int]  =					np.linalg.svd(UpperCAmelCase     )
  lowercase__				:    List[str]  =					svd_matrix[:, 0:dimensions]
  lowercase__				:    str  =					np.dot(filtered_svd_matrix.T		,     UpperCAmelCase     )
  logging.info('''Linear Discriminant Analysis computed'''     )

  return projected_data
 else:
  logging.basicConfig(level=logging.ERROR		,     format='''%(message)s'''		,     force=UpperCAmelCase     )
  logging.error('''Dataset empty'''     )
  raise AssertionError
def 			__UpperCamelCase       (   ):
 # Create dummy dataset with 2 classes and 3 features
 lowercase__				:    List[str]  =					np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]     )
 lowercase__				:    Optional[Any]  =					np.array([0, 0, 0, 1, 1]     )
 lowercase__				:    str  =					2
 lowercase__				:    Dict  =					2

 # Assert that the function raises an AssertionError if dimensions > classes
 with pytest.raises(UpperCAmelCase     ) as error_info:
  lowercase__				:    int  =					linear_discriminant_analysis(
      UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )
  if isinstance(UpperCAmelCase		,     np.ndarray     ):
   raise AssertionError(
       '''Did not raise AssertionError for dimensions > classes'''     )
  assert error_info.type is AssertionError
def 			__UpperCamelCase       (   ):
 lowercase__				:    Optional[int]  =					np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]     )
 lowercase__				:    int  =					2
 lowercase__				:    Any  =					np.array([[6.9_2_8_2_0_3_2_3, 8.6_6_0_2_5_4_0_4, 1_0.3_9_2_3_0_4_8_5], [3.0, 3.0, 3.0]]     )

 with pytest.raises(UpperCAmelCase     ) as error_info:
  lowercase__				:    Dict  =					principal_component_analysis(UpperCAmelCase		,     UpperCAmelCase     )
  if not np.allclose(UpperCAmelCase		,     UpperCAmelCase     ):
   raise AssertionError
  assert error_info.type is AssertionError


if __name__ == "__main__":
  import doctest

  doctest.testmod()

