



import argparse
import struct
import unittest







class     __lowerCAmelCase					:



			def __init__(		self     :						Optional[Any]				,	A     :						Optional[int])     ->					None:



						"""simple docstring"""






						_UpperCAmelCase	 =     data

						# Initialize hash values
						_UpperCAmelCase	 =     [
						    0X6a09e667,
						    0Xbb67ae85,
						    0X3c6ef372,
						    0Xa54ff53a,
						    0X510e527f,
						    0X9b05688c,
						    0X1f83d9ab,
						    0X5be0cd19,
						]

						# Initialize round constants
						_UpperCAmelCase	 =     [
						    0X428a2f98,
						    0X71374491,
						    0Xb5c0fbcf,
						    0Xe9b5dba5,
						    0X3956c25b,
						    0X59f111f1,
						    0X923f82a4,
						    0Xab1c5ed5,
						    0Xd807aa98,
						    0X12835b01,
						    0X243185be,
						    0X550c7dc3,
						    0X72be5d74,
						    0X80deb1fe,
						    0X9bdc06a7,
						    0Xc19bf174,
						    0Xe49b69c1,
						    0Xefbe4786,
						    0X0fc19dc6,
						    0X240ca1cc,
						    0X2de92c6f,
						    0X4a7484aa,
						    0X5cb0a9dc,
						    0X76f988da,
						    0X983e5152,
						    0Xa831c66d,
						    0Xb00327c8,
						    0Xbf597fc7,
						    0Xc6e00bf3,
						    0Xd5a79147,
						    0X06ca6351,
						    0X14292967,
						    0X27b70a85,
						    0X2e1b2138,
						    0X4d2c6dfc,
						    0X53380d13,
						    0X650a7354,
						    0X766a0abb,
						    0X81c2c92e,
						    0X92722c85,
						    0Xa2bfe8a1,
						    0Xa81a664b,
						    0Xc24b8b70,
						    0Xc76c51a3,
						    0Xd192e819,
						    0Xd6990624,
						    0Xf40e3585,
						    0X106aa070,
						    0X19a4c116,
						    0X1e376c08,
						    0X2748774c,
						    0X34b0bcb5,
						    0X391c0cb3,
						    0X4ed8aa4a,
						    0X5b9cca4f,
						    0X682e6ff3,
						    0X748f82ee,
						    0X78a5636f,
						    0X84c87814,
						    0X8cc70208,
						    0X90befffa,
						    0Xa4506ceb,
						    0Xbef9a3f7,
						    0Xc67178f2,
						]

						_UpperCAmelCase	 =     self.preprocessing(self.data)
						self.final_hash()



			@staticmethod
			def 					_lowerCamelCase (		A     :						Tuple)     ->					bytes:



						"""simple docstring"""






						_UpperCAmelCase	 =     B'\x80' + (B'\x00' * (63 - (len(lowerCamelCase_) + 8) % 64))
						_UpperCAmelCase	 =     struct.pack('>Q'				,	(len(lowerCamelCase_) * 8))
						return data + padding + big_endian_integer



			def 					_lowerCamelCase (		self     :						Optional[Any])     ->					None:



						"""simple docstring"""






						_UpperCAmelCase	 =     [
						    self.preprocessed_data[x : x + 64]
						    for x in range(0				,	len(self.preprocessed_data)				,	64)
						]

						for block in self.blocks:
									# Convert the given block into a list of 4 byte integers
									_UpperCAmelCase	 =     list(struct.unpack('>16L'				,	lowerCamelCase_))
									# add 48 0-ed integers
									words += [0] * 48

									_UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase	 =     self.hashes

									for index in range(0				,	64):
												if index > 15:
															# modify the zero-ed indexes at the end of the array
															_UpperCAmelCase	 =     (
															    self.ror(words[index - 15]				,	7)
															    ^ self.ror(words[index - 15]				,	18)
															    ^ (words[index - 15] >> 3)
															)
															_UpperCAmelCase	 =     (
															    self.ror(words[index - 2]				,	17)
															    ^ self.ror(words[index - 2]				,	19)
															    ^ (words[index - 2] >> 10)
															)

															_UpperCAmelCase	 =     (
															    words[index - 16] + sa + words[index - 7] + sa
															) % 0X100000000

												# Compression
												_UpperCAmelCase	 =     self.ror(lowerCamelCase_				,	6) ^ self.ror(lowerCamelCase_				,	11) ^ self.ror(lowerCamelCase_				,	25)
												_UpperCAmelCase	 =     (e & f) ^ ((~e & 0Xffffffff) & g)
												_UpperCAmelCase	 =     (
												    h + sa + ch + self.round_constants[index] + words[index]
												) % 0X100000000
												_UpperCAmelCase	 =     self.ror(lowerCamelCase_				,	2) ^ self.ror(lowerCamelCase_				,	13) ^ self.ror(lowerCamelCase_				,	22)
												_UpperCAmelCase	 =     (a & b) ^ (a & c) ^ (b & c)
												_UpperCAmelCase	 =     (sa + maj) % 0X100000000

												_UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase ,  _UpperCAmelCase	 =     (
												    g,
												    f,
												    e,
												    ((d + tempa) % 0X100000000),
												    c,
												    b,
												    a,
												    ((tempa + tempa) % 0X100000000),
												)

									_UpperCAmelCase	 =     [a, b, c, d, e, f, g, h]

									# Modify final values
									_UpperCAmelCase	 =     [
									    ((element + mutated_hash_values[index]) % 0X100000000)
									    for index, element in enumerate(self.hashes)
									]

						_UpperCAmelCase	 =     ''.join([hex(lowerCamelCase_)[2:].zfill(8) for value in self.hashes])



			def 					_lowerCamelCase (		self     :						Union[str, Any]				,	A     :						int				,	A     :						str)     ->					int:



						"""simple docstring"""






						return 0Xffffffff & (value << (32 - rotations)) | (value >> rotations)







class     __lowerCAmelCase					(    unittest.TestCase		):



			def 					_lowerCamelCase (		self     :						List[Any])     ->					None:



						"""simple docstring"""






						import hashlib

						_UpperCAmelCase	 =     bytes('Test String'				,	'utf-8')
						self.assertEqual(SHAaaa(lowerCamelCase_).hash				,	hashlib.shaaaa(lowerCamelCase_).hexdigest())





def 							A			(  )       ->				None:







			'''simple docstring'''
			import doctest

			doctest.testmod()

			_UpperCAmelCase	 =     argparse.ArgumentParser()
			parser.add_argument(
			    '-s'							,     '--string'							,     dest='input_string'							,     default='Hello World!! Welcome to Cryptography'							,     help='Hash the string'							,     )
			parser.add_argument(
			    '-f'							,     '--file'							,     dest='input_file'							,     help='Hash contents of a file'					)

			_UpperCAmelCase	 =     parser.parse_args()

			_UpperCAmelCase	 =     args.input_string

			# hash input should be a bytestring
			if args.input_file:
						with open(args.input_file							,     'rb'					) as f:
									_UpperCAmelCase	 =     f.read()
			else:
						_UpperCAmelCase	 =     bytes(_UpperCAmelCase							,     'utf-8'					)

			print(SHAaaa(_UpperCAmelCase					).hash					)


if __name__ == "__main__":
	main()





from collections import Counter
from timeit import timeit





def 							A			(  _UpperCAmelCase       :     str = ""							,     )       ->				bool:







			'''simple docstring'''
			return sum(c % 2 for c in Counter(input_str.replace(' '							,     ''					).lower()					).values()					) < 2





def 							A			(  _UpperCAmelCase       :     str = ""					)       ->				bool:







			'''simple docstring'''
			if len(_UpperCAmelCase					) == 0:
						return True
			_UpperCAmelCase	 =     input_str.replace(' '							,     ''					).lower()
			# character_freq_dict: Stores the frequency of every character in the input string
			_UpperCAmelCase	 =     {}

			for character in lower_case_input_str:
						_UpperCAmelCase	 =     character_freq_dict.get(_UpperCAmelCase							,     0					) + 1
			_UpperCAmelCase	 =     0

			for character_count in character_freq_dict.values():
						if character_count % 2:
									odd_char += 1
			if odd_char > 1:
						return False
			return True





def 							A			(  _UpperCAmelCase       :     str = ""					)       ->				None:







			'''simple docstring'''
			print('\nFor string = '							,     _UpperCAmelCase							,     ':'					)
			print(
			    '> can_string_be_rearranged_as_palindrome_counter()'							,     '\tans ='							,     can_string_be_rearranged_as_palindrome_counter(_UpperCAmelCase					)							,     '\ttime ='							,     timeit(
			        'z.can_string_be_rearranged_as_palindrome_counter(z.check_str)'							,     setup='import __main__ as z'							,     )							,     'seconds'							,     )
			print(
			    '> can_string_be_rearranged_as_palindrome()'							,     '\tans ='							,     can_string_be_rearranged_as_palindrome(_UpperCAmelCase					)							,     '\ttime ='							,     timeit(
			        'z.can_string_be_rearranged_as_palindrome(z.check_str)'							,     setup='import __main__ as z'							,     )							,     'seconds'							,     )


if __name__ == "__main__":
							UpperCAmelCase__     = input(
							    "Enter string to determine if it can be rearranged as a palindrome or not: "
							).strip()
							benchmark(check_str)
							UpperCAmelCase__     = can_string_be_rearranged_as_palindrome_counter(check_str)
							print(f"""{check_str} can {"" if status else "not "}be rearranged as a palindrome""")
