Skip to content

Commit a9f3230

Browse files
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
1 parent fc7451f commit a9f3230

File tree

1 file changed

+28
-27
lines changed

1 file changed

+28
-27
lines changed

ciphers/hill_cipher.py

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,33 +50,34 @@ def replace_digits(self, num: int) -> str:
5050
Convert numerical value to its character equivalent.
5151
"""
5252
return self.key_string[num]
53+
5354
def integer_determinant(self, matrix: np.ndarray) -> int:
5455
"""
5556
Calculate determinant of an integer matrix using exact arithmetic.
5657
"""
5758
n = matrix.shape[0]
58-
59+
5960
# Base case for 1x1 matrix
6061
if n == 1:
6162
return matrix[0, 0]
62-
63+
6364
# Base case for 2x2 matrix
6465
if n == 2:
6566
return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0]
66-
67+
6768
det = 0
6869
for j in range(n):
6970
# Create minor matrix by removing first row and j-th column
7071
minor = matrix[1:, :]
7172
minor = np.delete(minor, j, axis=1)
72-
73+
7374
# Recursively calculate determinant of minor
7475
minor_det = self.integer_determinant(minor)
75-
76+
7677
# Calculate cofactor with sign
7778
sign = (-1) ** j
7879
det += sign * matrix[0, j] * minor_det
79-
80+
8081
return det
8182

8283
def check_determinant(self) -> None:
@@ -89,7 +90,7 @@ def check_determinant(self) -> None:
8990
ValueError: If determinant is not coprime with 36
9091
"""
9192
det = self.integer_determinant(self.encrypt_key)
92-
93+
9394
# Ensure positive modulo value
9495
det_mod = det % len(self.key_string)
9596
if det_mod == 0:
@@ -107,14 +108,14 @@ def process_text(self, text: str) -> str:
107108
Prepare text for encryption/decryption.
108109
"""
109110
chars = [char for char in text.upper() if char in self.key_string]
110-
111+
111112
if not chars:
112113
return ""
113-
114+
114115
last = chars[-1]
115116
while len(chars) % self.break_key != 0:
116117
chars.append(last)
117-
118+
118119
return "".join(chars)
119120

120121
def encrypt(self, text: str) -> str:
@@ -124,17 +125,17 @@ def encrypt(self, text: str) -> str:
124125
text = self.process_text(text.upper())
125126
if not text:
126127
return ""
127-
128+
128129
encrypted = ""
129130

130131
for i in range(0, len(text), self.break_key):
131-
batch = text[i:i+self.break_key]
132+
batch = text[i : i + self.break_key]
132133
vec = [self.replace_letters(char) for char in batch]
133134
batch_vec = np.array(vec).reshape(-1, 1)
134-
135+
135136
product = self.encrypt_key @ batch_vec
136137
batch_encrypted = self.modulus(product).flatten().astype(int)
137-
138+
138139
encrypted_batch = "".join(
139140
self.replace_digits(num) for num in batch_encrypted
140141
)
@@ -149,7 +150,7 @@ def make_decrypt_key(self) -> np.ndarray:
149150
n = self.break_key
150151
det = self.integer_determinant(self.encrypt_key)
151152
modulus = len(self.key_string)
152-
153+
153154
# Find modular inverse of determinant
154155
det_mod = det % modulus
155156
det_inv = None
@@ -163,7 +164,7 @@ def make_decrypt_key(self) -> np.ndarray:
163164

164165
# Compute adjugate matrix
165166
adjugate = np.zeros((n, n), dtype=int)
166-
167+
167168
for i in range(n):
168169
for j in range(n):
169170
minor = np.delete(self.encrypt_key, i, axis=0)
@@ -183,18 +184,18 @@ def decrypt(self, text: str) -> str:
183184
text = self.process_text(text.upper())
184185
if not text:
185186
return ""
186-
187+
187188
decrypt_key = self.make_decrypt_key()
188189
decrypted = ""
189190

190191
for i in range(0, len(text), self.break_key):
191-
batch = text[i:i+self.break_key]
192+
batch = text[i : i + self.break_key]
192193
vec = [self.replace_letters(char) for char in batch]
193194
batch_vec = np.array(vec).reshape(-1, 1)
194-
195+
195196
product = decrypt_key @ batch_vec
196197
batch_decrypted = self.modulus(product).flatten().astype(int)
197-
198+
198199
decrypted_batch = "".join(
199200
self.replace_digits(num) for num in batch_decrypted
200201
)
@@ -203,7 +204,6 @@ def decrypt(self, text: str) -> str:
203204
return decrypted
204205

205206

206-
207207
def main() -> None:
208208
"""
209209
Command-line interface for Hill Cipher operations.
@@ -213,14 +213,14 @@ def main() -> None:
213213

214214
print("Enter each row of the encryption key with space separated integers")
215215
for i in range(n):
216-
row = [int(x) for x in input(f"Row {i+1}: ").split()]
216+
row = [int(x) for x in input(f"Row {i + 1}: ").split()]
217217
hill_matrix.append(row)
218218

219219
hc = HillCipher(np.array(hill_matrix))
220220

221221
print("\nWould you like to encrypt or decrypt some text?")
222222
option = input("1. Encrypt\n2. Decrypt\nEnter choice (1/2): ")
223-
223+
224224
if option == "1":
225225
text = input("\nEnter text to encrypt: ")
226226
print("\nEncrypted text:")
@@ -235,20 +235,21 @@ def main() -> None:
235235

236236
if __name__ == "__main__":
237237
import doctest
238+
238239
doctest.testmod()
239-
240+
240241
print("\nRunning sample tests...")
241242
key = np.array([[2, 5], [1, 6]])
242243
cipher = HillCipher(key)
243-
244+
244245
# Test encryption/decryption round trip
245246
plaintext = "HELLO123"
246247
encrypted = cipher.encrypt(plaintext)
247248
decrypted = cipher.decrypt(encrypted)
248-
249+
249250
print(f"\nOriginal text: {plaintext}")
250251
print(f"Encrypted text: {encrypted}")
251252
print(f"Decrypted text: {decrypted}")
252-
253+
253254
# Run CLI interface
254255
main()

0 commit comments

Comments
 (0)