Skip to content

Commit b1b0827

Browse files
committed
Add day 18
1 parent b1c5346 commit b1b0827

File tree

1 file changed

+39
-34
lines changed

1 file changed

+39
-34
lines changed

2020/18/18.rs

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,50 @@
1-
use std::io::stdin;
1+
use std::{collections::HashMap, io::stdin};
22

3-
fn eval(line: &str) -> i64 {
4-
let mut stack = vec![0, -1];
5-
eprintln!("line = {:?}", line);
6-
for c in line.chars() {
7-
let mut eval = false;
8-
eprintln!("c = {:?}, stack = {:?}", c, stack);
3+
use itertools::Itertools;
4+
5+
fn eval(line: &str, plus_precedence: i32) -> i64 {
6+
let mut nums = Vec::new();
7+
let mut operators = Vec::new();
8+
let precedence = HashMap::from([('(', 10), ('+', plus_precedence), ('*', 1)]);
9+
// eprintln!("line = {:?}", line);
10+
for c in line.chars().chain(")".chars()) {
11+
// eprintln!("c = {:?}, nums = {:?}, ops = {:?}", c, nums, operators);
912
match c {
10-
'0'..='9' => {
11-
stack.push(c.to_digit(10).unwrap() as i64);
12-
eval = true;
13-
}
14-
'(' => {
15-
stack.push(0);
16-
stack.push(-1);
17-
}
13+
'0'..='9' => nums.push(c.to_digit(10).unwrap() as i64),
14+
'(' => operators.push(c),
1815
')' => {
19-
eval = true;
16+
while !operators.is_empty() {
17+
let op = operators.pop().unwrap();
18+
if op == '(' {
19+
break;
20+
}
21+
let func = if op == '*' { |(a, b)| a * b } else { |(a, b)| a + b };
22+
let value = nums.pop().zip(nums.pop()).map(func).unwrap();
23+
nums.push(value);
24+
}
25+
}
26+
'+' | '*' => {
27+
while !operators.is_empty() {
28+
// eprintln!("\tc = {:?}, nums = {:?}, ops = {:?}", c, nums, operators);
29+
let op = operators.last().unwrap();
30+
if *op == '(' || precedence.get(op).unwrap() < precedence.get(&c).unwrap() {
31+
break;
32+
}
33+
let func = if *op == '*' { |(a, b)| a * b } else { |(a, b)| a + b };
34+
let value = nums.pop().zip(nums.pop()).map(func).unwrap();
35+
nums.push(value);
36+
operators.pop();
37+
}
38+
operators.push(c);
2039
},
21-
'+' => stack.push(-1),
22-
'*' => stack.push(-2),
2340
_ => (),
2441
}
25-
if eval {
26-
let digit1 = stack.pop().unwrap();
27-
let op = stack.pop().unwrap();
28-
let digit2 = stack.pop().unwrap();
29-
match op {
30-
-1 => stack.push(digit2 + digit1),
31-
_ => stack.push(digit2 * digit1),
32-
}
33-
}
3442
}
35-
*stack.get(0).unwrap()
43+
*nums.get(0).unwrap()
3644
}
3745

3846
fn main() {
39-
let out = stdin()
40-
.lines()
41-
.filter_map(Result::ok)
42-
.map(|line| eval(&line))
43-
.sum::<i64>();
44-
println!("{:?}", out)
47+
let lines = stdin() .lines().filter_map(Result::ok).collect_vec();
48+
println!("{:?}", lines.iter().map(|l| eval(&l, 1)).sum::<i64>());
49+
println!("{:?}", lines.iter().map(|l| eval(&l, 2)).sum::<i64>());
4550
}

0 commit comments

Comments
 (0)