day(08): add solution
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
1275d5b738
commit
88d06b99ec
3 changed files with 144 additions and 0 deletions
5
samples/day08_1.txt
Normal file
5
samples/day08_1.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
10
samples/day08_2.txt
Normal file
10
samples/day08_2.txt
Normal file
|
@ -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)
|
129
src/bin/day08.rs
Normal file
129
src/bin/day08.rs
Normal file
|
@ -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<Direction>,
|
||||
graph: HashMap<String, (String, String)>,
|
||||
}
|
||||
impl Solution<Output1, Output2> for Day08 {
|
||||
fn new<P: AsRef<Path>>(pathname: P) -> Self {
|
||||
let lines: Vec<String> = 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);
|
Loading…
Reference in a new issue