Skip to content

Commit 7a44f16

Browse files
authored
Added rail fence cipher (TheAlgorithms#3188)
* Added rail fence cipher * Update rail_fence_cipher.py * Update rail_fence_cipher.py
1 parent cc0678b commit 7a44f16

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

Diff for: ciphers/rail_fence_cipher.py

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
""" https://en.wikipedia.org/wiki/Rail_fence_cipher """
2+
3+
4+
def encrypt(input_string: str, key: int) -> str:
5+
"""
6+
Shuffles the character of a string by placing each of them
7+
in a grid (the height is dependent on the key) in a zigzag
8+
formation and reading it left to right.
9+
10+
>>> encrypt("Hello World", 4)
11+
'HWe olordll'
12+
13+
>>> encrypt("This is a message", 0)
14+
Traceback (most recent call last):
15+
...
16+
ValueError: Height of grid can't be 0 or negative
17+
18+
>>> encrypt(b"This is a byte string", 5)
19+
Traceback (most recent call last):
20+
...
21+
TypeError: sequence item 0: expected str instance, int found
22+
"""
23+
grid = [[] for _ in range(key)]
24+
lowest = key - 1
25+
26+
if key <= 0:
27+
raise ValueError("Height of grid can't be 0 or negative")
28+
if key == 1 or len(input_string) <= key:
29+
return input_string
30+
31+
for position, character in enumerate(input_string):
32+
num = position % (lowest * 2) # puts it in bounds
33+
num = min(num, lowest * 2 - num) # creates zigzag pattern
34+
grid[num].append(character)
35+
grid = ["".join(row) for row in grid]
36+
output_string = "".join(grid)
37+
38+
return output_string
39+
40+
41+
def decrypt(input_string: str, key: int) -> str:
42+
"""
43+
Generates a template based on the key and fills it in with
44+
the characters of the input string and then reading it in
45+
a zigzag formation.
46+
47+
>>> decrypt("HWe olordll", 4)
48+
'Hello World'
49+
50+
>>> decrypt("This is a message", -10)
51+
Traceback (most recent call last):
52+
...
53+
ValueError: Height of grid can't be 0 or negative
54+
55+
>>> decrypt("My key is very big", 100)
56+
'My key is very big'
57+
"""
58+
grid = []
59+
lowest = key - 1
60+
61+
if key <= 0:
62+
raise ValueError("Height of grid can't be 0 or negative")
63+
if key == 1:
64+
return input_string
65+
66+
temp_grid = [[] for _ in range(key)] # generates template
67+
for position in range(len(input_string)):
68+
num = position % (lowest * 2) # puts it in bounds
69+
num = min(num, lowest * 2 - num) # creates zigzag pattern
70+
temp_grid[num].append("*")
71+
72+
counter = 0
73+
for row in temp_grid: # fills in the characters
74+
splice = input_string[counter : counter + len(row)]
75+
grid.append([character for character in splice])
76+
counter += len(row)
77+
78+
output_string = "" # reads as zigzag
79+
for position in range(len(input_string)):
80+
num = position % (lowest * 2) # puts it in bounds
81+
num = min(num, lowest * 2 - num) # creates zigzag pattern
82+
output_string += grid[num][0]
83+
grid[num].pop(0)
84+
return output_string
85+
86+
87+
def bruteforce(input_string: str) -> dict:
88+
"""Uses decrypt function by guessing every key
89+
90+
>>> bruteforce("HWe olordll")[4]
91+
'Hello World'
92+
"""
93+
results = {}
94+
for key_guess in range(1, len(input_string)): # tries every key
95+
results[key_guess] = decrypt(input_string, key_guess)
96+
return results
97+
98+
99+
if __name__ == "__main__":
100+
import doctest
101+
102+
doctest.testmod()

0 commit comments

Comments
 (0)