




"""simple docstring"""







import argparse
import hashlib  # hashlib is only used inside the Test class
import struct

class       lowerCAmelCase__       :


				"""simple docstring"""





				def __init__(     self					:	List[str]    ,   lowercase__					:	Union[str, Any]						):
						__lowercase				:		str												=				data
						__lowercase				:		int												=				[0x67_452_301, 0xEF_CDA_B89, 0x98_BAD_CFE, 0x10_325_476, 0xC3_D2E_1F0]



				@staticmethod
				def       snake_case    (     lowercase__					:	Any    ,   lowercase__					:	Optional[int]						):
						return ((n << b) | (n >> (3_2 - b))) & 0xFF_FFF_FFF



				def       snake_case    (     self					:	int						):
						__lowercase				:		str												=				b"\x80" + b"\x00" * (6_3 - (len(self.data						) + 8) % 6_4)
						__lowercase				:		Any												=				self.data + padding + struct.pack(">Q"    ,   8 * len(self.data						)						)
						return padded_data



				def       snake_case    (     self					:	Union[str, Any]						):
						return [
						    self.padded_data[i : i + 6_4] for i in range(0    ,   len(self.padded_data						)    ,   6_4						)
						]



				def       snake_case    (     self					:	List[Any]    ,   lowercase__					:	Dict						):
						__lowercase				:		int												=				list(struct.unpack(">16L"    ,   lowercase__						)						) + [0] * 6_4
						for i in range(1_6    ,   8_0						):
								__lowercase				:		List[Any]												=				self.rotate((w[i - 3] ^ w[i - 8] ^ w[i - 1_4] ^ w[i - 1_6])    ,   1						)
						return w



				def       snake_case    (     self					:	List[str]						):
						__lowercase				:		Tuple												=				self.padding()
						__lowercase				:		Optional[int]												=				self.split_blocks()
						for block in self.blocks:
								__lowercase				:		str												=				self.expand_block(lowercase__						)
								__lowercase				:		List[Any]												=				self.h
								for i in range(0    ,   8_0						):
										if 0 <= i < 2_0:
												__lowercase				:		Optional[Any]												=				(b & c) | ((~b) & d)
												__lowercase				:		int												=				0x5A_827_999
										elif 2_0 <= i < 4_0:
												__lowercase				:		Dict												=				b ^ c ^ d
												__lowercase				:		Tuple												=				0x6E_D9E_BA1
										elif 4_0 <= i < 6_0:
												__lowercase				:		List[str]												=				(b & c) | (b & d) | (c & d)
												__lowercase				:		Optional[int]												=				0x8F_1BB_CDC
										elif 6_0 <= i < 8_0:
												__lowercase				:		Any												=				b ^ c ^ d
												__lowercase				:		Optional[Any]												=				0xCA_62C_1D6
										__lowercase				:		Any												=				(
										    self.rotate(lowercase__    ,   5						) + f + e + k + expanded_block[i] & 0xFF_FFF_FFF,
										    a,
										    self.rotate(lowercase__    ,   3_0						),
										    c,
										    d,
										)
								__lowercase				:		List[str]												=				(
								    self.h[0] + a & 0xFF_FFF_FFF,
								    self.h[1] + b & 0xFF_FFF_FFF,
								    self.h[2] + c & 0xFF_FFF_FFF,
								    self.h[3] + d & 0xFF_FFF_FFF,
								    self.h[4] + e & 0xFF_FFF_FFF,
								)
						return ("{:08x}" * 5).format(*self.h						)





def 						snake_case__       (					)			->Tuple:






		"""simple docstring"""


		__lowercase				:		int												=				b"Test String"
		assert SHAaHash(_lowerCamelCase				).final_hash() == hashlib.shaa(_lowerCamelCase				).hexdigest()  # noqa: S324

def 						snake_case__       (					)			->Tuple:






		"""simple docstring"""


		__lowercase				:		Dict												=				argparse.ArgumentParser(description="Process some strings or files"				)
		parser.add_argument(
		    "--string",  dest="input_string",  default="Hello World!! Welcome to Cryptography",  help="Hash the string",  )
		parser.add_argument("--file",  dest="input_file",  help="Hash contents of a file"				)
		__lowercase				:		int												=				parser.parse_args()
		__lowercase				:		str												=				args.input_string
		# In any case hash input should be a bytestring
		if args.input_file:
				with open(args.input_file,  "rb"				) as f:
						__lowercase				:		Dict												=				f.read()
		else:
				__lowercase				:		str												=				bytes(_lowerCamelCase,  "utf-8"				)
		print(SHAaHash(_lowerCamelCase				).final_hash()				)


if __name__ == "__main__":
						main()
						import doctest

						doctest.testmod()






"""simple docstring"""







from __future__ import annotations

import math

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase				)			->list:






		"""simple docstring"""


		if len(_lowerCamelCase				) != 2 or len(a[0]				) != 2 or len(_lowerCamelCase				) != 2 or len(b[0]				) != 2:
				raise Exception("Matrices are not 2x2"				)
		__lowercase				:		Tuple												=				[
		    [a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]],
		    [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]],
		]
		return new_matrix

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase				)			->Dict:






		"""simple docstring"""


		return [
		    [matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]				)				)]
		    for row in range(len(_lowerCamelCase				)				)
		]

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase				)			->Tuple:






		"""simple docstring"""


		return [
		    [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]				)				)]
		    for row in range(len(_lowerCamelCase				)				)
		]

def 						snake_case__       (					_lowerCamelCase				)			->tuple[list, list, list, list]:






		"""simple docstring"""


		if len(_lowerCamelCase				) % 2 != 0 or len(a[0]				) % 2 != 0:
				raise Exception("Odd matrices are not supported!"				)

		__lowercase				:		Tuple												=				len(_lowerCamelCase				)
		__lowercase				:		Any												=				matrix_length // 2

		__lowercase				:		Dict												=				[[a[i][j] for j in range(_lowerCamelCase,  _lowerCamelCase				)] for i in range(_lowerCamelCase				)]
		__lowercase				:		List[str]												=				[
		    [a[i][j] for j in range(_lowerCamelCase,  _lowerCamelCase				)] for i in range(_lowerCamelCase,  _lowerCamelCase				)
		]

		__lowercase				:		Union[str, Any]												=				[[a[i][j] for j in range(_lowerCamelCase				)] for i in range(_lowerCamelCase				)]
		__lowercase				:		List[str]												=				[[a[i][j] for j in range(_lowerCamelCase				)] for i in range(_lowerCamelCase,  _lowerCamelCase				)]

		return top_left, top_right, bot_left, bot_right

def 						snake_case__       (					_lowerCamelCase				)			->tuple[int, int]:






		"""simple docstring"""


		return len(_lowerCamelCase				), len(matrix[0]				)

def 						snake_case__       (					_lowerCamelCase				)			->None:






		"""simple docstring"""


		print("\n".join(str(_lowerCamelCase				) for line in matrix				)				)

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase				)			->list:






		"""simple docstring"""


		if matrix_dimensions(_lowerCamelCase				) == (2, 2):
				return default_matrix_multiplication(_lowerCamelCase,  _lowerCamelCase				)

		__lowercase						,__lowercase						,__lowercase						,__lowercase				:		Optional[Any]												=				split_matrix(_lowerCamelCase				)
		__lowercase						,__lowercase						,__lowercase						,__lowercase				:		Any												=				split_matrix(_lowerCamelCase				)

		__lowercase				:		str												=				actual_strassen(_lowerCamelCase,  matrix_subtraction(_lowerCamelCase,  _lowerCamelCase				)				)
		__lowercase				:		Dict												=				actual_strassen(matrix_addition(_lowerCamelCase,  _lowerCamelCase				),  _lowerCamelCase				)
		__lowercase				:		Union[str, Any]												=				actual_strassen(matrix_addition(_lowerCamelCase,  _lowerCamelCase				),  _lowerCamelCase				)
		__lowercase				:		Any												=				actual_strassen(_lowerCamelCase,  matrix_subtraction(_lowerCamelCase,  _lowerCamelCase				)				)
		__lowercase				:		List[Any]												=				actual_strassen(matrix_addition(_lowerCamelCase,  _lowerCamelCase				),  matrix_addition(_lowerCamelCase,  _lowerCamelCase				)				)
		__lowercase				:		Optional[int]												=				actual_strassen(matrix_subtraction(_lowerCamelCase,  _lowerCamelCase				),  matrix_addition(_lowerCamelCase,  _lowerCamelCase				)				)
		__lowercase				:		Optional[Any]												=				actual_strassen(matrix_subtraction(_lowerCamelCase,  _lowerCamelCase				),  matrix_addition(_lowerCamelCase,  _lowerCamelCase				)				)

		__lowercase				:		str												=				matrix_addition(matrix_subtraction(matrix_addition(_lowerCamelCase,  _lowerCamelCase				),  _lowerCamelCase				),  _lowerCamelCase				)
		__lowercase				:		Dict												=				matrix_addition(_lowerCamelCase,  _lowerCamelCase				)
		__lowercase				:		int												=				matrix_addition(_lowerCamelCase,  _lowerCamelCase				)
		__lowercase				:		Union[str, Any]												=				matrix_subtraction(matrix_subtraction(matrix_addition(_lowerCamelCase,  _lowerCamelCase				),  _lowerCamelCase				),  _lowerCamelCase				)

		# construct the new matrix from our 4 quadrants
		__lowercase				:		Optional[int]												=				[]
		for i in range(len(_lowerCamelCase				)				):
				new_matrix.append(top_left[i] + top_right[i]				)
		for i in range(len(_lowerCamelCase				)				):
				new_matrix.append(bot_left[i] + bot_right[i]				)
		return new_matrix

def 						snake_case__       (					_lowerCamelCase,  _lowerCamelCase				)			->list:






		"""simple docstring"""


		if matrix_dimensions(_lowerCamelCase				)[1] != matrix_dimensions(_lowerCamelCase				)[0]:
				__lowercase				:		int												=				(
				    "Unable to multiply these matrices, please check the dimensions.\n"
				    F'Matrix A: {matrixa}\n'
				    F'Matrix B: {matrixa}'
				)
				raise Exception(_lowerCamelCase				)
		__lowercase				:		List[Any]												=				matrix_dimensions(_lowerCamelCase				)
		__lowercase				:		Tuple												=				matrix_dimensions(_lowerCamelCase				)

		if dimensiona[0] == dimensiona[1] and dimensiona[0] == dimensiona[1]:
				return [matrixa, matrixa]

		__lowercase				:		int												=				max(*_lowerCamelCase,  *_lowerCamelCase				)
		__lowercase				:		Any												=				int(math.pow(2,  math.ceil(math.loga(_lowerCamelCase				)				)				)				)
		__lowercase				:		Dict												=				matrixa
		__lowercase				:		str												=				matrixa

		# Adding zeros to the matrices so that the arrays dimensions are the same and also
		# power of 2
		for i in range(0,  _lowerCamelCase				):
				if i < dimensiona[0]:
						for _ in range(dimensiona[1],  _lowerCamelCase				):
								new_matrixa[i].append(0				)
				else:
						new_matrixa.append([0] * maxim				)
				if i < dimensiona[0]:
						for _ in range(dimensiona[1],  _lowerCamelCase				):
								new_matrixa[i].append(0				)
				else:
						new_matrixa.append([0] * maxim				)

		__lowercase				:		Dict												=				actual_strassen(_lowerCamelCase,  _lowerCamelCase				)

		# Removing the additional zeros
		for i in range(0,  _lowerCamelCase				):
				if i < dimensiona[0]:
						for _ in range(dimensiona[1],  _lowerCamelCase				):
								final_matrix[i].pop()
				else:
						final_matrix.pop()
		return final_matrix


if __name__ == "__main__":
						__A   :  int					=      [
						    [2, 3, 4, 5],
						    [6, 4, 3, 1],
						    [2, 3, 6, 7],
						    [3, 1, 2, 4],
						    [2, 3, 4, 5],
						    [6, 4, 3, 1],
						    [2, 3, 6, 7],
						    [3, 1, 2, 4],
						    [2, 3, 4, 5],
						    [6, 2, 3, 1],
						]
						__A   :  Union[str, Any]					=      [[0, 2, 1, 1], [1_6, 2, 3, 3], [2, 2, 7, 7], [1_3, 1_1, 2_2, 4]]
						print(strassen(matrixa, matrixa))
