diff --git a/DIRECTORY.md b/DIRECTORY.md index d6ceb04a62eb..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) @@ -164,6 +168,7 @@ * [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) @@ -689,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) @@ -712,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) @@ -737,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) @@ -782,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) @@ -844,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) @@ -873,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) @@ -912,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) diff --git a/ciphers/printable_ascii_vigenere_cipher.py b/ciphers/printable_ascii_vigenere_cipher.py new file mode 100644 index 000000000000..5a2b752ac13d --- /dev/null +++ b/ciphers/printable_ascii_vigenere_cipher.py @@ -0,0 +1,103 @@ +""" +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 encrypt_message(key: str, message: str) -> str: + """ + Encrypts a message using printable ASCII Vigenere cipher. + + >>> 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") + + +def decrypt_message(key: str, message: str) -> str: + """ + Decrypts a message using printable ASCII Vigenere cipher. + + >>> 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") + + +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] + + 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__": + 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'.")