Coverage for kryptic_cypher/cypher/ceasar.py: 94%
53 statements
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-20 18:52 +0000
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-20 18:52 +0000
1"""Caesar cipher implementation for encrypting and decrypting text with a numeric key."""
3from .base import CypherResult, CypherWithKey, ValidationResult
5UPPER_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
6LOWER_ALPHABET = "abcdefghijklmnopqrstuvwxyz"
9def create_alpahbet(key: int):
10 translation_dictionary = {}
11 for cypher_index, original_index in zip(
12 range(key, key + len(UPPER_ALPHABET)),
13 range(len(UPPER_ALPHABET)),
14 ):
15 cypher_index_character = cypher_index % len(UPPER_ALPHABET)
16 translation_dictionary[UPPER_ALPHABET[original_index]] = UPPER_ALPHABET[
17 cypher_index_character
18 ]
20 for cypher_index, original_index in zip(
21 range(key, key + len(LOWER_ALPHABET)),
22 range(len(LOWER_ALPHABET)),
23 ):
24 cypher_index_character = cypher_index % len(LOWER_ALPHABET)
25 translation_dictionary[LOWER_ALPHABET[original_index]] = LOWER_ALPHABET[
26 cypher_index_character
27 ]
29 return translation_dictionary
32def create_reverse_alphabet(key: int):
33 upper_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
34 lower_alphabet = "abcdefghijklmnopqrstuvwxyz"
35 translation_dictionary = {}
36 for cypher_index, original_index in zip(
37 range(key, key + len(upper_alphabet)),
38 range(len(upper_alphabet)),
39 ):
40 cypher_index_character = cypher_index % len(upper_alphabet)
41 translation_dictionary[upper_alphabet[cypher_index_character]] = upper_alphabet[
42 original_index
43 ]
45 for cypher_index, original_index in zip(
46 range(key, key + len(lower_alphabet)),
47 range(len(lower_alphabet)),
48 ):
49 cypher_index_character = cypher_index % len(lower_alphabet)
50 translation_dictionary[lower_alphabet[cypher_index_character]] = lower_alphabet[
51 original_index
52 ]
54 return translation_dictionary
57class Ceasar(CypherWithKey):
58 """
59 The Caeser Cypher uses each letter and shifts it the given number of times in the alphabet.
61 EX:
63 Given Phrase: Caesar
64 Key: 2
66 To encrypt the given phrase we first get the full alphabet and shift each letter by the key.
68 ABCDEFGHIJKLMNOPQRSTUVWXYZ
69 CDEFGHIJKLMNOPQRSTUVWXYZAB
71 After shifting the alphabet we can then input our new letters for our phrase.
73 Encrypted: Ecguct
75 To decrypt just do the opposite to the alphabet with the key shifting.
77 ABCDEFGHIJKLMNOPQRSTUVWXYZ
78 YZABCDEFGHIJKLMNOPQRSTUVWX
80 Again we just input the shifted text into the decoded text.
82 Decoded: Caesar
83 """
85 @classmethod
86 def validate_key(cls, key):
87 if not key.isnumeric():
88 return ValidationResult.fail("Key must be numeric")
89 return ValidationResult.ok()
91 def encode(self, text: str, key: str) -> CypherResult:
92 try:
93 true_key = int(key)
94 except ValueError:
95 return CypherResult.fail(text, "Key must be numeric")
97 if true_key < 0:
98 return CypherResult.fail(text, "Key must be positive")
100 alphabet = create_alpahbet(true_key)
101 encoded_text = ""
102 for letter in text:
103 # If the letter is a space then just add it
104 encoded_text += alphabet.get(letter, letter)
105 return CypherResult.ok(text, encoded_text)
107 def decode(self, text: str, key: str) -> CypherResult:
108 try:
109 true_key = int(key)
110 except ValueError:
111 return CypherResult.fail(text, "Key must be numeric")
113 if true_key < 0:
114 return CypherResult.fail(text, "Key must be positive")
116 alphabet = create_reverse_alphabet(true_key)
117 decoded_text = ""
118 for letter in text:
119 # If the letter is a space then just add it
120 decoded_text += alphabet.get(letter, letter)
121 return CypherResult.ok(text, decoded_text)