From 9d5546987351d17b296f86ae9a45e169220ecae2 Mon Sep 17 00:00:00 2001 From: Ope Date: Thu, 19 Oct 2023 21:39:50 +0100 Subject: [PATCH 01/13] Added docstrings,doctests and fixed a bug --- ciphers/trifid_cipher.py | 90 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 8aa2263ca5ac..98ccc1e5e320 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -1,8 +1,23 @@ -# https://en.wikipedia.org/wiki/Trifid_cipher +""" + The trifid cipher uses a table to fractionate each plaintext letter into a trigram,mixes the constituents of the trigrams, and then applies the table in reverse to turn these mixed trigrams into ciphertext letters. + https://en.wikipedia.org/wiki/Trifid_cipher +""" + from __future__ import annotations def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: + """ + Arranges the triagram value of each letter of 'message_part' vertically and joins them horizontally + + >>> __encrypt_part('ASK',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + '132111112' + + 1 3 2 + 1 1 1 + 1 1 2 + + """ one, two, three = "", "", "" tmp = [] @@ -20,6 +35,12 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> st def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: + """ + Converts each letter of the input string into there respective trigram values, joins them and splits them into three equal groups of strings. Then returns the group of strings . + + >>> __decrypt_part('ABCDE',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + ('11111', '21131', '21122') + """ tmp, this_part = "", "" result = [] @@ -38,6 +59,32 @@ def __decrypt_part( def __prepare( message: str, alphabet: str ) -> tuple[str, str, dict[str, str], dict[str, str]]: + """ + A helper function that generates the triagrams and assigns each letter of the alphabet to its corresponding triagram and stores this in a dictionary ("character_to_number" and "number_to_character") after confirming if the alphabet's length is 27. + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') + ('IAMABOY', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ+', {'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}, {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') + Traceback (most recent call last): + ... + KeyError: 'Length of alphabet has to be 27.' + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxyzzwwtyyujjgfd') + Traceback (most recent call last): + ... + KeyError: 'Length of alphabet has to be 27.' + + >>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+') + Traceback (most recent call last): + ... + ValueError: Each message character has to be included in alphabet! + + >>> __prepare(500,'abCdeFghijkLmnopqrStuVwxYZ+') + Traceback (most recent call last): + ... + AttributeError: 'int' object has no attribute 'replace' + """ # Validate message and alphabet, set to upper and remove spaces alphabet = alphabet.replace(" ", "").upper() message = message.replace(" ", "").upper() @@ -91,6 +138,19 @@ def __prepare( def encrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: + """ + Encrypts a message using the trifid_cipher. Any punctuatuions that would be used should be added to the alphabet.'message' is the message you want to encrypt, 'alphabet' are the characters you want to use for the cipher, 'period' is the number of characters you want in a group whilst encrypting. + + >>> encrypt_message('I am a boy') + 'BCDGBQY' + + >>> encrypt_message(' ') + '' + + >>> encrypt_message(' aide toi le c iel ta id era ','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) + 'FMJFVOISSUFTFPUFEQQC' + + """ message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet ) @@ -110,18 +170,28 @@ def encrypt_message( def decrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: + """ + Decrypts a trifid_cipher encrypted message .'message' is the message you want to decrypt, 'alphabet' are the characters used for the cipher, 'period' is the number of characters used in grouping when it was encrypted. + + >>> decrypt_message('BCDGBQY') + 'IAMABOY' + >>> decrypt_message('FMJFVOISSUFTFPUFEQQC','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) + 'AIDETOILECIELTAIDERA' + + """ message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet ) + decrypted_numeric = [] decrypted = "" - - for i in range(0, len(message) + 1, period): + + for i in range(0, len(message) , period): a, b, c = __decrypt_part(message[i : i + period], character_to_number) - + for j in range(len(a)): decrypted_numeric.append(a[j] + b[j] + c[j]) - + for each in decrypted_numeric: decrypted += number_to_character[each] @@ -129,7 +199,9 @@ def decrypt_message( if __name__ == "__main__": - msg = "DEFEND THE EAST WALL OF THE CASTLE." - encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") - decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") - print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}") + import doctest + doctest.testmod() + # msg = "DEFEND THE EAST WALL OF THE CASTLE." + # encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + # decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + # print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}") From 7fea1eeaf4ad4d1bce8c807d3a5d949bc53f1d05 Mon Sep 17 00:00:00 2001 From: Ope Date: Thu, 19 Oct 2023 21:52:42 +0100 Subject: [PATCH 02/13] Added docstrings,doctests and fixed a bug --- ciphers/trifid_cipher.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 98ccc1e5e320..dac47a8fc75b 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -201,7 +201,7 @@ def decrypt_message( if __name__ == "__main__": import doctest doctest.testmod() - # msg = "DEFEND THE EAST WALL OF THE CASTLE." - # encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") - # decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") - # print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}") + msg = "DEFEND THE EAST WALL OF THE CASTLE." + encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") + print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}") From 91208b5fc76cbb48c4009373c26888dcb1546f93 Mon Sep 17 00:00:00 2001 From: Ope Date: Thu, 19 Oct 2023 23:25:09 +0100 Subject: [PATCH 03/13] Added docstrings,doctests and fixed a bug --- ciphers/trifid_cipher.py | 109 +++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index dac47a8fc75b..57f5e02fc760 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -1,6 +1,8 @@ """ - The trifid cipher uses a table to fractionate each plaintext letter into a trigram,mixes the constituents of the trigrams, and then applies the table in reverse to turn these mixed trigrams into ciphertext letters. - https://en.wikipedia.org/wiki/Trifid_cipher +The trifid cipher uses a table to fractionate each plaintext letter into a +trigram,mixes the constituents of the trigrams, and then applies the table +in reverse to turn these mixed trigrams into ciphertext letters. +https://en.wikipedia.org/wiki/Trifid_cipher """ from __future__ import annotations @@ -8,15 +10,11 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ - Arranges the triagram value of each letter of 'message_part' vertically and joins them horizontally - - >>> __encrypt_part('ASK',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) - '132111112' - - 1 3 2 - 1 1 1 - 1 1 2 + Arranges the triagram value of each letter of 'message_part' vertically + and joins them horizontally + >>> __encrypt_part('ASK',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + '132111112' """ one, two, three = "", "", "" tmp = [] @@ -36,10 +34,12 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - Converts each letter of the input string into there respective trigram values, joins them and splits them into three equal groups of strings. Then returns the group of strings . + Converts each letter of the input string into there respective trigram + values, joins them and splits them into three equal groups of strings. + Then returns the group of strings . - >>> __decrypt_part('ABCDE',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) - ('11111', '21131', '21122') + >>> __decrypt_part('ABCDE',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + ('11111', '21131', '21122') """ tmp, this_part = "", "" result = [] @@ -60,30 +60,33 @@ def __prepare( message: str, alphabet: str ) -> tuple[str, str, dict[str, str], dict[str, str]]: """ - A helper function that generates the triagrams and assigns each letter of the alphabet to its corresponding triagram and stores this in a dictionary ("character_to_number" and "number_to_character") after confirming if the alphabet's length is 27. - - >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') - ('IAMABOY', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ+', {'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}, {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) - - >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') - Traceback (most recent call last): - ... - KeyError: 'Length of alphabet has to be 27.' - - >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxyzzwwtyyujjgfd') - Traceback (most recent call last): - ... - KeyError: 'Length of alphabet has to be 27.' - - >>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+') - Traceback (most recent call last): - ... - ValueError: Each message character has to be included in alphabet! - - >>> __prepare(500,'abCdeFghijkLmnopqrStuVwxYZ+') - Traceback (most recent call last): - ... - AttributeError: 'int' object has no attribute 'replace' + A helper function that generates the triagrams and assigns each letter + of the alphabet to its corresponding triagram and stores this in a + dictionary ("character_to_number" and "number_to_character") after + confirming if the alphabet's length is 27. + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') + ('IAMABOY', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ+', {'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}, {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') + Traceback (most recent call last): + ... + KeyError: 'Length of alphabet has to be 27.' + + >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxyzzwwtyyujjgfd') + Traceback (most recent call last): + ... + KeyError: 'Length of alphabet has to be 27.' + + >>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+') + Traceback (most recent call last): + ... + ValueError: Each message character has to be included in alphabet! + + >>> __prepare(500,'abCdeFghijkLmnopqrStuVwxYZ+') + Traceback (most recent call last): + ... + AttributeError: 'int' object has no attribute 'replace' """ # Validate message and alphabet, set to upper and remove spaces alphabet = alphabet.replace(" ", "").upper() @@ -139,16 +142,20 @@ def encrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: """ - Encrypts a message using the trifid_cipher. Any punctuatuions that would be used should be added to the alphabet.'message' is the message you want to encrypt, 'alphabet' are the characters you want to use for the cipher, 'period' is the number of characters you want in a group whilst encrypting. + Encrypts a message using the trifid_cipher. Any punctuatuions that + would be used should be added to the alphabet.'message' is the + message you want to encrypt, 'alphabet' are the characters you want + to use for the cipher, 'period' is the number of characters you want + in a group whilst encrypting. - >>> encrypt_message('I am a boy') - 'BCDGBQY' + >>> encrypt_message('I am a boy') + 'BCDGBQY' - >>> encrypt_message(' ') - '' + >>> encrypt_message(' ') + '' - >>> encrypt_message(' aide toi le c iel ta id era ','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) - 'FMJFVOISSUFTFPUFEQQC' + >>> encrypt_message(' aide toi le c iel ta id era ','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) + 'FMJFVOISSUFTFPUFEQQC' """ message, alphabet, character_to_number, number_to_character = __prepare( @@ -171,13 +178,15 @@ def decrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: """ - Decrypts a trifid_cipher encrypted message .'message' is the message you want to decrypt, 'alphabet' are the characters used for the cipher, 'period' is the number of characters used in grouping when it was encrypted. + Decrypts a trifid_cipher encrypted message .'message' is the message you + want to decrypt, 'alphabet' are the characters used for the cipher, + 'period' is the number of characters used in grouping when it was encrypted. + + >>> decrypt_message('BCDGBQY') + 'IAMABOY' - >>> decrypt_message('BCDGBQY') - 'IAMABOY' - >>> decrypt_message('FMJFVOISSUFTFPUFEQQC','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) - 'AIDETOILECIELTAIDERA' - + >>> decrypt_message('FMJFVOISSUFTFPUFEQQC','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) + 'AIDETOILECIELTAIDERA' """ message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet From 3036859e1f0b6bb58d501da0dcbf59b39ad7f9a6 Mon Sep 17 00:00:00 2001 From: Ope Date: Fri, 20 Oct 2023 01:09:01 +0100 Subject: [PATCH 04/13] Added docstrings and doctests with a bug fix --- ciphers/trifid_cipher.py | 76 +++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 57f5e02fc760..862faae41211 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -13,8 +13,15 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> st Arranges the triagram value of each letter of 'message_part' vertically and joins them horizontally - >>> __encrypt_part('ASK',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + >>> __encrypt_part('ASK', + ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', + ... 'G': '131', 'H': '132', 'I': '133', + ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', + ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... '+': '333'}) '132111112' + """ one, two, three = "", "", "" tmp = [] @@ -38,7 +45,13 @@ def __decrypt_part( values, joins them and splits them into three equal groups of strings. Then returns the group of strings . - >>> __decrypt_part('ABCDE',{'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}) + >>> __decrypt_part('ABCDE', + ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', + ... 'G': '131', 'H': '132', 'I': '133', + ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', + ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... '+': '333'}) ('11111', '21131', '21122') """ tmp, this_part = "", "" @@ -65,24 +78,41 @@ def __prepare( dictionary ("character_to_number" and "number_to_character") after confirming if the alphabet's length is 27. - >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') - ('IAMABOY', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ+', {'A': '111', 'B': '112', 'C': '113', 'D': '121', 'E': '122', 'F': '123', 'G': '131', 'H': '132', 'I': '133', 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', '+': '333'}, {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) - + >>> test = __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') + >>> expected = ('IAMABOY','ABCDEFGHIJKLMNOPQRSTUVWXYZ+', + ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', + ... 'G': '131', 'H': '132', 'I': '133', + ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', + ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... '+': '333'}, + ... {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', + ... '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', + ... '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', + ... '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', + ... '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) + >>> test == expected + True + + Testing with incomplete alphabet >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') Traceback (most recent call last): ... KeyError: 'Length of alphabet has to be 27.' + Testing with extra long alphabets >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxyzzwwtyyujjgfd') Traceback (most recent call last): ... KeyError: 'Length of alphabet has to be 27.' + Testing with punctuations that are not in the given alphabet >>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+') Traceback (most recent call last): ... ValueError: Each message character has to be included in alphabet! + Testing with numbers >>> __prepare(500,'abCdeFghijkLmnopqrStuVwxYZ+') Traceback (most recent call last): ... @@ -142,11 +172,20 @@ def encrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: """ + encrypt_message + =============== + Encrypts a message using the trifid_cipher. Any punctuatuions that - would be used should be added to the alphabet.'message' is the - message you want to encrypt, 'alphabet' are the characters you want - to use for the cipher, 'period' is the number of characters you want - in a group whilst encrypting. + would be used should be added to the alphabet. + + PARAMETERS + ---------- + + * message: The message you want to encrypt. + * alphabet (optional): The characters to be used for the cipher . + * period (optional): The number of characters you want in a group whilst + encrypting. + >>> encrypt_message('I am a boy') 'BCDGBQY' @@ -154,7 +193,8 @@ def encrypt_message( >>> encrypt_message(' ') '' - >>> encrypt_message(' aide toi le c iel ta id era ','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) + >>> encrypt_message(' aide toi le c iel ta id era ', + ... 'FELIXMARDSTBCGHJKNOPQUVWYZ+',5) 'FMJFVOISSUFTFPUFEQQC' """ @@ -178,13 +218,23 @@ def decrypt_message( message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5 ) -> str: """ - Decrypts a trifid_cipher encrypted message .'message' is the message you - want to decrypt, 'alphabet' are the characters used for the cipher, - 'period' is the number of characters used in grouping when it was encrypted. + decrypt_message + =============== + + Decrypts a trifid_cipher encrypted message . + + PARAMETERS + ---------- + + * message: The message you want to decrypt . + * alphabet (optional): The characters used for the cipher. + * period (optional): The number of characters used in grouping when it + was encrypted. >>> decrypt_message('BCDGBQY') 'IAMABOY' + Decrypting with your own alphabet and period >>> decrypt_message('FMJFVOISSUFTFPUFEQQC','FELIXMARDSTBCGHJKNOPQUVWYZ+',5) 'AIDETOILECIELTAIDERA' """ From 7ff162db665ad6d73b8304b71c41dfc89eaab229 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Oct 2023 00:21:45 +0000 Subject: [PATCH 05/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/trifid_cipher.py | 43 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 862faae41211..f4e0005ea1b3 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -1,6 +1,6 @@ """ -The trifid cipher uses a table to fractionate each plaintext letter into a -trigram,mixes the constituents of the trigrams, and then applies the table +The trifid cipher uses a table to fractionate each plaintext letter into a +trigram,mixes the constituents of the trigrams, and then applies the table in reverse to turn these mixed trigrams into ciphertext letters. https://en.wikipedia.org/wiki/Trifid_cipher """ @@ -10,7 +10,7 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ - Arranges the triagram value of each letter of 'message_part' vertically + Arranges the triagram value of each letter of 'message_part' vertically and joins them horizontally >>> __encrypt_part('ASK', @@ -18,7 +18,7 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> st ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}) '132111112' @@ -41,8 +41,8 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - Converts each letter of the input string into there respective trigram - values, joins them and splits them into three equal groups of strings. + Converts each letter of the input string into there respective trigram + values, joins them and splits them into three equal groups of strings. Then returns the group of strings . >>> __decrypt_part('ABCDE', @@ -50,7 +50,7 @@ def __decrypt_part( ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}) ('11111', '21131', '21122') """ @@ -73,9 +73,9 @@ def __prepare( message: str, alphabet: str ) -> tuple[str, str, dict[str, str], dict[str, str]]: """ - A helper function that generates the triagrams and assigns each letter - of the alphabet to its corresponding triagram and stores this in a - dictionary ("character_to_number" and "number_to_character") after + A helper function that generates the triagrams and assigns each letter + of the alphabet to its corresponding triagram and stores this in a + dictionary ("character_to_number" and "number_to_character") after confirming if the alphabet's length is 27. >>> test = __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') @@ -84,7 +84,7 @@ def __prepare( ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}, ... {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', ... '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', @@ -93,7 +93,7 @@ def __prepare( ... '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) >>> test == expected True - + Testing with incomplete alphabet >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') Traceback (most recent call last): @@ -176,16 +176,16 @@ def encrypt_message( =============== Encrypts a message using the trifid_cipher. Any punctuatuions that - would be used should be added to the alphabet. + would be used should be added to the alphabet. PARAMETERS ---------- * message: The message you want to encrypt. * alphabet (optional): The characters to be used for the cipher . - * period (optional): The number of characters you want in a group whilst + * period (optional): The number of characters you want in a group whilst encrypting. - + >>> encrypt_message('I am a boy') 'BCDGBQY' @@ -228,7 +228,7 @@ def decrypt_message( * message: The message you want to decrypt . * alphabet (optional): The characters used for the cipher. - * period (optional): The number of characters used in grouping when it + * period (optional): The number of characters used in grouping when it was encrypted. >>> decrypt_message('BCDGBQY') @@ -241,16 +241,16 @@ def decrypt_message( message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet ) - + decrypted_numeric = [] decrypted = "" - - for i in range(0, len(message) , period): + + for i in range(0, len(message), period): a, b, c = __decrypt_part(message[i : i + period], character_to_number) - + for j in range(len(a)): decrypted_numeric.append(a[j] + b[j] + c[j]) - + for each in decrypted_numeric: decrypted += number_to_character[each] @@ -259,6 +259,7 @@ def decrypt_message( if __name__ == "__main__": import doctest + doctest.testmod() msg = "DEFEND THE EAST WALL OF THE CASTLE." encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ") From e2a865e87b8e6b647f3c965020a20f909eb5c1fb Mon Sep 17 00:00:00 2001 From: Ope Date: Fri, 20 Oct 2023 01:32:55 +0100 Subject: [PATCH 06/13] Added docstrings and doctests with a bug fix --- ciphers/trifid_cipher.py | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 862faae41211..557e65a2e922 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -1,6 +1,6 @@ """ -The trifid cipher uses a table to fractionate each plaintext letter into a -trigram,mixes the constituents of the trigrams, and then applies the table +The trifid cipher uses a table to fractionate each plaintext letter into a +trigram,mixes the constituents of the trigrams, and then applies the table in reverse to turn these mixed trigrams into ciphertext letters. https://en.wikipedia.org/wiki/Trifid_cipher """ @@ -10,7 +10,7 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ - Arranges the triagram value of each letter of 'message_part' vertically + Arranges the triagram value of each letter of 'message_part' vertically and joins them horizontally >>> __encrypt_part('ASK', @@ -18,7 +18,7 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> st ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}) '132111112' @@ -41,8 +41,8 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - Converts each letter of the input string into there respective trigram - values, joins them and splits them into three equal groups of strings. + Converts each letter of the input string into there respective trigram + values, joins them and splits them into three equal groups of strings. Then returns the group of strings . >>> __decrypt_part('ABCDE', @@ -50,7 +50,7 @@ def __decrypt_part( ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}) ('11111', '21131', '21122') """ @@ -73,9 +73,9 @@ def __prepare( message: str, alphabet: str ) -> tuple[str, str, dict[str, str], dict[str, str]]: """ - A helper function that generates the triagrams and assigns each letter - of the alphabet to its corresponding triagram and stores this in a - dictionary ("character_to_number" and "number_to_character") after + A helper function that generates the triagrams and assigns each letter + of the alphabet to its corresponding triagram and stores this in a + dictionary ("character_to_number" and "number_to_character") after confirming if the alphabet's length is 27. >>> test = __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') @@ -84,7 +84,7 @@ def __prepare( ... 'G': '131', 'H': '132', 'I': '133', ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', ... '+': '333'}, ... {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', ... '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', @@ -93,7 +93,7 @@ def __prepare( ... '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) >>> test == expected True - + Testing with incomplete alphabet >>> __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVw') Traceback (most recent call last): @@ -176,16 +176,15 @@ def encrypt_message( =============== Encrypts a message using the trifid_cipher. Any punctuatuions that - would be used should be added to the alphabet. + would be used should be added to the alphabet. PARAMETERS ---------- * message: The message you want to encrypt. * alphabet (optional): The characters to be used for the cipher . - * period (optional): The number of characters you want in a group whilst + * period (optional): The number of characters you want in a group whilst encrypting. - >>> encrypt_message('I am a boy') 'BCDGBQY' @@ -228,7 +227,7 @@ def decrypt_message( * message: The message you want to decrypt . * alphabet (optional): The characters used for the cipher. - * period (optional): The number of characters used in grouping when it + * period (optional): The number of characters used in grouping when it was encrypted. >>> decrypt_message('BCDGBQY') @@ -241,16 +240,16 @@ def decrypt_message( message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet ) - + decrypted_numeric = [] decrypted = "" for i in range(0, len(message) , period): a, b, c = __decrypt_part(message[i : i + period], character_to_number) - + for j in range(len(a)): decrypted_numeric.append(a[j] + b[j] + c[j]) - + for each in decrypted_numeric: decrypted += number_to_character[each] From 27b63be7995e619fdf4eefd59623e8eb4edcad79 Mon Sep 17 00:00:00 2001 From: Ope Oluwaferanmi <111365699+FEROS01@users.noreply.github.com> Date: Fri, 20 Oct 2023 15:00:56 +0100 Subject: [PATCH 07/13] Update ciphers/trifid_cipher.py Co-authored-by: Christian Clauss --- ciphers/trifid_cipher.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index f90e36593be6..71b001fdee06 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -10,8 +10,8 @@ def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ - Arranges the triagram value of each letter of 'message_part' vertically - and joins them horizontally + Arrange the triagram value of each letter of 'message_part' vertically and join them + horizontally. >>> __encrypt_part('ASK', ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', From b3511bfbe5651777c391dd915905b8f69b6f1a42 Mon Sep 17 00:00:00 2001 From: Ope Oluwaferanmi <111365699+FEROS01@users.noreply.github.com> Date: Fri, 20 Oct 2023 15:02:05 +0100 Subject: [PATCH 08/13] Update ciphers/trifid_cipher.py Co-authored-by: Christian Clauss --- ciphers/trifid_cipher.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 71b001fdee06..3d192f73aaed 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -41,9 +41,9 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - Converts each letter of the input string into there respective trigram - values, joins them and splits them into three equal groups of strings. - Then returns the group of strings . +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 + Convert each letter of the input string into their respective trigram values, join + them and split them into three equal groups of strings which are returned. >>> __decrypt_part('ABCDE', ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', From e28f43011cfadc022ccd62814c60b07aa2ca4433 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Oct 2023 14:02:37 +0000 Subject: [PATCH 09/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/trifid_cipher.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 3d192f73aaed..14b00b9b850c 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -41,18 +41,18 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 - Convert each letter of the input string into their respective trigram values, join - them and split them into three equal groups of strings which are returned. - - >>> __decrypt_part('ABCDE', - ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', - ... 'G': '131', 'H': '132', 'I': '133', - ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', - ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', - ... '+': '333'}) - ('11111', '21131', '21122') + 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 + Convert each letter of the input string into their respective trigram values, join + them and split them into three equal groups of strings which are returned. + + >>> __decrypt_part('ABCDE', + ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', + ... 'G': '131', 'H': '132', 'I': '133', + ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', + ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', + ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', + ... '+': '333'}) + ('11111', '21131', '21122') """ tmp, this_part = "", "" result = [] From 63be6827cb93f109ad65ba361d9ae80f1c9ad620 Mon Sep 17 00:00:00 2001 From: Ope Date: Fri, 20 Oct 2023 15:52:23 +0100 Subject: [PATCH 10/13] Docstrings edit --- ciphers/trifid_cipher.py | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 14b00b9b850c..4597df69dfca 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -7,19 +7,17 @@ from __future__ import annotations +TEST_CHARACTER_TO_NUMBER = {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E':'122', 'F': '123','G': '131', 'H': '132', 'I': '133','J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222','O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312','U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332','+': '333'} + +TEST_NUMBER_TO_CHARACTER = {value: key for key, value in + TEST_CHARACTER_TO_NUMBER.items()} def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ Arrange the triagram value of each letter of 'message_part' vertically and join them horizontally. - >>> __encrypt_part('ASK', - ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', - ... 'G': '131', 'H': '132', 'I': '133', - ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', - ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', - ... '+': '333'}) + >>> __encrypt_part('ASK', TEST_CHARACTER_TO_NUMBER) '132111112' """ @@ -41,17 +39,10 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 Convert each letter of the input string into their respective trigram values, join them and split them into three equal groups of strings which are returned. - >>> __decrypt_part('ABCDE', - ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', - ... 'G': '131', 'H': '132', 'I': '133', - ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', - ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', - ... '+': '333'}) + >>> __decrypt_part('ABCDE', TEST_CHARACTER_TO_NUMBER) ('11111', '21131', '21122') """ tmp, this_part = "", "" @@ -80,17 +71,7 @@ def __prepare( >>> test = __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') >>> expected = ('IAMABOY','ABCDEFGHIJKLMNOPQRSTUVWXYZ+', - ... {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E': '122', 'F': '123', - ... 'G': '131', 'H': '132', 'I': '133', - ... 'J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222', - ... 'O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312', - ... 'U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332', - ... '+': '333'}, - ... {'111': 'A', '112': 'B', '113': 'C', '121': 'D', '122': 'E', - ... '123': 'F', '131': 'G', '132': 'H', '133': 'I', '211': 'J', '212': 'K', - ... '213': 'L', '221': 'M', '222': 'N', '223': 'O', '231': 'P', '232': 'Q', - ... '233': 'R', '311': 'S', '312': 'T', '313': 'U', '321': 'V', '322': 'W', - ... '323': 'X', '331': 'Y', '332': 'Z', '333': '+'}) + ... TEST_CHARACTER_TO_NUMBER, TEST_NUMBER_TO_CHARACTER) >>> test == expected True From c678fa782befe689247816bdfc1039aeac7a2976 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 20 Oct 2023 14:55:26 +0000 Subject: [PATCH 11/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/trifid_cipher.py | 44 +++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 4597df69dfca..64efcd8c51dd 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -7,10 +7,40 @@ from __future__ import annotations -TEST_CHARACTER_TO_NUMBER = {'A': '111', 'B': '112', 'C':'113', 'D': '121', 'E':'122', 'F': '123','G': '131', 'H': '132', 'I': '133','J': '211', 'K': '212', 'L': '213', 'M': '221', 'N': '222','O': '223', 'P': '231', 'Q': '232', 'R': '233', 'S': '311', 'T': '312','U': '313', 'V': '321', 'W': '322', 'X': '323', 'Y': '331', 'Z': '332','+': '333'} +TEST_CHARACTER_TO_NUMBER = { + "A": "111", + "B": "112", + "C": "113", + "D": "121", + "E": "122", + "F": "123", + "G": "131", + "H": "132", + "I": "133", + "J": "211", + "K": "212", + "L": "213", + "M": "221", + "N": "222", + "O": "223", + "P": "231", + "Q": "232", + "R": "233", + "S": "311", + "T": "312", + "U": "313", + "V": "321", + "W": "322", + "X": "323", + "Y": "331", + "Z": "332", + "+": "333", +} + +TEST_NUMBER_TO_CHARACTER = { + value: key for key, value in TEST_CHARACTER_TO_NUMBER.items() +} -TEST_NUMBER_TO_CHARACTER = {value: key for key, value in - TEST_CHARACTER_TO_NUMBER.items()} def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ @@ -39,11 +69,11 @@ def __decrypt_part( message_part: str, character_to_number: dict[str, str] ) -> tuple[str, str, str]: """ - Convert each letter of the input string into their respective trigram values, join - them and split them into three equal groups of strings which are returned. + Convert each letter of the input string into their respective trigram values, join + them and split them into three equal groups of strings which are returned. - >>> __decrypt_part('ABCDE', TEST_CHARACTER_TO_NUMBER) - ('11111', '21131', '21122') + >>> __decrypt_part('ABCDE', TEST_CHARACTER_TO_NUMBER) + ('11111', '21131', '21122') """ tmp, this_part = "", "" result = [] From 9278361b808dcdd1ff928cafd62562cd27df9509 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 20 Oct 2023 23:19:30 +0200 Subject: [PATCH 12/13] Update trifid_cipher.py --- ciphers/trifid_cipher.py | 125 +++++++++------------------------------ 1 file changed, 29 insertions(+), 96 deletions(-) diff --git a/ciphers/trifid_cipher.py b/ciphers/trifid_cipher.py index 64efcd8c51dd..16b9faf67688 100644 --- a/ciphers/trifid_cipher.py +++ b/ciphers/trifid_cipher.py @@ -1,63 +1,35 @@ """ -The trifid cipher uses a table to fractionate each plaintext letter into a -trigram,mixes the constituents of the trigrams, and then applies the table -in reverse to turn these mixed trigrams into ciphertext letters. +The trifid cipher uses a table to fractionate each plaintext letter into a trigram, +mixes the constituents of the trigrams, and then applies the table in reverse to turn +these mixed trigrams into ciphertext letters. + https://en.wikipedia.org/wiki/Trifid_cipher """ from __future__ import annotations +# fmt: off TEST_CHARACTER_TO_NUMBER = { - "A": "111", - "B": "112", - "C": "113", - "D": "121", - "E": "122", - "F": "123", - "G": "131", - "H": "132", - "I": "133", - "J": "211", - "K": "212", - "L": "213", - "M": "221", - "N": "222", - "O": "223", - "P": "231", - "Q": "232", - "R": "233", - "S": "311", - "T": "312", - "U": "313", - "V": "321", - "W": "322", - "X": "323", - "Y": "331", - "Z": "332", - "+": "333", + "A": "111", "B": "112", "C": "113", "D": "121", "E": "122", "F": "123", "G": "131", + "H": "132", "I": "133", "J": "211", "K": "212", "L": "213", "M": "221", "N": "222", + "O": "223", "P": "231", "Q": "232", "R": "233", "S": "311", "T": "312", "U": "313", + "V": "321", "W": "322", "X": "323", "Y": "331", "Z": "332", "+": "333", } +# fmt: off -TEST_NUMBER_TO_CHARACTER = { - value: key for key, value in TEST_CHARACTER_TO_NUMBER.items() -} +TEST_NUMBER_TO_CHARACTER = {val: key for key, val in TEST_CHARACTER_TO_NUMBER.items()} def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str: """ - Arrange the triagram value of each letter of 'message_part' vertically and join them - horizontally. + Arrange the triagram value of each letter of 'message_part' vertically and join + them horizontally. >>> __encrypt_part('ASK', TEST_CHARACTER_TO_NUMBER) '132111112' - """ one, two, three = "", "", "" - tmp = [] - - for character in message_part: - tmp.append(character_to_number[character]) - - for each in tmp: + for each in (character_to_number[character] for character in message_part): one += each[0] two += each[1] three += each[2] @@ -75,12 +47,9 @@ def __decrypt_part( >>> __decrypt_part('ABCDE', TEST_CHARACTER_TO_NUMBER) ('11111', '21131', '21122') """ - tmp, this_part = "", "" + this_part = "".join(character_to_number[character] for character in message_part) result = [] - - for character in message_part: - this_part += character_to_number[character] - + tmp = "" for digit in this_part: tmp += digit if len(tmp) == len(message_part): @@ -94,10 +63,10 @@ def __prepare( message: str, alphabet: str ) -> tuple[str, str, dict[str, str], dict[str, str]]: """ - A helper function that generates the triagrams and assigns each letter - of the alphabet to its corresponding triagram and stores this in a - dictionary ("character_to_number" and "number_to_character") after - confirming if the alphabet's length is 27. + A helper function that generates the triagrams and assigns each letter of the + alphabet to its corresponding triagram and stores this in a dictionary + ("character_to_number" and "number_to_character") after confirming if the + alphabet's length is 27. >>> test = __prepare('I aM a BOy','abCdeFghijkLmnopqrStuVwxYZ+') >>> expected = ('IAMABOY','ABCDEFGHIJKLMNOPQRSTUVWXYZ+', @@ -136,45 +105,14 @@ def __prepare( # Check length and characters if len(alphabet) != 27: raise KeyError("Length of alphabet has to be 27.") - for each in message: - if each not in alphabet: - raise ValueError("Each message character has to be included in alphabet!") + if any(char not in alphabet for char in message): + raise ValueError("Each message character has to be included in alphabet!") # Generate dictionares - numbers = ( - "111", - "112", - "113", - "121", - "122", - "123", - "131", - "132", - "133", - "211", - "212", - "213", - "221", - "222", - "223", - "231", - "232", - "233", - "311", - "312", - "313", - "321", - "322", - "323", - "331", - "332", - "333", - ) - character_to_number = {} - number_to_character = {} - for letter, number in zip(alphabet, numbers): - character_to_number[letter] = number - number_to_character[number] = letter + character_to_number = dict(zip(alphabet, TEST_CHARACTER_TO_NUMBER.values())) + number_to_character = { + number: letter for letter, number in character_to_number.items() + } return message, alphabet, character_to_number, number_to_character @@ -211,16 +149,16 @@ def encrypt_message( message, alphabet, character_to_number, number_to_character = __prepare( message, alphabet ) - encrypted, encrypted_numeric = "", "" + encrypted_numeric = "" for i in range(0, len(message) + 1, period): encrypted_numeric += __encrypt_part( message[i : i + period], character_to_number ) + encrypted = "" for i in range(0, len(encrypted_numeric), 3): encrypted += number_to_character[encrypted_numeric[i : i + 3]] - return encrypted @@ -253,18 +191,13 @@ def decrypt_message( ) decrypted_numeric = [] - decrypted = "" - for i in range(0, len(message), period): a, b, c = __decrypt_part(message[i : i + period], character_to_number) for j in range(len(a)): decrypted_numeric.append(a[j] + b[j] + c[j]) - for each in decrypted_numeric: - decrypted += number_to_character[each] - - return decrypted + return "".join(number_to_character[each] for each in decrypted_numeric) if __name__ == "__main__": From 055d5c816fc57709c569060d77bc754853617c61 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Fri, 20 Oct 2023 23:21:54 +0200 Subject: [PATCH 13/13] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9c9262d77748..790a328b3564 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -135,5 +135,5 @@ omit = [ sort = "Cover" [tool.codespell] -ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,manuel,mater,secant,som,sur,tim,zar" +ignore-words-list = "3rt,ans,crate,damon,fo,followings,hist,iff,kwanza,manuel,mater,secant,som,sur,tim,toi,zar" skip = "./.*,*.json,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt"