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

@@ -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<Transformation>, 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<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)| {
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<usize> {
@@ -39,6 +48,29 @@ fn starts(a: &str, pattern: &str) -> Vec<usize> {
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)]
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);
}
}
#[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);
}
}