Skip to content
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

added docs to morse_code. Modified mod.rs in ciphers to include decod… #78

Merged
merged 3 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ciphers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod xor;
pub use self::aes::{aes_decrypt, aes_encrypt, AesKey};
pub use self::another_rot13::another_rot13;
pub use self::caesar::caesar;
pub use self::morse_code::encode;
pub use self::morse_code::{decode, encode};
pub use self::polybius::{decode_ascii, encode_ascii};
pub use self::rot13::rot13;
pub use self::sha256::sha256;
Expand Down
153 changes: 127 additions & 26 deletions src/ciphers/morse_code.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,35 @@
use std::collections::HashMap;

// The character used to represent an unknown morse code sequence
const UNKNOWN_CHARACTER: &str = "........";

// The character used to represent an unknown morse code character
const _UNKNOWN_MORSE_CHARACTER: &str = "_";

/// Encode a message into morse code.
///
/// Given a message, this function encodes it into morse code.
/// It uses a dictionary to map each character to its corresponding morse code sequence.
/// If a character is not found in the dictionary, it is replaced with the unknown character sequence.
///
/// # Arguments
///
/// * `message` - The message to encode into morse code.
///
/// # Returns
///
/// The encoded morse code as a string.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::ciphers::encode;
///
/// let message = "Hello Morse";
/// let cipher = encode(message);
///
/// assert_eq!(cipher, ".... . .-.. .-.. --- / -- --- .-. ... .");
/// ```
Comment on lines +25 to +32
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you added this as a doc test, could you delete the corresponding test in mod tests?

pub fn encode(message: &str) -> String {
let dictionary = _morse_dictionary();
message
Expand All @@ -22,6 +49,13 @@ macro_rules! map {
};
}

/// Create the morse code to alphanumeric dictionary.
///
/// This function creates a HashMap that maps each morse code sequence to its corresponding alphanumeric character.
///
/// # Returns
///
/// The morse code to alphanumeric dictionary as a HashMap.
fn _morse_dictionary() -> HashMap<&'static str, &'static str> {
map! {
"A" => ".-", "B" => "-...", "C" => "-.-.",
Expand All @@ -48,6 +82,13 @@ fn _morse_dictionary() -> HashMap<&'static str, &'static str> {
}
}

/// Create the morse code to alphanumeric dictionary.
///
/// This function creates a HashMap that maps each morse code sequence to its corresponding alphanumeric character.
///
/// # Returns
///
/// The morse code to alphanumeric dictionary as a HashMap.
fn _morse_to_alphanumeric_dictionary() -> HashMap<&'static str, &'static str> {
map! {
".-" => "A", "-..." => "B", "-.-." => "C",
Expand All @@ -74,6 +115,17 @@ fn _morse_to_alphanumeric_dictionary() -> HashMap<&'static str, &'static str> {
}
}

/// Check if a string is a valid morse code part.
///
/// This function checks if a string contains only valid morse code characters ('.', '-', and ' ').
///
/// # Arguments
///
/// * `string` - The string to check.
///
/// # Returns
///
/// `true` if the string is a valid morse code part, `false` otherwise.
fn _check_part(string: &str) -> bool {
for c in string.chars() {
match c {
Expand All @@ -84,30 +136,45 @@ fn _check_part(string: &str) -> bool {
true
}

/// Check if a string is a valid morse code.
///
/// This function checks if a string is a valid morse code by splitting it into parts and checking each part.
///
/// # Arguments
///
/// * `string` - The string to check.
///
/// # Returns
///
/// `true` if the string is a valid morse code, `false` otherwise.
fn _check_all_parts(string: &str) -> bool {
string.split('/').all(_check_part)
}

fn _decode_token(string: &str) -> String {
_morse_to_alphanumeric_dictionary()
.get(string)
.unwrap_or(&_UNKNOWN_MORSE_CHARACTER)
.to_string()
}

fn _decode_part(string: &str) -> String {
string
.split(' ')
.map(_decode_token)
.collect::<Vec<String>>()
.join("")
}

/// Convert morse code to ascii.
/// Decode a morse code into an alphanumeric message.
///
/// Given a morse code, return the corresponding message.
/// If the code is invalid, the undecipherable part of the code is replaced by `_`.
#[cfg(test)]
/// Given a morse code, this function decodes it into an alphanumeric message.
/// It uses a dictionary to map each morse code sequence to its corresponding alphanumeric character.
/// If a morse code sequence is not found in the dictionary, it is replaced with the unknown morse code character.
/// If the morse code is invalid, an `InvalidData` error is returned.
///
/// # Arguments
///
/// * `string` - The morse code to decode into an alphanumeric message.
///
/// # Returns
///
/// The decoded alphanumeric message as a `Result` containing a `String` if successful, or an `InvalidData` error.
///
/// # Examples
///
/// ```rust
/// use rust_algorithms::ciphers::decode;
///
/// let message = decode(".... . .-.. .-.. --- / -- --- .-. ... .").unwrap();
///
/// assert_eq!(message, "HELLO MORSE");
/// ```
pub fn decode(string: &str) -> Result<String, std::io::Error> {
if !_check_all_parts(string) {
return Err(std::io::Error::new(
Expand All @@ -125,6 +192,47 @@ pub fn decode(string: &str) -> Result<String, std::io::Error> {
Ok(partitions.join(" "))
}

/// Decode a morse code token into an alphanumeric character.
///
/// This function decodes a morse code token into its corresponding alphanumeric character.
/// It uses a dictionary to map each morse code sequence to its corresponding alphanumeric character.
/// If the morse code token is not found in the dictionary, it is replaced with the unknown morse code character.
///
/// # Arguments
///
/// * `string` - The morse code token to decode into an alphanumeric character.
///
/// # Returns
///
/// The decoded alphanumeric character as a string.
///
fn _decode_token(string: &str) -> String {
_morse_to_alphanumeric_dictionary()
.get(string)
.unwrap_or(&_UNKNOWN_MORSE_CHARACTER)
.to_string()
}

/// Decode a morse code part into an alphanumeric string.
///
/// This function decodes a morse code part into its corresponding alphanumeric string.
/// It splits the part into tokens, decodes each token, and joins them together.
///
/// # Arguments
///
/// * `string` - The morse code part to decode into an alphanumeric string.
///
/// # Returns
///
/// The decoded alphanumeric string.
fn _decode_part(string: &str) -> String {
string
.split(' ')
.map(_decode_token)
.collect::<Vec<String>>()
.join("")
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -195,11 +303,4 @@ mod tests {

assert_eq!(expected, result);
}

#[test]
fn test_decode() {
let message = ".... . .-.. .-.. --- / -- --- .-. ... .";
let cipher = decode(message).unwrap();
assert_eq!(cipher, "HELLO MORSE");
}
}
Loading