rustgym/leetcode/
_224_basic_calculator.rs1struct Solution;
2
3use std::iter::Peekable;
4use std::str::Chars;
5use std::vec::IntoIter;
6
7#[derive(Debug)]
8enum Tok {
9 Num(i32),
10 Op(char),
11}
12
13impl Solution {
14 fn calculate(s: String) -> i32 {
15 let mut it = s.chars().peekable();
16 let tokens = Self::parse_tokens(&mut it);
17 let mut it = tokens.into_iter().peekable();
18 Self::parse(&mut it)
19 }
20
21 fn parse_term(it: &mut Peekable<IntoIter<Tok>>) -> i32 {
22 if Self::eat(it, '(') {
23 let res = Self::parse(it);
24 Self::eat(it, ')');
25 res
26 } else {
27 if let Some(Tok::Num(x)) = it.next() {
28 x
29 } else {
30 panic!()
31 }
32 }
33 }
34
35 fn parse(it: &mut Peekable<IntoIter<Tok>>) -> i32 {
36 let mut left = Self::parse_term(it);
37 loop {
38 if Self::eat(it, '+') {
39 left += Self::parse_term(it);
40 continue;
41 }
42 if Self::eat(it, '-') {
43 left -= Self::parse_term(it);
44 continue;
45 }
46 break;
47 }
48 left
49 }
50
51 fn eat(it: &mut Peekable<IntoIter<Tok>>, c: char) -> bool {
52 if let Some(&Tok::Op(first)) = it.peek() {
53 if first == c {
54 it.next();
55 return true;
56 }
57 }
58 false
59 }
60
61 fn parse_tokens(it: &mut Peekable<Chars>) -> Vec<Tok> {
62 let mut res = vec![];
63 while let Some(c) = it.next() {
64 match c {
65 '0'..='9' => {
66 let mut x = (c as u8 - b'0') as i32;
67 while let Some('0'..='9') = it.peek() {
68 x *= 10;
69 x += (it.next().unwrap() as u8 - b'0') as i32;
70 }
71 res.push(Tok::Num(x));
72 }
73 '(' | ')' | '+' | '-' => {
74 res.push(Tok::Op(c));
75 }
76 _ => {}
77 }
78 }
79 res
80 }
81}
82
83#[test]
84fn test() {
85 let s = "1 + 1".to_string();
86 let res = 2;
87 assert_eq!(Solution::calculate(s), res);
88 let s = " 2-1 + 2 ".to_string();
89 let res = 3;
90 assert_eq!(Solution::calculate(s), res);
91 let s = "(1+(4+5+2)-3)+(6+8)".to_string();
92 let res = 23;
93 assert_eq!(Solution::calculate(s), res);
94}