code: 
  
  
  from collections.abc import Callable
  from math import log
  from os import name, system
  from random import gauss, seed
  from typing import TypeVar
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	float     ,       lowerCamelCase__		:	float     ,       lowerCamelCase__		:	int			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			seed(1			)
  			return [gauss(lowerCamelCase__     ,       lowerCamelCase__			) for _ in range(lowerCamelCase__			)]
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	int     ,       lowerCamelCase__		:	list			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			return [k for k in range(lowerCamelCase__			) for _ in range(instance_count[k]			)]
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	int     ,       lowerCamelCase__		:	list			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			return sum(lowerCamelCase__			) / instance_count
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	int     ,       lowerCamelCase__		:	int			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			return instance_count / total_count
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	list     ,       lowerCamelCase__		:	list     ,       lowerCamelCase__		:	int			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			lowerCamelCase								=     []  # An empty list to store all squared differences
  			# iterate over number of elements in items
  			for i in range(len(lowerCamelCase__			)			):
  						# for loop iterates over number of elements in inner layer of items
  						for j in range(len(items[i]			)			):
  									# appending squared differences to 'squared_diff' list
  									squared_diff.append((items[i][j] - means[i]) ** 2			)
  
      # one divided by (the number of all instances - number of classes) multiplied by
      # sum of all squared differences
  			lowerCamelCase								=     len(lowerCamelCase__			)  # Number of classes in dataset
  			return 1 / (total_count - n_classes) * sum(lowerCamelCase__			)
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	list     ,       lowerCamelCase__		:	list     ,       lowerCamelCase__		:	float     ,       lowerCamelCase__		:	list			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			lowerCamelCase								=     []
  			# for loop iterates over number of elements in list
  			for i in range(len(lowerCamelCase__			)			):
  						# for loop iterates over number of inner items of each element
  						for j in range(len(x_items[i]			)			):
  									lowerCamelCase								=     []  # to store all discriminant values of each item as a list
  									# for loop iterates over number of classes we have in our dataset
  									for k in range(len(lowerCamelCase__			)			):
  												# appending values of discriminants for each class to 'temp' list
  												temp.append(
  												    x_items[i][j] * (means[k] / variance)
  												    - (means[k] ** 2 / (2 * variance))
  												    + log(probabilities[k]			)			)
  									# appending discriminant values of each item to 'results' list
  									results.append(lowerCamelCase__			)
  
  			return [result.index(max(lowerCamelCase__			)			) for result in results]
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	list     ,       lowerCamelCase__		:	list			):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			lowerCamelCase								=     sum(1 for i, j in zip(lowerCamelCase__     ,       lowerCamelCase__			) if i == j			)
  			# percentage of accuracy equals to number of correct predictions divided by number
  			# of all data and multiplied by 100
  			return (correct / len(lowerCamelCase__			)) * 100
  
  
  UpperCAmelCase      :						Optional[Any]    =		TypeVar("num")
  
  
  
  
  
  
  def   __lowerCamelCase	(       lowerCamelCase__		:	Callable[[object], num]     ,       lowerCamelCase__		:	str     ,       lowerCamelCase__		:	str     ,       lowerCamelCase__		:	Callable[[num], bool] = lambda lowerCamelCase__			: True     ,       lowerCamelCase__		:	str | None = None     ,       ):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			while True:
  						try:
  									lowerCamelCase								=     input_type(input(lowerCamelCase__			).strip() or default			)
  									if condition(lowerCamelCase__			):
  												return user_input
  									else:
  												print(f'{user_input}: {err_msg}'			)
  												continue
  						except ValueError:
  									print(
  									    f'{user_input}: Incorrect input type, expected {input_type.__name__!r}'			)
  
  
  
  
  
  
  def   __lowerCamelCase	(       ):
  
  
  
  
  
  			'''simple docstring'''
  
  
  
  
  			while True:
  						print(""" Linear Discriminant Analysis """.center(50     ,       """*"""			)			)
  						print("""*""" * 50     ,       """\n"""			)
  						print("""First of all we should specify the number of classes that"""			)
  						print("""we want to generate as training dataset"""			)
  						# Trying to get number of classes
  						lowerCamelCase								=     valid_input(
  						    input_type=lowerCamelCase__     ,       condition=lambda lowerCamelCase__			: x > 0     ,       input_msg="""Enter the number of classes (Data Groupings): """     ,       err_msg="""Number of classes should be positive!"""     ,       )
  
  						print("""-""" * 100			)
  
  						# Trying to get the value of standard deviation
  						lowerCamelCase								=     valid_input(
  						    input_type=lowerCamelCase__     ,       condition=lambda lowerCamelCase__			: x >= 0     ,       input_msg=(
  						        """Enter the value of standard deviation"""
  						        """(Default value is 1.0 for all classes): """
  						    )     ,       err_msg="""Standard deviation should not be negative!"""     ,       default="""1.0"""     ,       )
  
  						print("""-""" * 100			)
  
  						# Trying to get number of instances in classes and theirs means to generate
  						# dataset
  						lowerCamelCase								=     []  # An empty list to store instance counts of classes in dataset
  						for i in range(lowerCamelCase__			):
  									lowerCamelCase								=     valid_input(
  									    input_type=lowerCamelCase__     ,       condition=lambda lowerCamelCase__			: x > 0     ,       input_msg=(f'Enter The number of instances for class_{i+1}: ')     ,       err_msg="""Number of instances should be positive!"""     ,       )
  									counts.append(lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						# An empty list to store values of user-entered means of classes
  						lowerCamelCase								=     []
  						for a in range(lowerCamelCase__			):
  									lowerCamelCase								=     valid_input(
  									    input_type=lowerCamelCase__     ,       input_msg=(f'Enter the value of mean for class_{a+1}: ')     ,       err_msg="""This is an invalid value."""     ,       )
  									user_means.append(lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						print("""Standard deviation: """     ,       lowerCamelCase__			)
  						# print out the number of instances in classes in separated line
  						for i, count in enumerate(lowerCamelCase__     ,       1			):
  									print(f'Number of instances in class_{i} is: {count}'			)
  						print("""-""" * 100			)
  
  						# print out mean values of classes separated line
  						for i, user_mean in enumerate(lowerCamelCase__     ,       1			):
  									print(f'Mean of class_{i} is: {user_mean}'			)
  						print("""-""" * 100			)
  
  						# Generating training dataset drawn from gaussian distribution
  						lowerCamelCase								=     [
  						    gaussian_distribution(user_means[j]     ,       lowerCamelCase__     ,       counts[j]			)
  						    for j in range(lowerCamelCase__			)
  						]
  						print("""Generated Normal Distribution: \n"""     ,       lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						# Generating Ys to detecting corresponding classes
  						lowerCamelCase								=     y_generator(lowerCamelCase__     ,       lowerCamelCase__			)
  						print("""Generated Corresponding Ys: \n"""     ,       lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						# Calculating the value of actual mean for each class
  						lowerCamelCase								=     [calculate_mean(counts[k]     ,       x[k]			) for k in range(lowerCamelCase__			)]
  						# for loop iterates over number of elements in 'actual_means' list and print
  						# out them in separated line
  						for i, actual_mean in enumerate(lowerCamelCase__     ,       1			):
  									print(f'Actual(Real) mean of class_{i} is: {actual_mean}'			)
  						print("""-""" * 100			)
  
  						# Calculating the value of probabilities for each class
  						lowerCamelCase								=     [
  						    calculate_probabilities(counts[i]     ,       sum(lowerCamelCase__			)			) for i in range(lowerCamelCase__			)
  						]
  
  						# for loop iterates over number of elements in 'probabilities' list and print
  						# out them in separated line
  						for i, probability in enumerate(lowerCamelCase__     ,       1			):
  									print(f'Probability of class_{i} is: {probability}'			)
  						print("""-""" * 100			)
  
  						# Calculating the values of variance for each class
  						lowerCamelCase								=     calculate_variance(lowerCamelCase__     ,       lowerCamelCase__     ,       sum(lowerCamelCase__			)			)
  						print("""Variance: """     ,       lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						# Predicting Y values
  						# storing predicted Y values in 'pre_indexes' variable
  						lowerCamelCase								=     predict_y_values(lowerCamelCase__     ,       lowerCamelCase__     ,       lowerCamelCase__     ,       lowerCamelCase__			)
  						print("""-""" * 100			)
  
  						# Calculating Accuracy of the model
  						print(f'Accuracy: {accuracy(lowerCamelCase__     ,       lowerCamelCase__			)}'			)
  						print("""-""" * 100			)
  						print(""" DONE """.center(100     ,       """+"""			)			)
  
  						if input("""Press any key to restart or 'q' for quit: """			).strip().lower() == "q":
  									print("""\n""" + """GoodBye!""".center(100     ,       """-"""			) + """\n"""			)
  									break
  						system("""cls""" if name == """nt""" else """clear"""			)  # noqa: S605
  
  
  if __name__ == "__main__":
  		main()
  
  
style_context: 
  
  
  import unittest
  
  from cer import CER
  
  
  UpperCAmelCase      :						Union[str, Any]    =		CER()
  
  
  
  
  
  
  
  class 					__lowercase					(       unittest.TestCase     ):
  
  
  
  		"""simple docstring"""
  
  		def 				__A      (   self  )     ->   Optional[int]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""White House"""]
  					lowerCamelCase								=     ["""white house"""]
  					# S = 2, D = 0, I = 0, N = 11, CER = 2 / 11
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.1818181818  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   List[str]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""were wolf"""]
  					lowerCamelCase								=     ["""werewolf"""]
  					# S = 0, D = 0, I = 1, N = 9, CER = 1 / 9
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.1111111  ) < 1e-6  )
  
  					lowerCamelCase								=     ["""werewolf"""]
  					lowerCamelCase								=     ["""weae     wolf"""]
  					# S = 1, D = 1, I = 0, N = 8, CER = 0.25
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.25  ) < 1e-6  )
  
  					# consecutive whitespaces case 1
  					lowerCamelCase								=     ["""were wolf"""]
  					lowerCamelCase								=     ["""were               wolf"""]
  					# S = 0, D = 0, I = 0, N = 9, CER = 0
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.0  ) < 1e-6  )
  
  					# consecutive whitespaces case 2
  					lowerCamelCase								=     ["""were   wolf"""]
  					lowerCamelCase								=     ["""were               wolf"""]
  					# S = 0, D = 0, I = 0, N = 9, CER = 0
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.0  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   str:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""werewolf"""]
  					lowerCamelCase								=     ["""weaewolf"""]
  					# S = 1, D = 0, I = 0, N = 8, CER = 0.125
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.125  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   Tuple:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""werewolf"""]
  					lowerCamelCase								=     ["""wereawolf"""]
  					# S = 0, D = 1, I = 0, N = 8, CER = 0.125
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.125  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   List[Any]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""werewolf"""]
  					lowerCamelCase								=     ["""wereolf"""]
  					# S = 0, D = 0, I = 1, N = 8, CER = 0.125
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.125  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   Tuple:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""werewolf"""]
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertEqual(A		,			0.0  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   List[str]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""werewolf""", """I am your father"""]
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertEqual(A		,			0.0  )
  
  					lowerCamelCase								=     ["""werewolf""", """I am your father""", """doge"""]
  					lowerCamelCase								=     ["""werxwolf""", """I       am your father""", """doge"""]
  					# S = 1, D = 0, I = 0, N = 28, CER = 1 / 28
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.03571428  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   List[Any]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""My hovercraft""", """is full of eels"""]
  					lowerCamelCase								=     ["""My hovercraft is full""", """ of eels"""]
  					# S = 0, D = 0, I = 2, N = 28, CER = 2 / 28
  					# whitespace at the front of " of eels" will be strip during preporcessing
  					# so need to insert 2 whitespaces
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A		,			concatenate_texts=A  )
  					self.assertTrue(abs(char_error_rate - 0.071428  ) < 1e-6  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   Optional[int]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     ["""我能吞下玻璃而不伤身体"""]
  					lowerCamelCase								=     [""" 能吞虾玻璃而 不霜身体啦"""]
  					# S = 3, D = 2, I = 0, N = 11, CER = 5 / 11
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.4545454545  ) < 1e-6  )
  
  					lowerCamelCase								=     ["""我能吞下玻璃""", """而不伤身体"""]
  					lowerCamelCase								=     ["""我    能 吞 下 玻 璃""", """而不伤身体"""]
  					# S = 0, D = 5, I = 0, N = 11, CER = 5 / 11
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertTrue(abs(char_error_rate - 0.454545454545  ) < 1e-6  )
  
  					lowerCamelCase								=     ["""我能吞下玻璃而不伤身体"""]
  					lowerCamelCase								=     cer.compute(predictions=A		,			references=A  )
  					self.assertFalse(A		,			0.0  )
  
  
  
  
  
  
  
  		def 				__A      (   self  )     ->   Optional[int]:
  
  
  
  
  
  
  
  					'''simple docstring'''
  
  
  
  
  
  
  
  					lowerCamelCase								=     [""""""]
  					lowerCamelCase								=     ["""Hypothesis"""]
  					with self.assertRaises(A  ):
  								cer.compute(predictions=A		,			references=A  )
  
  
  if __name__ == "__main__":
  		unittest.main()
  
  