A fun one! Day 18 done.
This commit is contained in:
106
src/bin/homework.rs
Normal file
106
src/bin/homework.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
use advent2020::errors::TopLevelError;
|
||||
use advent2020::math::Math;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
|
||||
#[test]
|
||||
fn neutral_examples() {
|
||||
assert_eq!(
|
||||
71,
|
||||
Math::new_neutral("1 + 2 * 3 + 4 * 5 + 6")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
51,
|
||||
Math::new_neutral("1 + (2 * 3) + (4 * (5 + 6))")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(26, Math::new_neutral("2 * 3 + (4 * 5)").unwrap().compute());
|
||||
assert_eq!(
|
||||
437,
|
||||
Math::new_neutral("5 + (8 * 3 + 9 + 3 * 4 * 3)")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
12240,
|
||||
Math::new_neutral("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
13632,
|
||||
Math::new_neutral("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_first_examples() {
|
||||
assert_eq!(
|
||||
231,
|
||||
Math::new_add_first("1 + 2 * 3 + 4 * 5 + 6")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
51,
|
||||
Math::new_add_first("1 + (2 * 3) + (4 * (5 + 6))")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
46,
|
||||
Math::new_add_first("2 * 3 + (4 * 5)").unwrap().compute()
|
||||
);
|
||||
assert_eq!(
|
||||
1445,
|
||||
Math::new_add_first("5 + (8 * 3 + 9 + 3 * 4 * 3)")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
669060,
|
||||
Math::new_add_first("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
assert_eq!(
|
||||
23340,
|
||||
Math::new_add_first("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2")
|
||||
.unwrap()
|
||||
.compute()
|
||||
);
|
||||
}
|
||||
|
||||
fn main() -> Result<(), TopLevelError> {
|
||||
let filename = env::args().nth(1).expect("No file argument given.");
|
||||
let contents = fs::read_to_string(filename)?;
|
||||
let mut sum_neutral = 0;
|
||||
let mut sum_add_first = 0;
|
||||
|
||||
for line in contents.lines() {
|
||||
match Math::new_neutral(line) {
|
||||
Ok(expr) => {
|
||||
println!("{} ==> {}", line, expr.compute());
|
||||
sum_neutral += expr.compute();
|
||||
}
|
||||
Err(e) => println!("PARSE ERROR: {}", e),
|
||||
}
|
||||
match Math::new_add_first(line) {
|
||||
Ok(expr) => {
|
||||
println!("{} ==> {}", line, expr.compute());
|
||||
sum_add_first += expr.compute();
|
||||
}
|
||||
Err(e) => println!("PARSE ERROR: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
println!("Total (neutral ordering): {}", sum_neutral);
|
||||
println!("Total (add-first ordering): {}", sum_add_first);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
extern crate lalrpop_util;
|
||||
|
||||
pub mod errors;
|
||||
pub mod map;
|
||||
pub mod math;
|
||||
|
||||
16
src/math.rs
Normal file
16
src/math.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
mod ast;
|
||||
|
||||
lalrpop_util::lalrpop_mod!(parse, "/math/parse.rs");
|
||||
|
||||
pub use crate::math::ast::Math;
|
||||
use crate::math::parse::{ExprMulParser, ExprParser};
|
||||
|
||||
impl Math {
|
||||
pub fn new_neutral(s: &str) -> Result<Math, String> {
|
||||
ExprParser::new().parse(s).map_err(|x| format!("{}", x))
|
||||
}
|
||||
|
||||
pub fn new_add_first(s: &str) -> Result<Math, String> {
|
||||
ExprMulParser::new().parse(s).map_err(|x| format!("{}", x))
|
||||
}
|
||||
}
|
||||
15
src/math/ast.rs
Normal file
15
src/math/ast.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
pub enum Math {
|
||||
Constant(usize),
|
||||
Multiply(Box<Math>, Box<Math>),
|
||||
Add(Box<Math>, Box<Math>),
|
||||
}
|
||||
|
||||
impl Math {
|
||||
pub fn compute(&self) -> usize {
|
||||
match self {
|
||||
Math::Constant(x) => *x,
|
||||
Math::Multiply(a, b) => a.compute() * b.compute(),
|
||||
Math::Add(a, b) => a.compute() + b.compute(),
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/math/parse.lalrpop
Normal file
32
src/math/parse.lalrpop
Normal file
@@ -0,0 +1,32 @@
|
||||
use crate::math::ast::Math;
|
||||
use std::str::FromStr;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Expr: Math = {
|
||||
<e1: Expr> "+" <e2: Term> => Math::Add(Box::new(e1), Box::new(e2)),
|
||||
<e1: Expr> "*" <e2: Term> => Math::Multiply(Box::new(e1), Box::new(e2)),
|
||||
<e: Term> => e,
|
||||
}
|
||||
|
||||
Term: Math = {
|
||||
<n:Num> => Math::Constant(n),
|
||||
"(" <t:Expr> ")" => t,
|
||||
};
|
||||
|
||||
pub ExprMul: Math = {
|
||||
<e1: ExprMul> "*" <e2: ExprAdd> => Math::Multiply(Box::new(e1), Box::new(e2)),
|
||||
<e: ExprAdd> => e,
|
||||
}
|
||||
|
||||
ExprAdd: Math = {
|
||||
<e1: ExprAdd> "+" <e2: ExprConst> => Math::Add(Box::new(e1), Box::new(e2)),
|
||||
<e: ExprConst> => e,
|
||||
}
|
||||
|
||||
ExprConst: Math = {
|
||||
<n:Num> => Math::Constant(n),
|
||||
"(" <t:ExprMul> ")" => t,
|
||||
}
|
||||
|
||||
Num: usize = <s:r"[0-9]+"> => usize::from_str(s).unwrap();
|
||||
Reference in New Issue
Block a user