From 56c88ffec9ddfeceb4e5064f9ae3f208b778775c Mon Sep 17 00:00:00 2001 From: Johannes Date: Sun, 30 Jun 2024 20:41:22 +0200 Subject: [PATCH] Day 19 part 2. --- src/day18.rs | 1 - src/day19.rs | 90 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/day18.rs b/src/day18.rs index bacfda1..cf91cd4 100644 --- a/src/day18.rs +++ b/src/day18.rs @@ -65,7 +65,6 @@ fn part2(input: &Field) -> usize { current.into_iter().flatten().filter(|x| *x).count() } - fn count_neighbors(field: &Field, x: usize, y: usize) -> usize { let mut result = 0; if field[x - 1][y - 1] { diff --git a/src/day19.rs b/src/day19.rs index 855b637..59d5cc3 100644 --- a/src/day19.rs +++ b/src/day19.rs @@ -1,4 +1,5 @@ -use std::collections::HashSet; +use std::collections::{HashSet, VecDeque}; + use aoc_runner_derive::{aoc, aoc_generator}; type Transformation = (String, String); @@ -6,27 +7,35 @@ type Transformation = (String, String); #[aoc_generator(day19)] fn parse(input: &str) -> (Vec, String) { let (a, b) = input.split_once("\n\n").unwrap(); - let t = a.lines().map(|line| { - let (lhs, rhs) = line.split_once(" => ").unwrap(); - (lhs.to_string(), rhs.to_string()) - }).collect(); + let t = a + .lines() + .map(|line| { + let (lhs, rhs) = line.split_once(" => ").unwrap(); + (lhs.to_string(), rhs.to_string()) + }) + .collect(); (t, b.to_string()) } #[aoc(day19, part1)] fn part1((transformations, start): &(Vec, String)) -> usize { - let all: HashSet = transformations.iter() + let all = possibilities(transformations, start); + all.len() +} + +fn possibilities(transformations: &[Transformation], start: &str) -> HashSet { + let all: HashSet = transformations + .iter() .flat_map(|(from, to)| { let start_indexes = starts(start, from); - start_indexes.into_iter() - .map(|si| { - let mut s = start.clone(); - s.replace_range(si..si+from.len(), to); - s - }) - }).collect(); - - all.len() + start_indexes.into_iter().map(|si| { + let mut s = start.to_string(); + s.replace_range(si..si + from.len(), to); + s + }) + }) + .collect(); + all } fn starts(a: &str, pattern: &str) -> Vec { @@ -39,6 +48,29 @@ fn starts(a: &str, pattern: &str) -> Vec { result } +#[aoc(day19, part2)] +fn part2((transformations, target): &(Vec, String)) -> usize { + search("e", transformations, target) +} + +fn search(base: &str, transformations: &[Transformation], target: &str) -> usize { + let mut seen = HashSet::new(); + seen.insert(base.to_string()); + let mut queue = VecDeque::new(); + queue.push_back((base.to_string(), 0)); + while let Some((from, depth)) = queue.pop_front() { + for possibility in possibilities(transformations, &from) { + if possibility == target { + return depth + 1; + } + if seen.insert(possibility.clone()) { + queue.push_back((possibility, depth + 1)); + } + } + } + unreachable!("No solution was found"); +} + #[cfg(test)] mod test { #[test] @@ -48,6 +80,30 @@ H => OH O => HH HOH"; - assert_eq!(super::part1(& super::parse(input)), 4); + assert_eq!(super::part1(&super::parse(input)), 4); } -} \ No newline at end of file + + #[test] + fn part2a() { + let input = "e => H +e => O +H => HO +H => OH +O => HH + +HOH"; + assert_eq!(super::part2(&super::parse(input)), 3); + } + + #[test] + fn part2b() { + let input = "e => H +e => O +H => HO +H => OH +O => HH + +HOHOHO"; + assert_eq!(super::part2(&super::parse(input)), 6); + } +}