Added day 18 part2
This commit is contained in:
parent
71dc5aef59
commit
f1812b5ee0
243
src/bin/day18.rs
243
src/bin/day18.rs
|
@ -3,23 +3,21 @@ use std::fs::File;
|
|||
use std::io::{self, BufRead};
|
||||
use std::vec::Vec;
|
||||
|
||||
fn extract_paren_expression(input: &str) -> String {
|
||||
let mut res: String = "".to_string();
|
||||
let mut open_count = 1;
|
||||
fn read_paren_expression(input: &str) -> (&str, &str) {
|
||||
let mut open_count = 0;
|
||||
let mut close_count = 0;
|
||||
|
||||
for c in input[1..].chars() {
|
||||
match c {
|
||||
for i in 0..input.len() {
|
||||
match input.chars().nth(i).unwrap() {
|
||||
'(' => open_count += 1,
|
||||
')' => {
|
||||
close_count += 1;
|
||||
if open_count == close_count {
|
||||
return res;
|
||||
return (&input[1..i], &input[i + 1..]);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
res += &c.to_string();
|
||||
}
|
||||
|
||||
panic!(
|
||||
|
@ -28,40 +26,114 @@ fn extract_paren_expression(input: &str) -> String {
|
|||
);
|
||||
}
|
||||
|
||||
fn extract_number(input: &str) -> String {
|
||||
input.chars().take_while(|c| c.is_ascii_digit()).collect()
|
||||
fn read_number(input: &str) -> (&str, &str) {
|
||||
for i in 0..input.len() {
|
||||
if !input.chars().nth(i).unwrap().is_ascii_digit() {
|
||||
return (&input[0..i], &input[i..]);
|
||||
}
|
||||
}
|
||||
return (input, "");
|
||||
}
|
||||
|
||||
fn eval_expression(input: &str) -> u64 {
|
||||
let mut clean: String = input.chars().filter(|c| *c != ' ').collect();
|
||||
let mut res = 0;
|
||||
let mut op = '^';
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
enum Expression {
|
||||
Num(u64),
|
||||
OpAdd,
|
||||
OpMul,
|
||||
SubExpr(Vec<Expression>),
|
||||
}
|
||||
|
||||
while clean != "" {
|
||||
let c = clean.chars().nth(0).unwrap();
|
||||
fn parse_expression(input: &str) -> Vec<Expression> {
|
||||
let mut expr = Vec::new();
|
||||
let mut rest = input;
|
||||
|
||||
while rest != "" {
|
||||
let c = rest.chars().nth(0).unwrap();
|
||||
if c.is_ascii_digit() {
|
||||
let substr = extract_number(&clean);
|
||||
clean = clean[substr.len()..].to_string();
|
||||
let num: u64 = substr.parse().unwrap();
|
||||
match op {
|
||||
'^' => res = num,
|
||||
'+' => res += num,
|
||||
'*' => res *= num,
|
||||
_ => panic!("Unsupported Op: {}", op),
|
||||
}
|
||||
} else if c == '+' || c == '*' {
|
||||
op = c;
|
||||
clean = clean[1..].to_string();
|
||||
let (substr, tail) = read_number(rest);
|
||||
expr.push(Expression::Num(substr.parse().unwrap()));
|
||||
rest = tail;
|
||||
} else if c == '(' {
|
||||
let substr = extract_paren_expression(&clean);
|
||||
clean = clean[substr.len() + 2..].to_string();
|
||||
let num = eval_expression(&substr);
|
||||
match op {
|
||||
'^' => res = num,
|
||||
'+' => res += num,
|
||||
'*' => res *= num,
|
||||
_ => panic!("Unsupported Op: {}", op),
|
||||
let (substr, tail) = read_paren_expression(rest);
|
||||
expr.push(Expression::SubExpr(parse_expression(substr)));
|
||||
rest = tail;
|
||||
} else if c == '+' {
|
||||
expr.push(Expression::OpAdd);
|
||||
rest = &rest[1..];
|
||||
} else if c == '*' {
|
||||
expr.push(Expression::OpMul);
|
||||
rest = &rest[1..];
|
||||
} else {
|
||||
rest = &rest[1..];
|
||||
}
|
||||
}
|
||||
|
||||
expr
|
||||
}
|
||||
|
||||
fn eval_part1(expr: &Vec<Expression>) -> u64 {
|
||||
let subexpr_eval = expr.iter().map(|e| match e {
|
||||
Expression::SubExpr(subexpr) => Expression::Num(eval_part1(subexpr)),
|
||||
_ => e.clone(),
|
||||
});
|
||||
|
||||
let mut res = 0;
|
||||
let mut op = Expression::OpAdd;
|
||||
for e in subexpr_eval {
|
||||
match e {
|
||||
Expression::Num(n) => match op {
|
||||
Expression::OpAdd => res += n,
|
||||
Expression::OpMul => res *= n,
|
||||
_ => panic!("Malformed expression. Not an op."),
|
||||
},
|
||||
Expression::OpAdd => op = Expression::OpAdd,
|
||||
Expression::OpMul => op = Expression::OpMul,
|
||||
_ => panic!("Malformed expression."),
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn eval_part2(expr: &Vec<Expression>) -> u64 {
|
||||
let subexpr_eval: Vec<Expression> = expr
|
||||
.iter()
|
||||
.map(|e| match e {
|
||||
Expression::SubExpr(subexpr) => Expression::Num(eval_part2(subexpr)),
|
||||
_ => e.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut mul_eval: Vec<Expression> = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < subexpr_eval.len() {
|
||||
match subexpr_eval[i] {
|
||||
Expression::OpAdd => {
|
||||
if let Expression::Num(n1) = mul_eval.pop().unwrap() {
|
||||
if let Expression::Num(n2) = subexpr_eval[i + 1] {
|
||||
mul_eval.push(Expression::Num(n1 + n2));
|
||||
i += 2;
|
||||
} else {
|
||||
panic!("Malformed expression: Expected Number")
|
||||
}
|
||||
} else {
|
||||
panic!("Malformed expression: Expected Number")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
mul_eval.push(subexpr_eval[i].clone());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut res = 1;
|
||||
|
||||
for e in mul_eval {
|
||||
match e {
|
||||
Expression::Num(n) => res *= n,
|
||||
Expression::OpMul => {}
|
||||
_ => panic!("Malformed expression."),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,8 +144,15 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||
let file = File::open("inputs/day18.txt")?;
|
||||
let lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
||||
|
||||
let res = lines.map(|l| eval_expression(&l)).fold(0, |x, y| x + y);
|
||||
println!("Answer: {}", res);
|
||||
let exprs: Vec<Vec<Expression>> = lines.map(|l| parse_expression(&l)).collect();
|
||||
|
||||
let result1 = exprs.iter().map(|e| eval_part1(e)).fold(0, |x, y| x + y);
|
||||
|
||||
println!("Answer Part 1: {}", result1);
|
||||
|
||||
let result2 = exprs.iter().map(|e| eval_part2(e)).fold(0, |x, y| x + y);
|
||||
|
||||
println!("Answer Part 2: {}", result2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -83,31 +162,97 @@ mod tests {
|
|||
use crate::*;
|
||||
|
||||
#[test]
|
||||
fn test_extractor() {
|
||||
fn test_paren_expression() {
|
||||
assert_eq!(
|
||||
extract_paren_expression("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"),
|
||||
"(2 + 4 * 9) * (6 + 9 * 8 + 6) + 6"
|
||||
read_paren_expression("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"),
|
||||
("(2 + 4 * 9) * (6 + 9 * 8 + 6) + 6", " + 2 + 4 * 2")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basics() {
|
||||
assert_eq!(eval_expression("23"), 23);
|
||||
assert_eq!(eval_expression("2 + 3 * 4"), 20);
|
||||
assert_eq!(eval_expression("2 + (3 * 4)"), 14);
|
||||
fn test_number() {
|
||||
assert_eq!(read_number("243 + 3"), ("243", " + 3"),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problems() {
|
||||
assert_eq!(eval_expression("2 * 3 + (4 * 5)"), 26);
|
||||
assert_eq!(eval_expression("5 + (8 * 3 + 9 + 3 * 4 * 3)"), 437);
|
||||
fn test_parse() {
|
||||
assert_eq!(parse_expression("23"), vec![Expression::Num(23)]);
|
||||
assert_eq!(
|
||||
eval_expression("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"),
|
||||
parse_expression("2 + 3 * 4"),
|
||||
vec![
|
||||
Expression::Num(2),
|
||||
Expression::OpAdd,
|
||||
Expression::Num(3),
|
||||
Expression::OpMul,
|
||||
Expression::Num(4)
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_expression("2 + (3 * 4)"),
|
||||
vec![
|
||||
Expression::Num(2),
|
||||
Expression::OpAdd,
|
||||
Expression::SubExpr(vec![
|
||||
Expression::Num(3),
|
||||
Expression::OpMul,
|
||||
Expression::Num(4)
|
||||
])
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basics1() {
|
||||
assert_eq!(eval_part1(&parse_expression("23")), 23);
|
||||
assert_eq!(eval_part1(&parse_expression("2 + 3 * 4")), 20);
|
||||
assert_eq!(eval_part1(&parse_expression("2 + (3 * 4)")), 14);
|
||||
}
|
||||
|
||||
fn test_basics2() {
|
||||
assert_eq!(eval_part2(&parse_expression("23")), 23);
|
||||
assert_eq!(eval_part2(&parse_expression("2 + 3 * 2 * 3 + 2")), 50);
|
||||
assert_eq!(eval_part2(&parse_expression("2 + (3 * 4)")), 14);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problems1() {
|
||||
assert_eq!(eval_part1(&parse_expression("2 * 3 + (4 * 5)")), 26);
|
||||
assert_eq!(
|
||||
eval_part1(&parse_expression("5 + (8 * 3 + 9 + 3 * 4 * 3)")),
|
||||
437
|
||||
);
|
||||
assert_eq!(
|
||||
eval_part1(&parse_expression(
|
||||
"5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"
|
||||
)),
|
||||
12240
|
||||
);
|
||||
assert_eq!(
|
||||
eval_expression("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"),
|
||||
eval_part1(&parse_expression(
|
||||
"((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"
|
||||
)),
|
||||
13632
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_problems2() {
|
||||
assert_eq!(eval_part2(&parse_expression("2 * 3 + (4 * 5)")), 46);
|
||||
assert_eq!(
|
||||
eval_part2(&parse_expression("5 + (8 * 3 + 9 + 3 * 4 * 3)")),
|
||||
1445
|
||||
);
|
||||
assert_eq!(
|
||||
eval_part2(&parse_expression(
|
||||
"5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"
|
||||
)),
|
||||
669060
|
||||
);
|
||||
assert_eq!(
|
||||
eval_part2(&parse_expression(
|
||||
"((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"
|
||||
)),
|
||||
23340
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue