- Notifications
You must be signed in to change notification settings - Fork 46.7k
/
Copy pathmixed_keyword_cypher.py
75 lines (62 loc) · 2.5 KB
/
mixed_keyword_cypher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
fromstringimportascii_uppercase
defmixed_keyword(
keyword: str, plaintext: str, verbose: bool=False, alphabet: str=ascii_uppercase
) ->str:
"""
For keyword: hello
H E L O
A B C D
F G I J
K M N P
Q R S T
U V W X
Y Z
and map vertically
>>> mixed_keyword("college", "UNIVERSITY", True) # doctest: +NORMALIZE_WHITESPACE
{'A': 'C', 'B': 'A', 'C': 'I', 'D': 'P', 'E': 'U', 'F': 'Z', 'G': 'O', 'H': 'B',
'I': 'J', 'J': 'Q', 'K': 'V', 'L': 'L', 'M': 'D', 'N': 'K', 'O': 'R', 'P': 'W',
'Q': 'E', 'R': 'F', 'S': 'M', 'T': 'S', 'U': 'X', 'V': 'G', 'W': 'H', 'X': 'N',
'Y': 'T', 'Z': 'Y'}
'XKJGUFMJST'
>>> mixed_keyword("college", "UNIVERSITY", False) # doctest: +NORMALIZE_WHITESPACE
'XKJGUFMJST'
"""
keyword=keyword.upper()
plaintext=plaintext.upper()
alphabet_set=set(alphabet)
# create a list of unique characters in the keyword - their order matters
# it determines how we will map plaintext characters to the ciphertext
unique_chars= []
forcharinkeyword:
ifcharinalphabet_setandcharnotinunique_chars:
unique_chars.append(char)
# the number of those unique characters will determine the number of rows
num_unique_chars_in_keyword=len(unique_chars)
# create a shifted version of the alphabet
shifted_alphabet=unique_chars+ [
charforcharinalphabetifcharnotinunique_chars
]
# create a modified alphabet by splitting the shifted alphabet into rows
modified_alphabet= [
shifted_alphabet[k : k+num_unique_chars_in_keyword]
forkinrange(0, 26, num_unique_chars_in_keyword)
]
# map the alphabet characters to the modified alphabet characters
# going 'vertically' through the modified alphabet - consider columns first
mapping= {}
letter_index=0
forcolumninrange(num_unique_chars_in_keyword):
forrowinmodified_alphabet:
# if current row (the last one) is too short, break out of loop
iflen(row) <=column:
break
# map current letter to letter in modified alphabet
mapping[alphabet[letter_index]] =row[column]
letter_index+=1
ifverbose:
print(mapping)
# create the encrypted text by mapping the plaintext to the modified alphabet
return"".join(mapping.get(char, char) forcharinplaintext)
if__name__=="__main__":
# example use
print(mixed_keyword("college", "UNIVERSITY"))