advent-of-code-2024/day24/part1.rs

67 lines
2 KiB
Rust
Raw Normal View History

2024-12-23 23:01:33 -07:00
use std::collections::HashMap;
use itertools::Itertools;
const INPUT: &str = include_str!("input.txt");
#[derive(Debug)]
struct Gate<'a> {
first: &'a str,
second: &'a str,
op: Operation
}
#[repr(u8)]
#[derive(Debug)]
enum Operation {
And,
Or,
Xor,
}
fn solve<'a>(state: &mut HashMap<&'a str, u64>, gates: &'a HashMap<&'a str, Gate>, output: &'a str) -> u64 {
state.get(output).map(|&t| t).unwrap_or_else(|| {
let gate = &gates[output];
let (first_res, second_res) = (solve(state, gates, gate.first), solve(state, gates, gate.second));
state.entry(gate.first).or_insert(first_res);
state.entry(gate.second).or_insert(second_res);
match gate.op {
Operation::And => first_res & second_res,
Operation::Or => first_res | second_res,
Operation::Xor => first_res ^ second_res
}
})
}
fn main() {
let (state, gates) = INPUT.split("\n\n").collect_tuple().unwrap();
let mut state = HashMap::<&str, u64>::from_iter(
state
.trim()
.lines()
.map(|l| l.split_once(": ").unwrap())
.map(|(wire, value)| (wire, if value == "0" { 0 } else { 1 }))
);
let gates = HashMap::<&str, Gate>::from_iter(
gates
.trim()
.lines()
.map(|l| l.split_once(" -> ").unwrap())
.map(|(inputs, output)| (inputs.split(' ').collect_tuple().unwrap(), output))
.map(|((first, op, second), output)| (output, Gate { first, second, op: match op {
"AND" => Operation::And,
"OR" => Operation::Or,
"XOR" => Operation::Xor,
_ => unreachable!()
}}))
);
let mut result = 0u64;
for (&output, z_value) in gates.keys().filter_map(|k| k.split_once('z').map(|(_, num)| (k, num.parse::<u64>().unwrap()))) {
result |= solve(&mut state, &gates, output) << z_value;
}
println!("{result}");
}