This commit is contained in:
2022-12-22 01:01:43 +01:00
parent ff2a983332
commit 19a0956873
7 changed files with 2561 additions and 0 deletions

16
Cargo.lock generated
View File

@@ -12,6 +12,7 @@ dependencies = [
"num",
"petgraph",
"rayon",
"xxcalc",
]
[[package]]
@@ -300,6 +301,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "smallvec"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
[[package]]
name = "tap"
version = "1.0.1"
@@ -314,3 +321,12 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]]
name = "xxcalc"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2725420f62b8c706cd7f710b45bc30a702de16b092114b84bd0bb6d9cccdbc"
dependencies = [
"smallvec",
]

View File

@@ -12,3 +12,4 @@ nom = "7.1.1"
num = "0.4.0"
petgraph = "0.6.2"
rayon = "1.6.1"
xxcalc = "0.2.1"

2399
inputs/day21.txt Normal file

File diff suppressed because it is too large Load Diff

8
src/bin/day21_1.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::fs;
use aoc2022::day21::process_part_1;
fn main() {
let file = fs::read_to_string("./inputs/day21.txt").unwrap();
println!("{}", process_part_1(&file));
}

8
src/bin/day21_2.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::fs;
use aoc2022::day21::process_part_2;
fn main() {
let file = fs::read_to_string("./inputs/day21.txt").unwrap();
println!("{}", process_part_2(&file));
}

128
src/day21.rs Normal file
View File

@@ -0,0 +1,128 @@
use std::collections::HashMap;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete;
use nom::character::complete::{alpha1, newline, one_of, space1};
use nom::combinator::map;
use nom::multi::separated_list1;
use nom::sequence::separated_pair;
use nom::IResult;
use xxcalc::calculator::Calculator;
pub fn process_part_1(input: &str) -> i64 {
let (_, monkeys) = parse_input(input).unwrap();
monkeys["root"].calc(&monkeys)
}
pub fn process_part_2(input: &str) -> i64 {
let (_, monkeys) = parse_input(input).unwrap();
let expr = match monkeys["root"] {
Monkey::Add(a, b) | Monkey::Sub(a, b) | Monkey::Mul(a, b) | Monkey::Div(a, b) => {
format!("{}={}", build_expr(&monkeys, a), build_expr(&monkeys, b))
}
_ => unreachable!(),
};
// Lazy man, i am
xxcalc::linear_solver::LinearSolver
.process(&expr)
.unwrap()
.as_f64()
.unwrap()
.floor() as i64
}
fn build_expr(monkeys: &HashMap<&str, Monkey>, name: &str) -> String {
if name == "humn" {
return "x".to_owned();
}
match monkeys[name] {
Monkey::Number(x) => format!("{x}"),
Monkey::Add(a, b) => format!("({}+{})", build_expr(monkeys, a), build_expr(monkeys, b)),
Monkey::Sub(a, b) => format!("({}-{})", build_expr(monkeys, a), build_expr(monkeys, b)),
Monkey::Mul(a, b) => format!("({}*{})", build_expr(monkeys, a), build_expr(monkeys, b)),
Monkey::Div(a, b) => format!("({}/{})", build_expr(monkeys, a), build_expr(monkeys, b)),
}
}
#[derive(Debug)]
enum Monkey<'a> {
Number(i64),
Add(&'a str, &'a str),
Sub(&'a str, &'a str),
Mul(&'a str, &'a str),
Div(&'a str, &'a str),
}
impl<'a> Monkey<'a> {
fn calc(&self, monkeys: &HashMap<&str, Monkey>) -> i64 {
match *self {
Monkey::Number(i) => i,
Monkey::Add(a, b) => monkeys[a].calc(monkeys) + monkeys[b].calc(monkeys),
Monkey::Sub(a, b) => monkeys[a].calc(monkeys) - monkeys[b].calc(monkeys),
Monkey::Mul(a, b) => monkeys[a].calc(monkeys) * monkeys[b].calc(monkeys),
Monkey::Div(a, b) => monkeys[a].calc(monkeys) / monkeys[b].calc(monkeys),
}
}
}
fn parse_operation_monkey(input: &str) -> IResult<&str, Monkey> {
let (input, lhs) = alpha1(input)?;
let (input, _) = space1(input)?;
let (input, op) = one_of("+-*/")(input)?;
let (input, _) = space1(input)?;
let (input, rhs) = alpha1(input)?;
Ok((
input,
match op {
'+' => Monkey::Add(lhs, rhs),
'-' => Monkey::Sub(lhs, rhs),
'*' => Monkey::Mul(lhs, rhs),
'/' => Monkey::Div(lhs, rhs),
_ => unreachable!(),
},
))
}
fn parse_monkey(input: &str) -> IResult<&str, Monkey> {
alt((map(complete::i64, Monkey::Number), parse_operation_monkey))(input)
}
fn parse_input(input: &str) -> IResult<&str, HashMap<&str, Monkey>> {
let (input, monkeys) =
separated_list1(newline, separated_pair(alpha1, tag(": "), parse_monkey))(input)?;
Ok((input, HashMap::from_iter(monkeys.into_iter())))
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT: &str = "root: pppw + sjmn
dbpl: 5
cczh: sllz + lgvd
zczc: 2
ptdq: humn - dvpt
dvpt: 3
lfqf: 4
humn: 5
ljgn: 2
sjmn: drzm * dbpl
sllz: 4
pppw: cczh / lfqf
lgvd: ljgn * ptdq
drzm: hmdt - zczc
hmdt: 32";
#[test]
fn day1() {
assert_eq!(process_part_1(INPUT), 152);
}
#[test]
fn day2() {
assert_eq!(process_part_2(INPUT), 301);
}
}

View File

@@ -21,3 +21,4 @@ pub mod day17;
pub mod day18;
pub mod day19;
pub mod day20;
pub mod day21;