Day 19
This commit is contained in:
parent
cd4268a9ce
commit
10245f3faa
1 changed files with 141 additions and 0 deletions
141
src/bin/day19.rs
Normal file
141
src/bin/day19.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
use core::str;
|
||||||
|
use std::{collections::HashMap, time::Instant};
|
||||||
|
|
||||||
|
use aoc_2024::{load, print_res};
|
||||||
|
use bstr::BString;
|
||||||
|
use color_eyre::eyre::{bail, OptionExt};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Color {
|
||||||
|
White,
|
||||||
|
Blue,
|
||||||
|
Black,
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Color {
|
||||||
|
fn from_b(b: u8) -> color_eyre::Result<Self> {
|
||||||
|
Ok(match b {
|
||||||
|
b'w' => Color::White,
|
||||||
|
b'u' => Color::Blue,
|
||||||
|
b'b' => Color::Black,
|
||||||
|
b'r' => Color::Red,
|
||||||
|
b'g' => Color::Green,
|
||||||
|
_ => bail!("Invalid color: {}", b as char),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Parsed = (Vec<Vec<Color>>, Vec<Vec<Color>>);
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn parsing(input: &BString) -> color_eyre::Result<Parsed> {
|
||||||
|
let (towels, patterns) = str::from_utf8(input)?
|
||||||
|
.split_once("\n\n")
|
||||||
|
.ok_or_eyre("Missing blank line")?;
|
||||||
|
|
||||||
|
let towels = towels
|
||||||
|
.split(", ")
|
||||||
|
.map(|towel| {
|
||||||
|
towel
|
||||||
|
.bytes()
|
||||||
|
.map(Color::from_b)
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
let patterns = patterns
|
||||||
|
.lines()
|
||||||
|
.map(|line| {
|
||||||
|
line.bytes()
|
||||||
|
.map(Color::from_b)
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
Ok((towels, patterns))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn part1((towels, patterns): Parsed) {
|
||||||
|
let mut possible = 0;
|
||||||
|
|
||||||
|
'pattern: for pattern in patterns {
|
||||||
|
let mut current = vec![&*pattern];
|
||||||
|
|
||||||
|
while let Some(v) = current.pop() {
|
||||||
|
if v.is_empty() {
|
||||||
|
possible += 1;
|
||||||
|
continue 'pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
for towel in &towels {
|
||||||
|
if v.starts_with(towel) {
|
||||||
|
current.push(&v[towel.len()..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print_res!("Number of possible patterns: {possible}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
pub fn part2((towels, patterns): Parsed) {
|
||||||
|
let mut memo = HashMap::new();
|
||||||
|
memo.insert(&[][..], 1);
|
||||||
|
|
||||||
|
let mut possible = 0;
|
||||||
|
|
||||||
|
fn arrangements<'a>(
|
||||||
|
pattern: &'a [Color],
|
||||||
|
towels: &[Vec<Color>],
|
||||||
|
memo: &mut HashMap<&'a [Color], usize>,
|
||||||
|
) -> usize {
|
||||||
|
match memo.get(pattern) {
|
||||||
|
Some(&v) => v,
|
||||||
|
None => {
|
||||||
|
let value = towels
|
||||||
|
.iter()
|
||||||
|
.map(|towel| {
|
||||||
|
if pattern.starts_with(towel) {
|
||||||
|
arrangements(&pattern[towel.len()..], towels, memo)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
memo.insert(pattern, value);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for pattern in &patterns {
|
||||||
|
possible += arrangements(pattern, &towels, &mut memo);
|
||||||
|
}
|
||||||
|
|
||||||
|
print_res!("Number of possible arrangements: {possible}");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() -> color_eyre::Result<()> {
|
||||||
|
let context = load()?;
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
let parsed = parsing(&context.input)?;
|
||||||
|
let elapsed = humantime::format_duration(start.elapsed());
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
if context.part == 1 {
|
||||||
|
part1(parsed);
|
||||||
|
} else {
|
||||||
|
part2(parsed);
|
||||||
|
}
|
||||||
|
let elapsed_part = humantime::format_duration(start.elapsed());
|
||||||
|
|
||||||
|
println!(" Parsing: {elapsed}");
|
||||||
|
println!(" Solving: {elapsed_part}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue