Created
July 30, 2017 16:31
-
-
Save sistemd/0315410bda7ff09b3afab86e5400fd2a to your computer and use it in GitHub Desktop.
The master cryptanalyst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from typing import TypeVar, Iterator, List, Dict | |
import enum | |
import re | |
import colorama | |
colorama.init() | |
class NotAnUppercaseLetter(Exception): | |
pass | |
class CharacterEncrypted(Exception): | |
pass | |
class AlreadyHasSubstitution(Exception): | |
pass | |
class CharacterSubstitutions: | |
def __init__(self, text: str) -> None: | |
self.__character_substitutions: Dict[str, str] = {} | |
for char in text.upper(): | |
if not is_uppercase_letter(char): | |
self.__character_substitutions[char] = char | |
def substitution_for_character(self, char: str) -> str: | |
return self.__character_substitutions[char.upper()] | |
def character_has_substitution(self, char: str) -> bool: | |
char = char.upper() | |
return char in self.__character_substitutions | |
def create_substitution(self, old: str, new: str): | |
old = old.upper() | |
new = new.upper() | |
if self.character_has_substitution(old): | |
raise AlreadyHasSubstitution | |
self.__character_substitutions[old] = new | |
class Cipher: | |
def __init__(self, text: str) -> None: | |
self.__text = text.upper() | |
self.__character_substitutions = CharacterSubstitutions(text) | |
def decrypt_character(self, old: str, new: str): | |
self.__character_substitutions.create_substitution(old, new) | |
def decrypt_string(self, old: str, new: str) -> None: | |
for old_char, new_char in zip(old, new): | |
self.decrypt_character(old_char, new_char) | |
def most_common_word_of_length(self, length: int) -> str: | |
return most_common_word_of_length(self.__text, length) | |
def fancy_print(self) -> None: | |
print(self.__fancy_string()) | |
def __fancy_string(self) -> str: | |
result = '' | |
for char in self.__text: | |
if self.__character_substitutions.character_has_substitution(char): | |
result += self.__character_substitutions.substitution_for_character(char) | |
else: | |
result += colorama.Fore.LIGHTRED_EX + char + colorama.Fore.WHITE | |
return result | |
def is_uppercase_letter(s: str) -> bool: | |
""" | |
>>> is_uppercase_letter('a') | |
False | |
>>> is_uppercase_letter('B') | |
True | |
>>> is_uppercase_letter('3') | |
False | |
>>> is_uppercase_letter('string') | |
False | |
""" | |
match = re.match(r'[A-Z]', s) | |
return match is not None and len(match.group()) == len(s) | |
def all_indexes(s: str, sub: str) -> Iterator[int]: | |
""" | |
>>> list(all_indexes('Hello world', 'o')) | |
[4, 7] | |
>>> list(all_indexes('', 'example')) | |
[] | |
>>> list(all_indexes('example', '')) | |
[] | |
>>> list(all_indexes('abracadabra', 'ab')) | |
[0, 7] | |
""" | |
if sub == '': | |
return | |
i = -1 | |
while True: | |
i = s.find(sub, i + 1) | |
if i == -1: | |
break | |
yield i | |
def most_common_word_of_length(s: str, length) -> str: | |
return most_common_element(list(words_of_length(s, length))) | |
def words(s: str) -> List[str]: | |
return s.split(' ') | |
def words_of_length(s: str, length: int) -> Iterator[str]: | |
yield from (word for word in words(s) if len(word) == length) | |
T = TypeVar('T') | |
class EmptyList(Exception): | |
pass | |
def most_common_element(l: List[T]) -> T: | |
if not l: | |
raise EmptyList | |
value_to_count = value_to_count_dict(l) | |
value, highest_count = max(value_to_count.items(), key=lambda value_and_count: value_and_count[1]) | |
return value | |
def value_to_count_dict(l: List[T]) -> Dict[T, int]: | |
return {e: l.count(e) for e in l} | |
if __name__ == '__main__': | |
import doctest | |
doctest.testmod() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
http://imgur.com/a/jxmFb |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment