Skip to content

Commit 5714656

Browse files
committed
Solve #224
1 parent c03b439 commit 5714656

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,4 @@ mod n0219_contains_duplicate_ii;
191191
mod n0221_maximal_square;
192192
mod n0223_rectangle_area;
193193
mod n0222_count_complete_tree_nodes;
194+
mod n0224_basic_calculator;

src/n0224_basic_calculator.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* [224] Basic Calculator
3+
*
4+
* Implement a basic calculator to evaluate a simple expression string.
5+
*
6+
* The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .
7+
*
8+
* Example 1:
9+
*
10+
*
11+
* Input: "1 + 1"
12+
* Output: 2
13+
*
14+
*
15+
* Example 2:
16+
*
17+
*
18+
* Input: " 2-1 + 2 "
19+
* Output: 3
20+
*
21+
* Example 3:
22+
*
23+
*
24+
* Input: "(1+(4+5+2)-3)+(6+8)"
25+
* Output: 23
26+
* Note:
27+
*
28+
*
29+
* You may assume that the given expression is always valid.
30+
* Do not use the eval built-in library function.
31+
*
32+
*
33+
*/
34+
pub struct Solution {}
35+
36+
// submission codes start here
37+
38+
#[derive(PartialEq,Copy,Clone,Debug)]
39+
enum Token {
40+
LeftBracket,
41+
RightBracket,
42+
PlusSign,
43+
MinusSign,
44+
Number(i64),
45+
}
46+
47+
impl Solution {
48+
pub fn calculate(s: String) -> i32 {
49+
// lexer
50+
let mut token_stream = Vec::new();
51+
let mut num = 0_i64;
52+
let mut in_num = false;
53+
for ch in s.chars() {
54+
match ch {
55+
'0'...'9' => {
56+
in_num = true;
57+
num = 10 * num + (ch as u8 - '0' as u8) as i64;
58+
}
59+
_ => {
60+
if in_num {
61+
token_stream.push(Token::Number(num));
62+
num = 0;
63+
in_num = false;
64+
}
65+
match ch {
66+
'(' => { token_stream.push(Token::LeftBracket); },
67+
')' => { token_stream.push(Token::RightBracket); },
68+
'+' => { token_stream.push(Token::PlusSign); },
69+
'-' => { token_stream.push(Token::MinusSign); },
70+
_ => {},
71+
};
72+
},
73+
}
74+
}
75+
if in_num {
76+
token_stream.push(Token::Number(num));
77+
}
78+
79+
80+
// parser
81+
let mut stack = Vec::new();
82+
let mut iter = token_stream.into_iter();
83+
let mut pause = false;
84+
let mut token = Token::LeftBracket;
85+
loop {
86+
if !pause {
87+
token = if let Some(token) = iter.next() {
88+
token
89+
} else {
90+
break;
91+
}
92+
} else {
93+
pause = false;
94+
}
95+
match token {
96+
Token::LeftBracket => {
97+
stack.push(token);
98+
},
99+
Token::RightBracket => {
100+
if let Token::Number(right_hand) = stack.pop().unwrap() {
101+
stack.pop();
102+
pause = true;
103+
token = Token::Number(right_hand);
104+
}
105+
},
106+
Token::PlusSign => {
107+
stack.push(token);
108+
},
109+
Token::MinusSign => {
110+
stack.push(token);
111+
},
112+
Token::Number(num) => {
113+
if stack.is_empty() || Token::LeftBracket == *stack.last().unwrap() {
114+
stack.push(Token::Number(num));
115+
} else {
116+
let sign = stack.pop().unwrap();
117+
if let Token::Number(left_hand) = stack.pop().unwrap() {
118+
let res = left_hand + num * if Token::PlusSign == sign { 1 } else { -1 };
119+
stack.push(Token::Number(res));
120+
}
121+
}
122+
},
123+
}
124+
}
125+
if let Token::Number(num) = stack.pop().unwrap() {
126+
return num as i32
127+
}
128+
0
129+
}
130+
}
131+
132+
// submission codes end
133+
134+
#[cfg(test)]
135+
mod tests {
136+
use super::*;
137+
138+
#[test]
139+
fn test_224() {
140+
assert_eq!(Solution::calculate("(1+(4+5+2)-3)+(6+8)".to_owned()), 23);
141+
assert_eq!(Solution::calculate("1+1".to_owned()), 2);
142+
assert_eq!(Solution::calculate("0".to_owned()), 0);
143+
assert_eq!(Solution::calculate("2147483647".to_owned()), 2147483647);
144+
}
145+
}

0 commit comments

Comments
 (0)