From 1da1a3c1c9a0f8f2cf3475a10e5d66d185516cf7 Mon Sep 17 00:00:00 2001 From: achance6 Date: Fri, 22 Nov 2019 13:49:45 -0500 Subject: [PATCH 1/9] Implemented simple keyword cipher --- ciphers/simple_keyword_cypher.py | 74 ++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 ciphers/simple_keyword_cypher.py diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py new file mode 100644 index 000000000000..80367661f602 --- /dev/null +++ b/ciphers/simple_keyword_cypher.py @@ -0,0 +1,74 @@ +def main(): + message = input("Enter message to encode or decode: ") + key = input("Enter keyword: ") + option = input("Encipher or decipher? E/D: ") + key = key.upper() + message = message.upper() + cipher = encode(key) + if option.lower() == 'e': + enciphered = encipher(message, cipher) + print(enciphered) + elif option.lower() == 'd': + deciphered = decipher(message, cipher) + print(deciphered) + else: + print("Invalid input option") + + +def encode(key): + alphabet = [] + cipherAlphabet = {} + # Create alphabet list + for i in range(26): + alphabet.append(chr(i + 65)) + # Remove duplicate characters from key + key = removeDuplicates(key) + offset = len(key) + # First fill cipher with key characters + for i in range(len(key)): + cipherAlphabet[alphabet[i]] = key[i] + # Then map remaining characters in alphabet to + # the alphabet from the beginning + for i in range(len(cipherAlphabet.keys()), 26): + char = alphabet[i - offset] + # Ensure we are not mapping letters to letters previously mapped + while key.find(char) != -1: + offset -= 1 + char = alphabet[i - offset] + cipherAlphabet[alphabet[i]] = char + return cipherAlphabet + + +def removeDuplicates(key): + keyNoDups = "" + for ch in key: + if keyNoDups.find(ch) == -1: + keyNoDups += ch + return keyNoDups + + +def encipher(message, cipher): + enciphered = "" + for ch in message: + if ch.isalpha(): + enciphered += cipher[ch.upper()] + else: + enciphered += ' ' + return enciphered + + +def decipher(message, cipher): + # Reverse our cipher mappings + revCipher = dict((v, k) for k, v in cipher.items()) + deciphered = "" + print(cipher) + for ch in message: + if ch.isalpha(): + deciphered += revCipher[ch.upper()] + else: + deciphered += ch + return deciphered + + +if __name__ == "__main__": + main() From cac49e3187c8c8526294f69b3a4633e68deb3179 Mon Sep 17 00:00:00 2001 From: achance6 Date: Fri, 22 Nov 2019 19:54:21 -0500 Subject: [PATCH 2/9] Added documentation and improved input processing --- ciphers/simple_keyword_cypher.py | 109 +++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 35 deletions(-) diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py index 80367661f602..0c85c8499b24 100644 --- a/ciphers/simple_keyword_cypher.py +++ b/ciphers/simple_keyword_cypher.py @@ -1,74 +1,113 @@ +import sys + + def main(): - message = input("Enter message to encode or decode: ") - key = input("Enter keyword: ") - option = input("Encipher or decipher? E/D: ") + """ + Handles I/O + :return: void + """ + print("Enter message to encode or decode:", end=" ") + message = sys.stdin.readline().strip() + print("Enter keyword:", end=" ") + key = sys.stdin.readline().strip() + print("Encipher or decipher? E/D:", end=" ") + option = sys.stdin.readline().strip() key = key.upper() - message = message.upper() - cipher = encode(key) - if option.lower() == 'e': - enciphered = encipher(message, cipher) - print(enciphered) - elif option.lower() == 'd': - deciphered = decipher(message, cipher) - print(deciphered) + message = message.upper().strip() + cipher_map = create_cipher_map(key) + if option.lower().startswith("e"): + enciphered_message = encipher(message, cipher_map) + print(enciphered_message) + elif option.lower().startswith("d"): + deciphered_message = decipher(message, cipher_map) + print(deciphered_message) else: print("Invalid input option") -def encode(key): +def create_cipher_map(key: str) -> dict: + """ + Returns a cipher map given a keyword. + :param key: keyword to use + :return: dictionary cipher map + """ alphabet = [] - cipherAlphabet = {} + cipher_alphabet = {} # Create alphabet list for i in range(26): alphabet.append(chr(i + 65)) # Remove duplicate characters from key - key = removeDuplicates(key) + key = remove_duplicates(key) offset = len(key) # First fill cipher with key characters for i in range(len(key)): - cipherAlphabet[alphabet[i]] = key[i] + cipher_alphabet[alphabet[i]] = key[i] # Then map remaining characters in alphabet to # the alphabet from the beginning - for i in range(len(cipherAlphabet.keys()), 26): + for i in range(len(cipher_alphabet.keys()), 26): char = alphabet[i - offset] # Ensure we are not mapping letters to letters previously mapped while key.find(char) != -1: offset -= 1 char = alphabet[i - offset] - cipherAlphabet[alphabet[i]] = char - return cipherAlphabet + cipher_alphabet[alphabet[i]] = char + return cipher_alphabet -def removeDuplicates(key): - keyNoDups = "" +def remove_duplicates(key: str) -> str: + """ + Removes duplicate characters in a keyword (removed after first appearance). + :param key: Keyword to use + :return: String with duplicates removed + """ + """ + >>> remove_duplicates('hellol') + 'helo' + """ + + key_no_dups = "" for ch in key: - if keyNoDups.find(ch) == -1: - keyNoDups += ch - return keyNoDups + if key_no_dups.find(ch) == -1: + key_no_dups += ch + return key_no_dups -def encipher(message, cipher): - enciphered = "" +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_message = "" for ch in message: if ch.isalpha(): - enciphered += cipher[ch.upper()] + enciphered_message += cipher_map[ch.upper()] else: - enciphered += ' ' - return enciphered + enciphered_message += ch + return enciphered_message -def decipher(message, cipher): +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 + """ # Reverse our cipher mappings - revCipher = dict((v, k) for k, v in cipher.items()) - deciphered = "" - print(cipher) + rev_cipher_map = dict((v, k) for k, v in cipher_map.items()) + deciphered_message = "" for ch in message: if ch.isalpha(): - deciphered += revCipher[ch.upper()] + deciphered_message += rev_cipher_map[ch.upper()] else: - deciphered += ch - return deciphered + deciphered_message += ch + return deciphered_message if __name__ == "__main__": + import doctest + + doctest.testmod() main() From 3ede35ec8ded036f3fdef1a1c653eaa185ae2734 Mon Sep 17 00:00:00 2001 From: achance6 Date: Fri, 22 Nov 2019 20:53:58 -0500 Subject: [PATCH 3/9] Allow object's hash function to be called --- data_structures/hashing/hash_table.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index ab473dc52324..8e5b3581638d 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -24,7 +24,14 @@ def balanced_factor(self): ) def hash_function(self, key): - return key % self.size_table + try: + return abs(hash(key)) % self.size_table + except RuntimeError: + try: + return key % self.size_table + except RuntimeError: + print("Object needs hash function!") + exit(0) def _step_by_step(self, step_ord): From b2a1a3b22a6130cf37e2f7f531ee19b51c2726ea Mon Sep 17 00:00:00 2001 From: achance6 Date: Fri, 22 Nov 2019 21:25:57 -0500 Subject: [PATCH 4/9] added to string functionality --- data_structures/hashing/hash_table.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index 8e5b3581638d..c0e2ebc0ebd9 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -39,12 +39,20 @@ def _step_by_step(self, step_ord): print([i for i in range(len(self.values))]) print(self.values) + def __str__(self): + output = "{" + for key in self._keys: + if self._keys[key] is not None: + output += str(key) + ": " + str(self._keys[key] + ", ") + output = output[0: len(output) - 2] + output += "}" + return output + def bulk_insert(self, values): i = 1 self.__aux_list = values for value in values: self.insert_data(value) - self._step_by_step(i) i += 1 def _set_value(self, key, data): @@ -69,7 +77,7 @@ def rehashing(self): self.size_table = next_prime(self.size_table, factor=2) self._keys.clear() self.values = [None] * self.size_table # hell's pointers D: don't DRY ;/ - map(self.insert_data, survivor_values) + self.bulk_insert(survivor_values) def insert_data(self, data): key = self.hash_function(data) From b52619be88edd6b07ebf281955fabb4eee8f0acb Mon Sep 17 00:00:00 2001 From: achance6 Date: Sat, 23 Nov 2019 08:27:53 -0500 Subject: [PATCH 5/9] reverted --- data_structures/hashing/hash_table.py | 1878 +++++++++++++++++++++++-- 1 file changed, 1781 insertions(+), 97 deletions(-) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index c0e2ebc0ebd9..81215f317178 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -1,97 +1,1781 @@ -#!/usr/bin/env python3 -from number_theory.prime_numbers import next_prime - - -class HashTable: - """ - Basic Hash Table example with open addressing and linear probing - """ - - def __init__(self, size_table, charge_factor=None, lim_charge=None): - self.size_table = size_table - self.values = [None] * self.size_table - self.lim_charge = 0.75 if lim_charge is None else lim_charge - self.charge_factor = 1 if charge_factor is None else charge_factor - self.__aux_list = [] - self._keys = {} - - def keys(self): - return self._keys - - def balanced_factor(self): - return sum([1 for slot in self.values if slot is not None]) / ( - self.size_table * self.charge_factor - ) - - def hash_function(self, key): - try: - return abs(hash(key)) % self.size_table - except RuntimeError: - try: - return key % self.size_table - except RuntimeError: - print("Object needs hash function!") - exit(0) - - def _step_by_step(self, step_ord): - - print("step {0}".format(step_ord)) - print([i for i in range(len(self.values))]) - print(self.values) - - def __str__(self): - output = "{" - for key in self._keys: - if self._keys[key] is not None: - output += str(key) + ": " + str(self._keys[key] + ", ") - output = output[0: len(output) - 2] - output += "}" - return output - - def bulk_insert(self, values): - i = 1 - self.__aux_list = values - for value in values: - self.insert_data(value) - i += 1 - - def _set_value(self, key, data): - self.values[key] = data - self._keys[key] = data - - def _colision_resolution(self, key, data=None): - new_key = self.hash_function(key + 1) - - while self.values[new_key] is not None and self.values[new_key] != key: - - if self.values.count(None) > 0: - new_key = self.hash_function(new_key + 1) - else: - new_key = None - break - - return new_key - - def rehashing(self): - survivor_values = [value for value in self.values if value is not None] - self.size_table = next_prime(self.size_table, factor=2) - self._keys.clear() - self.values = [None] * self.size_table # hell's pointers D: don't DRY ;/ - self.bulk_insert(survivor_values) - - def insert_data(self, data): - key = self.hash_function(data) - - if self.values[key] is None: - self._set_value(key, data) - - elif self.values[key] == data: - pass - - else: - colision_resolution = self._colision_resolution(key, data) - if colision_resolution is not None: - self._set_value(colision_resolution, data) - else: - self.rehashing() - self.insert_data(data) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Python/hash_table.py at master · TheAlgorithms/Python + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + + + + + +
+ +
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+ +
    + +
  • + +
  • + + + +
  • + +
    + +
    + + + Unwatch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • +
    +
    + +
  • +
+ +

+ + /Python + + +

+ +
+ + + + + + +
+
+
+ + + + + + + + + Permalink + + + + + + + + + + + +
+
+ + @WilliamHYZhang + WilliamHYZhang + + psf/black code formatting (#1277) + + + + 9eac17a + Oct 5, 2019 + +
+ +
+
+ + 1 contributor + + +
+ +

+ Users who have contributed to this file +

+
+ +
+
+
+
+ + + + + +
+ +
+
+ + 82 lines (63 sloc) + + 2.42 KB +
+ +
+ +
+ Raw + Blame + History +
+ + +
+ + + + +
+ +
+
+ +
+
+
+ + +
+
+
+
+

Code navigation is available!

+
+

+ Navigate your code with ease. Click on function and method calls to jump to their definitions or references in the same repository. + Learn more +

+
+
+
+
+
+
+ +
+
+
+ + You're using jump to definition to discover and navigate code. +
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#!/usr/bin/env python3
from number_theory.prime_numbers import next_prime
+
+
class HashTable:
"""
Basic Hash Table example with open addressing and linear probing
"""
+
def __init__(self, size_table, charge_factor=None, lim_charge=None):
self.size_table = size_table
self.values = [None] * self.size_table
self.lim_charge = 0.75 if lim_charge is None else lim_charge
self.charge_factor = 1 if charge_factor is None else charge_factor
self.__aux_list = []
self._keys = {}
+
def keys(self):
return self._keys
+
def balanced_factor(self):
return sum([1 for slot in self.values if slot is not None]) / (
self.size_table * self.charge_factor
)
+
def hash_function(self, key):
return key % self.size_table
+
def _step_by_step(self, step_ord):
+
print("step {0}".format(step_ord))
print([i for i in range(len(self.values))])
print(self.values)
+
def bulk_insert(self, values):
i = 1
self.__aux_list = values
for value in values:
self.insert_data(value)
self._step_by_step(i)
i += 1
+
def _set_value(self, key, data):
self.values[key] = data
self._keys[key] = data
+
def _colision_resolution(self, key, data=None):
new_key = self.hash_function(key + 1)
+
while self.values[new_key] is not None and self.values[new_key] != key:
+
if self.values.count(None) > 0:
new_key = self.hash_function(new_key + 1)
else:
new_key = None
break
+
return new_key
+
def rehashing(self):
survivor_values = [value for value in self.values if value is not None]
self.size_table = next_prime(self.size_table, factor=2)
self._keys.clear()
self.values = [None] * self.size_table # hell's pointers D: don't DRY ;/
map(self.insert_data, survivor_values)
+
def insert_data(self, data):
key = self.hash_function(data)
+
if self.values[key] is None:
self._set_value(key, data)
+
elif self.values[key] == data:
pass
+
else:
colision_resolution = self._colision_resolution(key, data)
if colision_resolution is not None:
self._set_value(colision_resolution, data)
else:
self.rehashing()
self.insert_data(data)
+ + + +
+ +
+ + + +
+ + +
+ + +
+
+ + + + + +
+
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + + + + + + +
+ + + + From 559a02ef74729cbbd03776d1847cb508119d18e4 Mon Sep 17 00:00:00 2001 From: achance6 Date: Sat, 23 Nov 2019 08:28:27 -0500 Subject: [PATCH 6/9] Revised according to pull request #1589 --- ciphers/simple_keyword_cypher.py | 62 +++++++++++++------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py index 0c85c8499b24..014ecec9a829 100644 --- a/ciphers/simple_keyword_cypher.py +++ b/ciphers/simple_keyword_cypher.py @@ -6,23 +6,15 @@ def main(): Handles I/O :return: void """ - print("Enter message to encode or decode:", end=" ") - message = sys.stdin.readline().strip() - print("Enter keyword:", end=" ") - key = sys.stdin.readline().strip() - print("Encipher or decipher? E/D:", end=" ") - option = sys.stdin.readline().strip() - key = key.upper() - message = message.upper().strip() + message = input("Enter message to encode or decode: ").strip().upper() + key = input("Enter keyword: ").strip().upper() + 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) - if option.lower().startswith("e"): - enciphered_message = encipher(message, cipher_map) - print(enciphered_message) - elif option.lower().startswith("d"): - deciphered_message = decipher(message, cipher_map) - print(deciphered_message) - else: - print("Invalid input option") + print(func(message, cipher_map)) def create_cipher_map(key: str) -> dict: @@ -31,23 +23,21 @@ def create_cipher_map(key: str) -> dict: :param key: keyword to use :return: dictionary cipher map """ - alphabet = [] cipher_alphabet = {} # Create alphabet list - for i in range(26): - alphabet.append(chr(i + 65)) + alphabet = [chr(i + 65) for i in range(26)] # Remove duplicate characters from key key = remove_duplicates(key) offset = len(key) # First fill cipher with key characters - for i in range(len(key)): - cipher_alphabet[alphabet[i]] = key[i] + for i, char in enumerate(key): + cipher_alphabet[alphabet[i]] = char # Then map remaining characters in alphabet to # the alphabet from the beginning for i in range(len(cipher_alphabet.keys()), 26): char = alphabet[i - offset] # Ensure we are not mapping letters to letters previously mapped - while key.find(char) != -1: + while char in key: offset -= 1 char = alphabet[i - offset] cipher_alphabet[alphabet[i]] = char @@ -56,18 +46,16 @@ def create_cipher_map(key: str) -> dict: def remove_duplicates(key: str) -> str: """ - Removes duplicate characters in a keyword (removed after first appearance). + Removes duplicate alphabetic characters in a keyword (removed after first appearance). :param key: Keyword to use :return: String with duplicates removed - """ - """ - >>> remove_duplicates('hellol') - 'helo' + >>> remove_duplicates('Hello World!!') + 'Helo Wrd' """ key_no_dups = "" for ch in key: - if key_no_dups.find(ch) == -1: + if (ch not in key_no_dups and ch.isalpha()) or ch == ' ': key_no_dups += ch return key_no_dups @@ -77,14 +65,13 @@ 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: + :return: enciphered string + >>> encipher('HELLO WORLD!!', create_cipher_map('GOODBYE!!')) + 'CYJJM VMQJB!!' """ enciphered_message = "" for ch in message: - if ch.isalpha(): - enciphered_message += cipher_map[ch.upper()] - else: - enciphered_message += ch + enciphered_message += cipher_map.get(ch, ch) return enciphered_message @@ -94,15 +81,14 @@ def decipher(message: str, cipher_map: dict) -> str: :param message: Message to decipher :param cipher_map: Dictionary mapping to use :return: Deciphered string + >>> decipher(encipher('HELLO WORLD!!', create_cipher_map('GOODBYE!!')), create_cipher_map('GOODBYE!!')) + 'HELLO WORLD!!' """ # Reverse our cipher mappings - rev_cipher_map = dict((v, k) for k, v in cipher_map.items()) + rev_cipher_map = {v: k for k, v in cipher_map.items()} deciphered_message = "" for ch in message: - if ch.isalpha(): - deciphered_message += rev_cipher_map[ch.upper()] - else: - deciphered_message += ch + deciphered_message += rev_cipher_map.get(ch, ch) return deciphered_message From 671a3c96c1921b7a9797d3e55668c5f8f7bcaf5e Mon Sep 17 00:00:00 2001 From: achance6 Date: Sat, 23 Nov 2019 08:43:05 -0500 Subject: [PATCH 7/9] Optimized imports --- ciphers/simple_keyword_cypher.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py index 014ecec9a829..1608dd844167 100644 --- a/ciphers/simple_keyword_cypher.py +++ b/ciphers/simple_keyword_cypher.py @@ -1,6 +1,3 @@ -import sys - - def main(): """ Handles I/O @@ -55,7 +52,7 @@ def remove_duplicates(key: str) -> str: key_no_dups = "" for ch in key: - if (ch not in key_no_dups and ch.isalpha()) or ch == ' ': + if (ch not in key_no_dups and ch.isalpha()) or ch == " ": key_no_dups += ch return key_no_dups From c5f5ae43056a80efa03de00224cc89156d4b26a1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 23 Nov 2019 16:51:10 +0100 Subject: [PATCH 8/9] Update simple_keyword_cypher.py --- ciphers/simple_keyword_cypher.py | 80 +++++++++++++++----------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/ciphers/simple_keyword_cypher.py b/ciphers/simple_keyword_cypher.py index 1608dd844167..71c3083e9dfc 100644 --- a/ciphers/simple_keyword_cypher.py +++ b/ciphers/simple_keyword_cypher.py @@ -1,17 +1,18 @@ -def main(): +def remove_duplicates(key: str) -> str: """ - Handles I/O - :return: void + 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' """ - message = input("Enter message to encode or decode: ").strip().upper() - key = input("Enter keyword: ").strip().upper() - 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)) + + 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: @@ -20,18 +21,16 @@ def create_cipher_map(key: str) -> dict: :param key: keyword to use :return: dictionary cipher map """ - cipher_alphabet = {} # Create alphabet list alphabet = [chr(i + 65) for i in range(26)] # Remove duplicate characters from key - key = remove_duplicates(key) + key = remove_duplicates(key.upper()) offset = len(key) # First fill cipher with key characters - for i, char in enumerate(key): - cipher_alphabet[alphabet[i]] = char + 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.keys()), 26): + 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: @@ -41,35 +40,16 @@ def create_cipher_map(key: str) -> dict: return cipher_alphabet -def remove_duplicates(key: str) -> str: - """ - Removes duplicate alphabetic characters in a keyword (removed after 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 not in key_no_dups and ch.isalpha()) or ch == " ": - key_no_dups += ch - return key_no_dups - - 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!!')) + >>> encipher('Hello World!!', create_cipher_map('Goodbye!!')) 'CYJJM VMQJB!!' """ - enciphered_message = "" - for ch in message: - enciphered_message += cipher_map.get(ch, ch) - return enciphered_message + return "".join(cipher_map.get(ch, ch) for ch in message.upper()) def decipher(message: str, cipher_map: dict) -> str: @@ -78,15 +58,29 @@ def decipher(message: str, cipher_map: dict) -> str: :param message: Message to decipher :param cipher_map: Dictionary mapping to use :return: Deciphered string - >>> decipher(encipher('HELLO WORLD!!', create_cipher_map('GOODBYE!!')), create_cipher_map('GOODBYE!!')) + >>> 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()} - deciphered_message = "" - for ch in message: - deciphered_message += rev_cipher_map.get(ch, ch) - return deciphered_message + 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__": From 5208c5d066ed27ca46375ab1e45981fd4af1c24f Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 23 Nov 2019 16:51:40 +0100 Subject: [PATCH 9/9] Update hash_table.py --- data_structures/hashing/hash_table.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index 6acfd22161c6..ab473dc52324 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -79,4 +79,4 @@ def insert_data(self, data): self._set_value(colision_resolution, data) else: self.rehashing() - self.insert_data(data) \ No newline at end of file + self.insert_data(data)