From 88d06b99ecfffab42416eac0eea1b2882c2e60ae Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Fri, 8 Dec 2023 11:55:22 +0100 Subject: [PATCH] day(08): add solution Signed-off-by: Matej Focko --- samples/day08_1.txt | 5 ++ samples/day08_2.txt | 10 ++++ src/bin/day08.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 samples/day08_1.txt create mode 100644 samples/day08_2.txt create mode 100644 src/bin/day08.rs diff --git a/samples/day08_1.txt b/samples/day08_1.txt new file mode 100644 index 0000000..34ffa8a --- /dev/null +++ b/samples/day08_1.txt @@ -0,0 +1,5 @@ +LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ) \ No newline at end of file diff --git a/samples/day08_2.txt b/samples/day08_2.txt new file mode 100644 index 0000000..5b3fa58 --- /dev/null +++ b/samples/day08_2.txt @@ -0,0 +1,10 @@ +LR + +11A = (11B, XXX) +11B = (XXX, 11Z) +11Z = (11B, XXX) +22A = (22B, XXX) +22B = (22C, 22C) +22C = (22Z, 22Z) +22Z = (22B, 22B) +XXX = (XXX, XXX) diff --git a/src/bin/day08.rs b/src/bin/day08.rs new file mode 100644 index 0000000..7f485ee --- /dev/null +++ b/src/bin/day08.rs @@ -0,0 +1,129 @@ +use std::collections::HashMap; + +use aoc_2023::*; + +type Output1 = u64; +type Output2 = Output1; + +#[derive(Debug, Clone, Copy)] +enum Direction { + Left, + Right, +} + +impl Direction { + fn get<'a>(&self, options: &'a (String, String)) -> &'a str { + match self { + Direction::Left => &options.0, + Direction::Right => &options.1, + } + } +} + +fn gcd(mut x: u64, mut y: u64) -> u64 { + while y != 0 { + (x, y) = (y, x % y); + } + + x +} + +fn lcm(x: u64, y: u64) -> u64 { + x / gcd(x, y) * y +} + +struct Day08 { + instructions: Vec, + graph: HashMap, +} +impl Solution for Day08 { + fn new>(pathname: P) -> Self { + let lines: Vec = file_to_lines(pathname); + + let mut graph = HashMap::new(); + for line in lines.iter().skip(2) { + let mut parts = line.split(" = "); + + let u = parts.next().unwrap(); + let right = parts.next().unwrap(); + + let next = right + .strip_prefix('(') + .unwrap() + .strip_suffix(')') + .unwrap() + .split(", ") + .collect_vec(); + + graph.insert(u.to_string(), (next[0].to_string(), next[1].to_string())); + } + + Self { + instructions: lines[0] + .chars() + .map(|i| match i { + 'L' => Direction::Left, + 'R' => Direction::Right, + _ => unreachable!("unknown direction"), + }) + .collect_vec(), + graph, + } + } + + fn part_1(&mut self) -> Output1 { + let mut instructions = self.instructions.iter().cycle(); + let mut counter = 0; + + let mut vertex = "AAA"; + while vertex != "ZZZ" { + let instruction = instructions.next().unwrap(); + vertex = instruction.get(&self.graph[vertex]); + + counter += 1; + } + + counter + } + + fn part_2(&mut self) -> Output2 { + let mut instructions = self.instructions.iter().cycle(); + + let mut vertices: Vec<&str> = self + .graph + .keys() + .filter_map(|u| { + if u.ends_with('A') { + Some(u.as_str()) + } else { + None + } + }) + .collect(); + let mut counters = vec![0; vertices.len()]; + + while vertices.iter().any(|v| !v.ends_with('Z')) { + let instruction = instructions.next().unwrap(); + + for u in 0..vertices.len() { + if vertices[u].ends_with('Z') { + continue; + } + + vertices[u] = instruction.get(&self.graph[vertices[u]]); + counters[u] += 1; + } + } + + debug!("Instruction length: {}", self.instructions.len()); + debug!("Counters: {:?}", &counters); + + counters.into_iter().fold(1, lcm) + } +} + +fn main() -> Result<()> { + Day08::main() +} + +test_sample!(day_08, Day08, 6, 6);