From 2759b7e1f63c8777a7d52bc4d0f5cec71142d53d Mon Sep 17 00:00:00 2001 From: Lars Martens Date: Sun, 7 Dec 2025 15:17:55 +0100 Subject: [PATCH] Solve 07 --- src/bin/07.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/bin/07.rs diff --git a/src/bin/07.rs b/src/bin/07.rs new file mode 100644 index 0000000..f93f8ee --- /dev/null +++ b/src/bin/07.rs @@ -0,0 +1,95 @@ +use aoc::*; +use cached::{proc_macro::cached, stores::UnboundCache}; +use std::collections::HashSet; + +const INPUT: &str = include_str!("../../input/07"); + +fn main() { + println!("Part 1: {}", part1(INPUT)); + println!("Part 2: {}", part2(INPUT)); +} + +#[test] +fn example() { + assert_example!(part1, "07-test", 21); + assert_example!(part2, "07-test", 40); +} + +fn part1(input: &str) -> usize { + let (start, splitters) = parse_input(input); + + let mut sum = 0; + let mut beams = HashSet::from([start]); + + for splitters in splitters { + let (count, new) = split_count(&splitters, beams); + beams = new; + sum += count; + } + + sum +} + +fn part2(input: &str) -> usize { + let (start, splitters) = parse_input(input); + timelines(start, 0, &splitters) +} + +fn split_count(splitters: &HashSet, beams: HashSet) -> (usize, HashSet) { + let mut result = HashSet::new(); + let mut count = 0; + + for beam in beams { + if splitters.contains(&beam) { + result.insert(beam + 1); + result.insert(beam - 1); + count += 1; + } else { + result.insert(beam); + } + } + + (count, result) +} + +#[cached( + type = "UnboundCache<(i32, usize), usize>", + create = "{ UnboundCache::new() }", + convert = r#"{ (beam, depth) }"# +)] +fn timelines(beam: i32, depth: usize, splitters: &[HashSet]) -> usize { + if depth >= splitters.len() { + return 1; + } + + let splitter = &splitters[depth]; + + if splitter.contains(&beam) { + timelines(beam - 1, depth + 1, splitters) + timelines(beam + 1, depth + 1, splitters) + } else { + timelines(beam, depth + 1, splitters) + } +} + +/// Returns (start, lines of splitter positions) +fn parse_input(input: &str) -> (i32, Vec>) { + let mut lines = input.lines(); + + let first_line = lines.next().unwrap(); + let start = first_line.chars().position(|c| c == 'S').unwrap() as i32; + + let splitters = lines + .map(parse_line) + .filter(|line| !line.is_empty()) + .collect(); + + (start, splitters) +} + +fn parse_line(line: &str) -> HashSet { + line.chars() + .enumerate() + .filter(|&(_, c)| c == '^') + .map(|(i, _)| i as i32) + .collect() +}