From 98b78ed667dffb6b06895a9c43ba4c47ff132bc6 Mon Sep 17 00:00:00 2001 From: Abheelash-Mishra Date: Sun, 12 Oct 2025 22:37:57 +0530 Subject: [PATCH 1/4] Implement modified vigenere cipher for all printable ASCII --- ciphers/printable_ascii_vigenere_cipher.py | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 ciphers/printable_ascii_vigenere_cipher.py diff --git a/ciphers/printable_ascii_vigenere_cipher.py b/ciphers/printable_ascii_vigenere_cipher.py new file mode 100644 index 000000000000..c42c9098f59d --- /dev/null +++ b/ciphers/printable_ascii_vigenere_cipher.py @@ -0,0 +1,91 @@ +PRINTABLE_START = 32 +PRINTABLE_END = 126 +PRINTABLE_RANGE = PRINTABLE_END - PRINTABLE_START + 1 + + +def main() -> None: + """ + This program encrypts or decrypts messages using a modified Vigenere cipher + that operates only on printable ASCII characters (from 32-126). + Each character in the message is shifted by a value derived from the corresponding + character in the key. When the end of the key is reached, it repeats cyclically. + + Algorithm summary: + - For each printable character: + * Convert both the message and key characters to their ASCII codes. + * During encryption: add the key's ASCII value to the message character. + * During decryption: subtract the key's ASCII value from the message character. + * Wrap the result within the printable ASCII range using modulo arithmetic. + - Non-printable characters are left unchanged. + - The key repeats automatically to match the message length. + """ + message = input("Enter message: ") + key = input("Enter secret key: ") + mode = input("Encrypt/Decrypt [e/d]: ") + + if mode.lower().startswith("e"): + mode = "encrypt" + translated = encrypt_message(key, message) + elif mode.lower().startswith("d"): + mode = "decrypt" + translated = decrypt_message(key, message) + else: + print("Invalid mode. Use 'e' or 'd'.") + return + + print(f"\n{mode.title()}ed message: {translated}") + + +def encrypt_message(key: str, message: str) -> str: + """ + Encrypts a message using printable ASCII Vigenere cipher. + + >>> encrypt_message('key', 'Hello!') + "Tk'xu;" + """ + return translate_message(key, message, "encrypt") + + +def decrypt_message(key: str, message: str) -> str: + """ + Decrypts a message using printable ASCII Vigenere cipher. + + >>> decrypt_message('key', "Tk'xu;") + 'Hello!' + """ + return translate_message(key, message, "decrypt") + + +def translate_message(key: str, message: str, mode: str) -> str: + translated = [] + key_index = 0 + key_bytes = [ord(ch) for ch in key] + + for symbol in message: + sym_val = ord(symbol) + + if PRINTABLE_START <= sym_val <= PRINTABLE_END: + key_val = key_bytes[key_index] + + if mode == "encrypt": + new_val = ( + sym_val - PRINTABLE_START + key_val + ) % PRINTABLE_RANGE + PRINTABLE_START + elif mode == "decrypt": + new_val = ( + sym_val - PRINTABLE_START - key_val + ) % PRINTABLE_RANGE + PRINTABLE_START + else: + raise ValueError("Mode must be 'encrypt' or 'decrypt'") + + translated.append(chr(new_val)) + + key_index = (key_index + 1) % len(key_bytes) + else: + translated.append(symbol) + + return "".join(translated) + + +if __name__ == "__main__": + main() From baecafecf8e72badd25aee1826ace4e914921c62 Mon Sep 17 00:00:00 2001 From: Abheelash-Mishra Date: Sun, 12 Oct 2025 22:52:40 +0530 Subject: [PATCH 2/4] Improve docstrings --- DIRECTORY.md | 1 + ciphers/printable_ascii_vigenere_cipher.py | 37 +++++++++++++--------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 0f9859577493..b3b8ec5bb831 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -109,6 +109,7 @@ * [Morse Code](ciphers/morse_code.py) * [Onepad Cipher](ciphers/onepad_cipher.py) * [Permutation Cipher](ciphers/permutation_cipher.py) + * [Printable ASCII Vigenere Cipher](ciphers/printable_ascii_vigenere_cipher.py) * [Playfair Cipher](ciphers/playfair_cipher.py) * [Polybius](ciphers/polybius.py) * [Porta Cipher](ciphers/porta_cipher.py) diff --git a/ciphers/printable_ascii_vigenere_cipher.py b/ciphers/printable_ascii_vigenere_cipher.py index c42c9098f59d..4db72b06aebc 100644 --- a/ciphers/printable_ascii_vigenere_cipher.py +++ b/ciphers/printable_ascii_vigenere_cipher.py @@ -1,24 +1,27 @@ +""" +This program encrypts or decrypts messages using a modified Vigenere cipher +that operates on all printable ASCII characters (from 32-126) instead of just letters. +Each character in the message is shifted by a value derived from the corresponding +character in the key. When the end of the key is reached, it repeats cyclically. + +Algorithm summary: +- For each printable character: + * Convert both the message and key characters to their ASCII codes. + * During encryption: add the key's ASCII value to the message character. + * During decryption: subtract the key's ASCII value from the message character. + * Wrap the result within the printable ASCII range using modulo arithmetic. +- Non-printable characters are left unchanged. +- The key repeats automatically to match the message length. + +Reference: https://stackoverflow.com/questions/28182091/ascii-vigenere-cipher-implementation-in-java +""" + PRINTABLE_START = 32 PRINTABLE_END = 126 PRINTABLE_RANGE = PRINTABLE_END - PRINTABLE_START + 1 def main() -> None: - """ - This program encrypts or decrypts messages using a modified Vigenere cipher - that operates only on printable ASCII characters (from 32-126). - Each character in the message is shifted by a value derived from the corresponding - character in the key. When the end of the key is reached, it repeats cyclically. - - Algorithm summary: - - For each printable character: - * Convert both the message and key characters to their ASCII codes. - * During encryption: add the key's ASCII value to the message character. - * During decryption: subtract the key's ASCII value from the message character. - * Wrap the result within the printable ASCII range using modulo arithmetic. - - Non-printable characters are left unchanged. - - The key repeats automatically to match the message length. - """ message = input("Enter message: ") key = input("Enter secret key: ") mode = input("Encrypt/Decrypt [e/d]: ") @@ -42,6 +45,8 @@ def encrypt_message(key: str, message: str) -> str: >>> encrypt_message('key', 'Hello!') "Tk'xu;" + >>> encrypt_message('SUpeR$eCR3t_KEY', 'This is a message to encrypt.') + 'H^zyr.ycTS#e_Y[[[1zbDkRVF/p`s' """ return translate_message(key, message, "encrypt") @@ -52,6 +57,8 @@ def decrypt_message(key: str, message: str) -> str: >>> decrypt_message('key', "Tk'xu;") 'Hello!' + >>> decrypt_message('SUpeR$eCR3t_KEY', 'H^zyr.ycTS#e_Y[[[1zbDkRVF/p`s') + 'This is a message to encrypt.' """ return translate_message(key, message, "decrypt") From e371c10ba27af0de048b84849a94af4e2ac3ed6e Mon Sep 17 00:00:00 2001 From: Abheelash-Mishra Date: Sun, 12 Oct 2025 23:02:23 +0530 Subject: [PATCH 3/4] Add more doctests --- ciphers/printable_ascii_vigenere_cipher.py | 43 ++++++++++++---------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/ciphers/printable_ascii_vigenere_cipher.py b/ciphers/printable_ascii_vigenere_cipher.py index 4db72b06aebc..5a2b752ac13d 100644 --- a/ciphers/printable_ascii_vigenere_cipher.py +++ b/ciphers/printable_ascii_vigenere_cipher.py @@ -21,24 +21,6 @@ PRINTABLE_RANGE = PRINTABLE_END - PRINTABLE_START + 1 -def main() -> None: - message = input("Enter message: ") - key = input("Enter secret key: ") - mode = input("Encrypt/Decrypt [e/d]: ") - - if mode.lower().startswith("e"): - mode = "encrypt" - translated = encrypt_message(key, message) - elif mode.lower().startswith("d"): - mode = "decrypt" - translated = decrypt_message(key, message) - else: - print("Invalid mode. Use 'e' or 'd'.") - return - - print(f"\n{mode.title()}ed message: {translated}") - - def encrypt_message(key: str, message: str) -> str: """ Encrypts a message using printable ASCII Vigenere cipher. @@ -64,6 +46,14 @@ def decrypt_message(key: str, message: str) -> str: def translate_message(key: str, message: str, mode: str) -> str: + """ + Translates (encrypts or decrypts) a message using the given key. + + >>> translate_message('key', 'Hello!', 'encrypt') + "Tk'xu;" + >>> translate_message('key', "Tk'xu;", 'decrypt') + 'Hello!' + """ translated = [] key_index = 0 key_bytes = [ord(ch) for ch in key] @@ -95,4 +85,19 @@ def translate_message(key: str, message: str, mode: str) -> str: if __name__ == "__main__": - main() + message = input("Enter message: ") + key = input("Enter secret key: ") + mode = input("Encrypt/Decrypt [e/d]: ") + + if mode.lower().startswith("e"): + mode = "encrypt" + translated = encrypt_message(key, message) + + print(f"Encrypted message: {translated}") + elif mode.lower().startswith("d"): + mode = "decrypt" + translated = decrypt_message(key, message) + + print(f"Decrypted message: {translated}") + else: + print("Invalid mode. Use 'e' or 'd'.") From f30bbab332773d0784b9289caa26d3d3e7dc6263 Mon Sep 17 00:00:00 2001 From: cclauss Date: Tue, 15 Sep 2026 04:40:10 +0000 Subject: [PATCH 4/4] updating DIRECTORY.md --- DIRECTORY.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 4b51587fac13..8371504db006 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -62,6 +62,7 @@ * [Generate Parentheses Iterative](backtracking/generate_parentheses_iterative.py) * [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py) * [Knight Tour](backtracking/knight_tour.py) + * [M Coloring Problem](backtracking/m_coloring_problem.py) * [Match Word Pattern](backtracking/match_word_pattern.py) * [Minimax](backtracking/minimax.py) * [N Queens](backtracking/n_queens.py) @@ -108,6 +109,9 @@ ## [Blockchain](blockchain) * [Diophantine Equation](blockchain/diophantine_equation.py) + * [Merkle Tree](blockchain/merkle_tree.py) + * [Simple Blockchain](blockchain/simple_blockchain.py) + * [Simple Proof Of Work](blockchain/simple_proof_of_work.py) ## [Boolean Algebra](boolean_algebra) * [And Gate](boolean_algebra/and_gate.py) @@ -161,10 +165,10 @@ * [Morse Code](ciphers/morse_code.py) * [Onepad Cipher](ciphers/onepad_cipher.py) * [Permutation Cipher](ciphers/permutation_cipher.py) - * [Printable ASCII Vigenere Cipher](ciphers/printable_ascii_vigenere_cipher.py) * [Playfair Cipher](ciphers/playfair_cipher.py) * [Polybius](ciphers/polybius.py) * [Porta Cipher](ciphers/porta_cipher.py) + * [Printable Ascii Vigenere Cipher](ciphers/printable_ascii_vigenere_cipher.py) * [Rabin Miller](ciphers/rabin_miller.py) * [Rail Fence Cipher](ciphers/rail_fence_cipher.py) * [Rot13](ciphers/rot13.py) @@ -690,6 +694,7 @@ * [Astar](machine_learning/astar.py) * [Automatic Differentiation](machine_learning/automatic_differentiation.py) * [Data Transformations](machine_learning/data_transformations.py) + * [Dbscan](machine_learning/dbscan.py) * [Decision Tree](machine_learning/decision_tree.py) * [Dimensionality Reduction](machine_learning/dimensionality_reduction.py) * [Federated Averaging](machine_learning/federated_averaging.py) @@ -713,15 +718,18 @@ * [Loss Functions](machine_learning/loss_functions.py) * Lstm * [Lstm Prediction](machine_learning/lstm/lstm_prediction.py) + * [Mean Shift](machine_learning/mean_shift.py) * [Mfcc](machine_learning/mfcc.py) * [Mini Batch Gradient Descent](machine_learning/mini_batch_gradient_descent.py) * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py) + * [Naive Bayes Text Classification](machine_learning/naive_bayes_text_classification.py) * [Ordinary Least Squares Regression](machine_learning/ordinary_least_squares_regression.py) * [Polynomial Regression](machine_learning/polynomial_regression.py) * [Principle Component Analysis](machine_learning/principle_component_analysis.py) * [Q Learning](machine_learning/q_learning.py) * [Random Forest Classifier](machine_learning/random_forest_classifier.py) * [Random Forest Regressor](machine_learning/random_forest_regressor.py) + * [Rmsprop](machine_learning/rmsprop.py) * [Scoring Functions](machine_learning/scoring_functions.py) * [Self Organizing Map](machine_learning/self_organizing_map.py) * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py) @@ -738,6 +746,7 @@ * [Arc Length](maths/arc_length.py) * [Area](maths/area.py) * [Area Under Curve](maths/area_under_curve.py) + * [Autocorrelation](maths/autocorrelation.py) * [Average Absolute Deviation](maths/average_absolute_deviation.py) * [Average Mean](maths/average_mean.py) * [Average Median](maths/average_median.py) @@ -783,6 +792,7 @@ * [Fibonacci](maths/fibonacci.py) * [Find Max](maths/find_max.py) * [Find Min](maths/find_min.py) + * [First Fundamental Form](maths/first_fundamental_form.py) * [Floor](maths/floor.py) * [Gamma](maths/gamma.py) * [Gaussian](maths/gaussian.py) @@ -845,6 +855,7 @@ * [Square Root](maths/numerical_analysis/square_root.py) * [Weierstrass Method](maths/numerical_analysis/weierstrass_method.py) * [Odd Sieve](maths/odd_sieve.py) + * [Padovan Sequence](maths/padovan_sequence.py) * [Pell Number](maths/pell_number.py) * [Perfect Cube](maths/perfect_cube.py) * [Perfect Number](maths/perfect_number.py) @@ -874,6 +885,8 @@ * [Reverse Factorial Recursive](maths/reverse_factorial_recursive.py) * [Segmented Sieve](maths/segmented_sieve.py) * Series + * [Alternate Harmonic Series](maths/series/alternate_harmonic_series.py) + * [Alternating Harmonic Series](maths/series/alternating_harmonic_series.py) * [Arithmetic](maths/series/arithmetic.py) * [Geometric](maths/series/geometric.py) * [Geometric Series](maths/series/geometric_series.py) @@ -913,6 +926,7 @@ * [Polygonal Numbers](maths/special_numbers/polygonal_numbers.py) * [Pronic Number](maths/special_numbers/pronic_number.py) * [Proth Number](maths/special_numbers/proth_number.py) + * [Spy Number](maths/special_numbers/spy_number.py) * [Triangular Numbers](maths/special_numbers/triangular_numbers.py) * [Trimorphic Number](maths/special_numbers/trimorphic_number.py) * [Ugly Numbers](maths/special_numbers/ugly_numbers.py)