rustgym/leetcode/
_224_basic_calculator.rs

1struct 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}