diff options
author | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-15 23:56:23 +0200 |
---|---|---|
committer | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-15 23:56:23 +0200 |
commit | b66833f6dc447906c31a1eca03bdcdfe26069a8f (patch) | |
tree | aac12e2d87ea88362c50009d197d6fb4eb951781 /src | |
download | rpn-parse-rs-b66833f6dc447906c31a1eca03bdcdfe26069a8f.tar.gz rpn-parse-rs-b66833f6dc447906c31a1eca03bdcdfe26069a8f.tar.bz2 rpn-parse-rs-b66833f6dc447906c31a1eca03bdcdfe26069a8f.zip |
feat(cs): implemented rpn
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 107 | ||||
-rw-r--r-- | src/rpn.rs | 54 |
2 files changed, 161 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f7fe16c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,107 @@ +mod rpn; +use std::{collections::HashMap, io::stdin}; +/*struct TextSettings {} +struct Component { + text: String, + setting: TextSettings, +} +struct Article { + title: String, + components: Vec<Component>, +} +impl Display for Component { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.text) + } +} +impl Component { + fn new(text: String, setting: Option<TextSettings>) -> Component { + match setting { + Some(s) => { + return Component { + text, + setting: s, + } + }, + None => { + return Component { + text, + setting: TextSettings {} + } + } + } + } +} +impl Article { + fn new(lines: Vec<String>) -> Article { + let mut components = vec![]; + for (i, l) in lines.iter().enumerate() { + components.insert(i, Component::new(l.to_string(), None)); + } + Article { + title: "article title".to_string(), + components, + } + } +} +impl Display for Article { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut builder = String::from(""); + for c in &self.components { + builder += &format!("{}\n", c); + } + write!(f, "{}", builder) + } +}*/ +fn main() { + let mut vars: HashMap<char, f32> = HashMap::new(); + println!("Input your variable mappings below, in K:char,V:f32 format, * to break;"); + let term = stdin(); + loop { + let mut s = String::new(); + let _ = term.read_line(&mut s); + if s.trim() == "*" { + break; + } + let vals = s.trim().split_once(','); + if vals.is_none() { + println!("Format invalid!"); + return; + } + let (k_s, v_s) = vals.unwrap(); + println!("'{}': '{}'", k_s, v_s); + if k_s.chars().count() != 1 { + println!("Identifier must only be one character!"); + return; + } + let k = k_s.chars().next(); + if k.is_none() { + return; + } + vars.insert(k.unwrap(), v_s.parse::<f32>().unwrap()); + } + println!("Great! Now put your RPN expression below"); + let mut rpn_str = String::new(); + let _ = term.read_line(&mut rpn_str); + let result = rpn::eval(rpn_str.trim().to_string(), vars); + match result { + Ok(number) => println!("Result: {}", number), + Err(_) => println!("Error occurred"), + } +} +/*fn _main() -> Result<(), Box<dyn Error>> { + println!("running main function"); + let mut cont = true; + let mut lines: Vec<String> = vec![]; + while true { + let mut s = String::new(); + let input = stdin(); + let _size = input.read_line(&mut s); + println!("{}", s); + if s.eq("stop") { break; } + lines.push(s); + } + let a = Article::new(lines); + println!("{}", a); + Ok(()) +}*/ diff --git a/src/rpn.rs b/src/rpn.rs new file mode 100644 index 0000000..92272ba --- /dev/null +++ b/src/rpn.rs @@ -0,0 +1,54 @@ +use std::collections::HashMap; + +pub enum RpnOperation { + Add, + Subtract, + Multiply, + Divide, +} +fn apply_op(op: RpnOperation, v1: f32, v2: f32) -> f32 { + match op { + RpnOperation::Add => v1 + v2, + RpnOperation::Subtract => v1 - v2, + RpnOperation::Multiply => v1 * v2, + RpnOperation::Divide => v1 / v2, + } +} +fn rpn_match_op(c: char) -> Option<RpnOperation> { + match c { + '+' => Some(RpnOperation::Add), + '-' => Some(RpnOperation::Subtract), + '/' => Some(RpnOperation::Divide), + '*' => Some(RpnOperation::Multiply), + _ => None, + } +} +pub fn eval(rpn_str: String, var_map: HashMap<char, f32>) -> Result<f32, ()> { + let mut stack: Vec<f32> = vec![]; + for (_i, ch) in rpn_str.chars().enumerate() { + println!("Parsing: {}", ch); + let res = rpn_match_op(ch); + if res.is_none() { + let num = var_map.get(&ch); + if num.is_none() { + return Err(()); + } + stack.push(*num.unwrap()); + continue; + } + let v1 = stack.pop(); + let v2 = stack.pop(); + if v1.is_none() || v2.is_none() { + return Err(()); + } + let num = apply_op(res.unwrap(), v1.unwrap(), v2.unwrap()); + println!("Result tmp: {}", num); + stack.push(num) + } + if stack.len() != 1 { + return Err(()); + } + Ok(stack + .pop() + .expect("Expected there to be at least 1 element left...")) +} |