advent-of-code/2023/src/bin/day08.rs
2023-12-08 07:05:56 +01:00

95 lines
2.4 KiB
Rust

#![feature(test)]
extern crate test;
use std::collections::HashMap;
use aoc2023::{boilerplate, common::*};
const DAY: usize = 08;
type Parsed<'a> = (Vec<Direction>, HashMap<&'a str, (&'a str, &'a str)>);
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
enum Direction {
Left,
Right,
}
fn parse_input(raw: &str) -> Parsed {
let (directions, map) = raw.split_once("\n\n").unwrap();
let directions = directions
.bytes()
.map(|i| match i {
b'L' => Direction::Left,
b'R' => Direction::Right,
_ => unreachable!(),
})
.collect();
let map = map.lines().map(|l| (&l[0..=2], (&l[7..=9], &l[12..=14]))).collect();
(directions, map)
}
fn part1(parsed: &Parsed) -> usize {
steps_until(parsed, "AAA", "ZZZ")
}
fn steps_until((directions, map): &Parsed, start: &str, target: &str) -> usize {
let mut visited = HashMap::new();
directions
.iter()
.enumerate()
.cycle()
.enumerate()
.scan(start, |pos, (i, (j, dir))| {
let next = match dir {
Direction::Left => map.get(pos)?.0,
Direction::Right => map.get(pos)?.1,
};
if next.ends_with("Z") {
println!("Found ghost after {}", i + 1);
}
if pos == &next || next.ends_with(target) || visited.contains_key(&(next, j)) {
println!("Stopping at {pos} (next {next}) after {i} steps");
None
} else {
visited.insert((next, j), i);
*pos = next;
Some(next)
}
})
.count()
+ 1
}
fn part2(parsed: &Parsed) -> usize {
for (start, _) in parsed.1.iter().filter(|(start, _)| start.ends_with("A")) {
println!("{}", steps_until(parsed, start, start));
}
unimplemented!()
}
#[cfg(test)]
const TEST_INPUT_P2: &str = "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)";
boilerplate! {
TEST_INPUT == "LLR
AAA = (BBB, BBB)
BBB = (AAA, ZZZ)
ZZZ = (ZZZ, ZZZ)",
tests: {
part1: { TEST_INPUT => 6 },
part2: { TEST_INPUT_P2 => 6 },
},
bench1 == 12083,
bench2 == 0, // 183359899573 too low
bench_parse: |(v, m): &Parsed| { assert_eq!(m["AAA"], ("MJJ", "QBJ")); (v.len(), v[0]) } => (281, Direction::Left),
}