-
-
Save rust-play/57ffa4be87181efc62e1969f06ddb60f to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
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
| use std::rc::Rc; | |
| use std::cell::RefCell; | |
| use std::collections::HashMap; | |
| use anyhow::{anyhow, Result}; | |
| /// A node in our Morse Virtual Circuit binary tree. | |
| #[derive(Debug, Default)] | |
| struct Node { | |
| value: Option<char>, | |
| dot: Option<Rc<RefCell<Node>>>, | |
| dash: Option<Rc<RefCell<Node>>>, | |
| } | |
| struct MorseCircuit { | |
| root: Rc<RefCell<Node>>, | |
| encoder_map: HashMap<char, String>, | |
| } | |
| impl MorseCircuit { | |
| pub fn new() -> Self { | |
| let mut circuit = MorseCircuit { | |
| root: Rc::new(RefCell::new(Node::default())), | |
| encoder_map: HashMap::new(), | |
| }; | |
| let dataset = [ | |
| ('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', "-----"), | |
| ('.', ".-.-.-"), (',', "--..--"), ('?', "..--.."), ('/', "-..-."), | |
| ('-', "-....-"), ('(', "-.--."), (')', "-.--.-"), (' ', "/"), | |
| ]; | |
| for (ch, code) in dataset { | |
| circuit.insert(ch, code); | |
| } | |
| circuit | |
| } | |
| fn insert(&mut self, ch: char, code: &str) { | |
| self.encoder_map.insert(ch, code.to_string()); | |
| let mut current = Rc::clone(&self.root); | |
| for signal in code.chars() { | |
| let next = match signal { | |
| '.' => { | |
| let mut node = current.borrow_mut(); | |
| node.dot.get_or_insert_with(|| Rc::new(RefCell::new(Node::default()))).clone() | |
| } | |
| '-' => { | |
| let mut node = current.borrow_mut(); | |
| node.dash.get_or_insert_with(|| Rc::new(RefCell::new(Node::default()))).clone() | |
| } | |
| _ => continue, | |
| }; | |
| current = next; | |
| } | |
| current.borrow_mut().value = Some(ch); | |
| } | |
| /// Encodes text, returning an error if a character is not supported. | |
| pub fn encode(&self, text: &str) -> Result<String> { | |
| let mut results = Vec::new(); | |
| for ch in text.to_uppercase().chars() { | |
| let code = self.encoder_map.get(&ch) | |
| .ok_or_else(|| anyhow!("Character '{}' is not supported by the circuit", ch))?; | |
| results.push(code.clone()); | |
| } | |
| Ok(results.join(" ")) | |
| } | |
| /// Decodes signals, returning an error if a sequence leads to a dead end. | |
| pub fn decode(&self, morse: &str) -> Result<String> { | |
| let mut decoded_text = String::new(); | |
| for code in morse.split_whitespace() { | |
| if code == "/" { | |
| decoded_text.push(' '); | |
| continue; | |
| } | |
| let mut current = Rc::clone(&self.root); | |
| for signal in code.chars() { | |
| let next = match signal { | |
| '.' => current.borrow().dot.as_ref().map(Rc::clone), | |
| '-' => current.borrow().dash.as_ref().map(Rc::clone), | |
| _ => return Err(anyhow!("Invalid signal '{}' in sequence '{}'", signal, code)), | |
| }; | |
| current = next.ok_or_else(|| anyhow!("Signal path '{}' does not exist", code))?; | |
| } | |
| let val = current.borrow().value | |
| .ok_or_else(|| anyhow!("Sequence '{}' is incomplete or has no value", code))?; | |
| decoded_text.push(val); | |
| } | |
| Ok(decoded_text) | |
| } | |
| } | |
| fn main() -> Result<()> { | |
| let circuit = MorseCircuit::new(); | |
| // Successful Run | |
| let encoded = circuit.encode("Rust 2026")?; | |
| println!("Encoded: {}", encoded); | |
| println!("Decoded: {}", circuit.decode(&encoded)?); | |
| // Demonstration of Error Handling | |
| println!("\n--- Error Test ---"); | |
| match circuit.encode("Rust!") { | |
| Ok(_) => println!("Success!"), | |
| Err(e) => println!("Encode Error: {}", e), // Character '!' is not supported | |
| } | |
| match circuit.decode(".......") { | |
| Ok(_) => println!("Success!"), | |
| Err(e) => println!("Decode Error: {}", e), // Signal path '.......' does not exist | |
| } | |
| Ok(()) | |
| } | |
| #[cfg(test)] | |
| mod tests { | |
| use super::*; | |
| #[test] | |
| fn test_error_on_invalid_char() { | |
| let circuit = MorseCircuit::new(); | |
| assert!(circuit.encode("#").is_err()); | |
| } | |
| #[test] | |
| fn test_error_on_invalid_sequence() { | |
| let circuit = MorseCircuit::new(); | |
| assert!(circuit.decode("........").is_err()); | |
| } | |
| #[test] | |
| fn test_full_sentence_round_trip() -> Result<()> { | |
| let circuit = MorseCircuit::new(); | |
| let input = "HELLO WORLD 2026"; | |
| let encoded = circuit.encode(input)?; | |
| let decoded = circuit.decode(&encoded)?; | |
| assert_eq!(input, decoded); | |
| Ok(()) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment