-
-
Notifications
You must be signed in to change notification settings - Fork 46.8k
Added fractionated_morse_cipher #9442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
cclauss
merged 10 commits into
TheAlgorithms:master
from
Om-Alve:fractionated_morse_cipher
Oct 8, 2023
Merged
Changes from 2 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
30c9d29
Added fractionated_morse_cipher
Om-Alve 9f2d8fe
Added return type hint for main function
Om-Alve 69d9456
Added doctest for main
Om-Alve a1f40d3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 89a0fc1
Replaced main function
Om-Alve 90b8318
Solved merge conflicts
Om-Alve cd01d4d
changed the references section
Om-Alve 95471d9
removed repetitive datatype hint in the docstring
Om-Alve df7b182
changed dictionary comprehension variable names to something more com…
Om-Alve 74d71d0
Update fractionated_morse_cipher.py
cclauss File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
""" | ||
Python program for the Fractionated Morse Cipher. | ||
|
||
The Fractionated Morse cipher first converts the plaintext to morse code, | ||
then enciphers fixed-size blocks of morse code back to letters. | ||
This procedure means plaintext letters are mixed into the ciphertext letters, | ||
making it more secure than substitution ciphers. | ||
|
||
For more information visit - http://practicalcryptography.com/ciphers/fractionated-morse-cipher/ | ||
|
||
""" | ||
|
||
|
||
import string | ||
|
||
# Define Morse code dictionary | ||
MORSE_CODE_DICT = { | ||
"A": ".-", | ||
"B": "-...", | ||
"C": "-.-.", | ||
"D": "-..", | ||
"E": ".", | ||
"F": "..-.", | ||
"G": "--.", | ||
"H": "....", | ||
"I": "..", | ||
"J": ".---", | ||
"K": "-.-", | ||
"L": ".-..", | ||
"M": "--", | ||
"N": "-.", | ||
"O": "---", | ||
"P": ".--.", | ||
"Q": "--.-", | ||
"R": ".-.", | ||
"S": "...", | ||
"T": "-", | ||
"U": "..-", | ||
"V": "...-", | ||
"W": ".--", | ||
"X": "-..-", | ||
"Y": "-.--", | ||
"Z": "--..", | ||
" ": "", | ||
} | ||
|
||
# Define possible trigrams of Morse code | ||
MORSE_COMBINATIONS = [ | ||
"...", | ||
"..-", | ||
"..x", | ||
".-.", | ||
".--", | ||
".-x", | ||
".x.", | ||
".x-", | ||
".xx", | ||
"-..", | ||
"-.-", | ||
"-.x", | ||
"--.", | ||
"---", | ||
"--x", | ||
"-x.", | ||
"-x-", | ||
"-xx", | ||
"x..", | ||
"x.-", | ||
"x.x", | ||
"x-.", | ||
"x--", | ||
"x-x", | ||
"xx.", | ||
"xx-", | ||
"xxx", | ||
] | ||
|
||
# Create a reverse dictionary for Morse code | ||
REVERSE_DICT = {value: key for key, value in MORSE_CODE_DICT.items()} | ||
|
||
|
||
def encode_to_morse(plaintext: str) -> str: | ||
"""Encode a plaintext message into Morse code. | ||
|
||
Args: | ||
plaintext (str): The plaintext message to encode. | ||
Om-Alve marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Returns: | ||
str: The Morse code representation of the plaintext message. | ||
|
||
Example: | ||
>>> encode_to_morse("defend the east") | ||
'-..x.x..-.x.x-.x-..xx-x....x.xx.x.-x...x-' | ||
""" | ||
return "x".join([MORSE_CODE_DICT.get(letter.upper(), "") for letter in plaintext]) | ||
|
||
|
||
def encrypt_fractionated_morse(plaintext: str, key: str) -> str: | ||
"""Encrypt a plaintext message using Fractionated Morse Cipher. | ||
|
||
Args: | ||
plaintext (str): The plaintext message to encrypt. | ||
key (str): The encryption key. | ||
|
||
Returns: | ||
str: The encrypted ciphertext. | ||
|
||
Example: | ||
>>> encrypt_fractionated_morse("defend the east","Roundtable") | ||
'ESOAVVLJRSSTRX' | ||
|
||
""" | ||
morse_code = encode_to_morse(plaintext) | ||
key = key.upper() + string.ascii_uppercase | ||
key = "".join(sorted(set(key), key=key.find)) | ||
|
||
# Ensure morse_code length is a multiple of 3 | ||
padding_length = 3 - (len(morse_code) % 3) | ||
morse_code += "x" * padding_length | ||
|
||
fractionated_morse_dict = { | ||
value: key for key, value in zip(key, MORSE_COMBINATIONS) | ||
} | ||
Om-Alve marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fractionated_morse_dict["xxx"] = "" | ||
encrypted_text = "".join( | ||
[ | ||
fractionated_morse_dict[morse_code[i : i + 3]] | ||
for i in range(0, len(morse_code), 3) | ||
] | ||
) | ||
return encrypted_text | ||
|
||
|
||
def decrypt_fractionated_morse(ciphertext: str, key: str) -> str: | ||
"""Decrypt a ciphertext message encrypted with Fractionated Morse Cipher. | ||
|
||
Args: | ||
ciphertext (str): The ciphertext message to decrypt. | ||
key (str): The decryption key. | ||
|
||
Returns: | ||
str: The decrypted plaintext message. | ||
|
||
Example: | ||
>>> decrypt_fractionated_morse("ESOAVVLJRSSTRX","Roundtable") | ||
'DEFEND THE EAST' | ||
""" | ||
key = key.upper() + string.ascii_uppercase | ||
key = "".join(sorted(set(key), key=key.find)) | ||
|
||
inverse_fractionated_morse_dict = dict(zip(key, MORSE_COMBINATIONS)) | ||
morse_code = "".join( | ||
[inverse_fractionated_morse_dict.get(letter, "") for letter in ciphertext] | ||
) | ||
decrypted_text = "".join( | ||
[REVERSE_DICT[code] for code in morse_code.split("x")] | ||
).strip() | ||
return decrypted_text | ||
|
||
|
||
def main() -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As there is no test file in this pull request nor any test function or class in the file |
||
""" | ||
Example usage of Fractionated Morse Cipher. | ||
""" | ||
plaintext = "defend the east" | ||
print("Plain Text:", plaintext) | ||
key = "ROUNDTABLE" | ||
|
||
ciphertext = encrypt_fractionated_morse(plaintext, key) | ||
print("Encrypted:", ciphertext) | ||
|
||
decrypted_text = decrypt_fractionated_morse(ciphertext, key) | ||
print("Decrypted:", decrypted_text) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.