diff --git a/Cargo.toml b/Cargo.toml index ed5f88f..ffe153c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" num = "0.4.0" rand = "0.8.5" hashbrown = { version = "0.14.3" } +lazy_static = "1.4.0" [dev-dependencies] diff --git a/src/ciphers/mod.rs b/src/ciphers/mod.rs new file mode 100644 index 0000000..7a597d8 --- /dev/null +++ b/src/ciphers/mod.rs @@ -0,0 +1,3 @@ +//! A module of cipher algorithms + +pub mod morse_code; diff --git a/src/ciphers/morse_code.rs b/src/ciphers/morse_code.rs new file mode 100644 index 0000000..7efc204 --- /dev/null +++ b/src/ciphers/morse_code.rs @@ -0,0 +1,151 @@ +//! This module provides functions to convert characters to Morse code and vice versa, +//! as well as functions to encrypt and decrypt text using Morse code. + +use alloc::{string::String, vec::Vec}; +use hashbrown::HashMap; + +use crate::macros::hashmap; + +lazy_static::lazy_static! { + static ref MORSE_TABLE: HashMap = hashmap! { + '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' => "--..", + '1' => ".----", + '2' => "..---", + '3' => "...--", + '4' => "....-", + '5' => ".....", + '6' => "-....", + '7' => "--...", + '8' => "---..", + '9' => "----.", + '0' => "-----", + '.' => ".-.-.-", + ',' => "--..--", + '?' => "..--..", + '\'' => ".----.", + '!' => "-.-.--", + '/' => "-..-.", + '(' => "-.--.", + ')' => "-.--.-", + '&' => ".-...", + ':' => "---...", + ';' => "-.-.-.", + '=' => "-...-", + '+' => ".-.-.", + '-' => "-....-", + '_' => "..--.-", + '"' => ".-..-.", + '$' => "...-..-", + '@' => ".--.-.", + '¿' => "..-.-", + '¡' => "--...-", + }; +} + +/// Encrypts a text by converting each character to Morse code. +/// +/// # Arguments +/// +/// * `text` - A string slice that represents the text to be encrypted. +/// +/// # Returns +/// +/// * A string that represents the encrypted text. +#[must_use] +pub fn encrypt(text: &str) -> String { + let text_lowered = text.to_lowercase(); + let words = text_lowered.split(' ').collect::>(); + let mut morse = String::new(); + + for (index, word) in words.iter().enumerate() { + for (index, character) in word.char_indices() { + morse.push_str(MORSE_TABLE[&character]); + + if index == word.len() { + morse.push_str(""); + } else { + morse.push_str(" "); + } + } + + if index == words.len() - 1 { + morse.push_str(""); + } else { + morse.push_str(" / "); + } + } + + morse +} + +/// Decrypts a text by converting each Morse code to its character equivalent. +/// +/// # Arguments +/// +/// * `text` - A string slice that represents the Morse code to be decrypted. +/// +/// # Returns +/// +/// * A string that represents the decrypted text. +#[must_use] +pub fn decrypt(text: &str) -> String { + let mut decrypted_text = String::new(); + + let splits = text + .split(char::is_whitespace) + .filter(|s| !s.is_empty()) + .collect::>(); + + for split in &splits { + for (key, value) in MORSE_TABLE.iter() { + if split == value { + decrypted_text.push(*key); + } + } + } + + decrypted_text +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn test_morse() { + let text = "01234567890"; + let encrypted = encrypt(text); + let decrypted = decrypt(&encrypted); + assert_eq!(text, decrypted); + + let text = "abcdefghijklmnopqrstuvwxyz"; + let encrypted = encrypt(text); + let decrypted = decrypt(&encrypted); + assert_eq!(text, decrypted); + } +} diff --git a/src/lib.rs b/src/lib.rs index f481076..3f7880a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ extern crate alloc; +pub mod ciphers; pub mod dynamic_programming; pub mod macros; pub mod math; diff --git a/src/sorts/bubble.rs b/src/sorts/bubble.rs index 08cf872..55a74b6 100644 --- a/src/sorts/bubble.rs +++ b/src/sorts/bubble.rs @@ -60,8 +60,8 @@ where #[cfg(test)] mod tests { - use alloc::vec::Vec; use alloc::vec; + use alloc::vec::Vec; use test_case::test_case; diff --git a/src/sorts/bucket.rs b/src/sorts/bucket.rs index f67189c..f4c39d4 100644 --- a/src/sorts/bucket.rs +++ b/src/sorts/bucket.rs @@ -1,5 +1,5 @@ -use alloc::vec::Vec; use alloc::vec; +use alloc::vec::Vec; /// A Rust bucket sort implementation /// diff --git a/src/sorts/counting.rs b/src/sorts/counting.rs index d9942a3..ad7de49 100644 --- a/src/sorts/counting.rs +++ b/src/sorts/counting.rs @@ -1,5 +1,5 @@ -use alloc::vec::Vec; use alloc::vec; +use alloc::vec::Vec; use core::ops::AddAssign; diff --git a/src/sorts/insertion.rs b/src/sorts/insertion.rs index 5ac4629..893209a 100644 --- a/src/sorts/insertion.rs +++ b/src/sorts/insertion.rs @@ -87,7 +87,7 @@ where #[cfg(test)] mod tests { use test_case::test_case; - + use alloc::vec; use alloc::vec::Vec;