From e5f906dae19b3f80d2e2adc0587740e08560ea0e Mon Sep 17 00:00:00 2001 From: dece Date: Sun, 7 Nov 2021 17:50:33 +0100 Subject: [PATCH] 2015 day 7 --- 2015/src/bin/day7.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 2015/src/bin/day7.rs diff --git a/2015/src/bin/day7.rs b/2015/src/bin/day7.rs new file mode 100644 index 0000000..80a272f --- /dev/null +++ b/2015/src/bin/day7.rs @@ -0,0 +1,67 @@ +use std::collections::HashMap; + +use aoc::input; + +#[derive(Debug)] +enum Op { + And(String, String), // left-hand can be an int + Or(String, String), + Not(String), + Lshift(String, u16), + Rshift(String, u16), + Value(String), // either int or wire +} + +fn main() { + let lines = input::read_lines(); + let mut wiring: HashMap = HashMap::new(); + for line in lines { + let mut parts = line.split(" -> "); + let op_text = parts.next().unwrap(); + let target = parts.next().unwrap(); + let op_parts: Vec<&str> = op_text.split_whitespace().collect(); + let op = match op_parts.len() { + 1 => { Op::Value(op_parts[0].to_string()) } + 2 => { Op::Not(op_parts[1].to_string()) } + 3 => { match op_parts[1] { + "AND" => { Op::And(op_parts[0].to_string(), op_parts[2].to_string()) } + "OR" => { Op::Or(op_parts[0].to_string(), op_parts[2].to_string()) } + "LSHIFT" => { Op::Lshift(op_parts[0].to_string(), op_parts[2].parse::().unwrap()) } + "RSHIFT" => { Op::Rshift(op_parts[0].to_string(), op_parts[2].parse::().unwrap()) } + _ => panic!() + } } + _ => panic!() + }; + wiring.insert(target.to_string(), op); + } + + // Part 1 + let mut cache: HashMap = HashMap::new(); + let part1 = solve(&wiring, "a", &mut cache); + println!("Wire a: {}", part1); + + // Part 2 + wiring.insert("b".to_string(), Op::Value(part1.to_string())); + let mut cache: HashMap = HashMap::new(); + println!("Wire a with b overridden: {}", solve(&wiring, "a", &mut cache)); +} + +fn solve(wiring: &HashMap, name: &str, cache: &mut HashMap) -> u16 { + if cache.contains_key(name) { + return *cache.get(name).unwrap() + } + let value = if let Ok(value) = name.parse::() { + return value + } else { + match wiring.get(name).unwrap() { + Op::And(lh, rh) => { solve(wiring, lh, cache) & solve(wiring, rh, cache) } + Op::Or(lh, rh) => { solve(wiring, lh, cache) | solve(wiring, rh, cache) } + Op::Not(op) => { !solve(wiring, op, cache) } + Op::Lshift(lh, rh) => { solve(wiring, lh, cache) << rh } + Op::Rshift(lh, rh) => { solve(wiring, lh, cache) >> rh } + Op::Value(v) => { solve(wiring, v, cache) } + } + }; + cache.insert(name.to_string(), value); + value +}