mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 15:01:08 +00:00
Implemented simple keyword cipher (#1589)
* Implemented simple keyword cipher * Added documentation and improved input processing * Allow object's hash function to be called * added to string functionality * reverted * Revised according to pull request #1589 * Optimized imports * Update simple_keyword_cypher.py * Update hash_table.py
This commit is contained in:
parent
4c75f863c8
commit
2ad5a1f083
90
ciphers/simple_keyword_cypher.py
Normal file
90
ciphers/simple_keyword_cypher.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
def remove_duplicates(key: str) -> str:
|
||||
"""
|
||||
Removes duplicate alphabetic characters in a keyword (letter is ignored after its
|
||||
first appearance).
|
||||
:param key: Keyword to use
|
||||
:return: String with duplicates removed
|
||||
>>> remove_duplicates('Hello World!!')
|
||||
'Helo Wrd'
|
||||
"""
|
||||
|
||||
key_no_dups = ""
|
||||
for ch in key:
|
||||
if ch == " " or ch not in key_no_dups and ch.isalpha():
|
||||
key_no_dups += ch
|
||||
return key_no_dups
|
||||
|
||||
|
||||
def create_cipher_map(key: str) -> dict:
|
||||
"""
|
||||
Returns a cipher map given a keyword.
|
||||
:param key: keyword to use
|
||||
:return: dictionary cipher map
|
||||
"""
|
||||
# Create alphabet list
|
||||
alphabet = [chr(i + 65) for i in range(26)]
|
||||
# Remove duplicate characters from key
|
||||
key = remove_duplicates(key.upper())
|
||||
offset = len(key)
|
||||
# First fill cipher with key characters
|
||||
cipher_alphabet = {alphabet[i]: char for i, char in enumerate(key)}
|
||||
# Then map remaining characters in alphabet to
|
||||
# the alphabet from the beginning
|
||||
for i in range(len(cipher_alphabet), 26):
|
||||
char = alphabet[i - offset]
|
||||
# Ensure we are not mapping letters to letters previously mapped
|
||||
while char in key:
|
||||
offset -= 1
|
||||
char = alphabet[i - offset]
|
||||
cipher_alphabet[alphabet[i]] = char
|
||||
return cipher_alphabet
|
||||
|
||||
|
||||
def encipher(message: str, cipher_map: dict) -> str:
|
||||
"""
|
||||
Enciphers a message given a cipher map.
|
||||
:param message: Message to encipher
|
||||
:param cipher_map: Cipher map
|
||||
:return: enciphered string
|
||||
>>> encipher('Hello World!!', create_cipher_map('Goodbye!!'))
|
||||
'CYJJM VMQJB!!'
|
||||
"""
|
||||
return "".join(cipher_map.get(ch, ch) for ch in message.upper())
|
||||
|
||||
|
||||
def decipher(message: str, cipher_map: dict) -> str:
|
||||
"""
|
||||
Deciphers a message given a cipher map
|
||||
:param message: Message to decipher
|
||||
:param cipher_map: Dictionary mapping to use
|
||||
:return: Deciphered string
|
||||
>>> cipher_map = create_cipher_map('Goodbye!!')
|
||||
>>> decipher(encipher('Hello World!!', cipher_map), cipher_map)
|
||||
'HELLO WORLD!!'
|
||||
"""
|
||||
# Reverse our cipher mappings
|
||||
rev_cipher_map = {v: k for k, v in cipher_map.items()}
|
||||
return "".join(rev_cipher_map.get(ch, ch) for ch in message.upper())
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Handles I/O
|
||||
:return: void
|
||||
"""
|
||||
message = input("Enter message to encode or decode: ").strip()
|
||||
key = input("Enter keyword: ").strip()
|
||||
option = input("Encipher or decipher? E/D:").strip()[0].lower()
|
||||
try:
|
||||
func = {"e": encipher, "d": decipher}[option]
|
||||
except KeyError:
|
||||
raise KeyError("invalid input option")
|
||||
cipher_map = create_cipher_map(key)
|
||||
print(func(message, cipher_map))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
main()
|
Loading…
Reference in New Issue
Block a user