Day 19 part 2.

This commit is contained in:
2024-06-30 20:41:22 +02:00
parent 4b3b030f6e
commit 56c88ffec9
2 changed files with 73 additions and 18 deletions

View File

@@ -65,7 +65,6 @@ fn part2(input: &Field) -> usize {
current.into_iter().flatten().filter(|x| *x).count() current.into_iter().flatten().filter(|x| *x).count()
} }
fn count_neighbors(field: &Field, x: usize, y: usize) -> usize { fn count_neighbors(field: &Field, x: usize, y: usize) -> usize {
let mut result = 0; let mut result = 0;
if field[x - 1][y - 1] { if field[x - 1][y - 1] {

View File

@@ -1,4 +1,5 @@
use std::collections::HashSet; use std::collections::{HashSet, VecDeque};
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
type Transformation = (String, String); type Transformation = (String, String);
@@ -6,27 +7,35 @@ type Transformation = (String, String);
#[aoc_generator(day19)] #[aoc_generator(day19)]
fn parse(input: &str) -> (Vec<Transformation>, String) { fn parse(input: &str) -> (Vec<Transformation>, String) {
let (a, b) = input.split_once("\n\n").unwrap(); let (a, b) = input.split_once("\n\n").unwrap();
let t = a.lines().map(|line| { let t = a
.lines()
.map(|line| {
let (lhs, rhs) = line.split_once(" => ").unwrap(); let (lhs, rhs) = line.split_once(" => ").unwrap();
(lhs.to_string(), rhs.to_string()) (lhs.to_string(), rhs.to_string())
}).collect(); })
.collect();
(t, b.to_string()) (t, b.to_string())
} }
#[aoc(day19, part1)] #[aoc(day19, part1)]
fn part1((transformations, start): &(Vec<Transformation>, String)) -> usize { fn part1((transformations, start): &(Vec<Transformation>, String)) -> usize {
let all: HashSet<String> = transformations.iter() let all = possibilities(transformations, start);
all.len()
}
fn possibilities(transformations: &[Transformation], start: &str) -> HashSet<String> {
let all: HashSet<String> = transformations
.iter()
.flat_map(|(from, to)| { .flat_map(|(from, to)| {
let start_indexes = starts(start, from); let start_indexes = starts(start, from);
start_indexes.into_iter() start_indexes.into_iter().map(|si| {
.map(|si| { let mut s = start.to_string();
let mut s = start.clone();
s.replace_range(si..si + from.len(), to); s.replace_range(si..si + from.len(), to);
s s
}) })
}).collect(); })
.collect();
all.len() all
} }
fn starts(a: &str, pattern: &str) -> Vec<usize> { fn starts(a: &str, pattern: &str) -> Vec<usize> {
@@ -39,6 +48,29 @@ fn starts(a: &str, pattern: &str) -> Vec<usize> {
result result
} }
#[aoc(day19, part2)]
fn part2((transformations, target): &(Vec<Transformation>, 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)] #[cfg(test)]
mod test { mod test {
#[test] #[test]
@@ -50,4 +82,28 @@ O => HH
HOH"; HOH";
assert_eq!(super::part1(&super::parse(input)), 4); assert_eq!(super::part1(&super::parse(input)), 4);
} }
#[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);
}
} }