From 65d498f168fbe4eb599b7e2b52d1d3125b9f46ff Mon Sep 17 00:00:00 2001 From: Keenan Tims Date: Wed, 18 Dec 2024 22:39:26 -0800 Subject: [PATCH] day19: complete solution --- .aoc_tiles/tiles/2024/19.png | Bin 3843 -> 8409 bytes README.md | 5 +- src/day19.rs | 176 +++++++++++++++++++++++++++++++++-- 3 files changed, 173 insertions(+), 8 deletions(-) diff --git a/.aoc_tiles/tiles/2024/19.png b/.aoc_tiles/tiles/2024/19.png index 291b2ef4511932a85929e26bc4a335a197f81c20..9da34f0fa1f63f196b1365413a8ffc3ec3181f05 100644 GIT binary patch literal 8409 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 SbRO8;g3L^;j7dhfWBv!Mwu~MC diff --git a/README.md b/README.md index 0e6a135..b2594e8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- 2024 - 36 ⭐ - Rust + 2024 - 38 ⭐ - Rust

@@ -56,4 +56,7 @@ + + + diff --git a/src/day19.rs b/src/day19.rs index bb922e8..42f7856 100644 --- a/src/day19.rs +++ b/src/day19.rs @@ -1,31 +1,193 @@ use aoc_runner_derive::aoc; +use cached::proc_macro::cached; +use itertools::Itertools; +use rustc_hash::{FxHashMap, FxHasher}; +use std::{ + collections::VecDeque, + fmt::{Display, Write}, +}; -fn parse(input: &str) -> String { - todo!() +#[repr(u8)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +enum Stripe { + White = b'w', + Blue = b'u', + Black = b'b', + Red = b'r', + Green = b'g', +} + +impl From<&u8> for Stripe { + fn from(value: &u8) -> Self { + match value { + b'w' => Self::White, + b'u' => Self::Blue, + b'b' => Self::Black, + b'r' => Self::Red, + b'g' => Self::Green, + _ => unimplemented!(), + } + } +} + +impl Into for &Stripe { + fn into(self) -> char { + let v = *self as u8; + v.into() + } +} + +impl Display for Stripe { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_char(self.into()) + } +} + +#[derive(Debug)] +struct Design { + stripes: Vec, +} + +impl From<&[u8]> for Design { + fn from(input: &[u8]) -> Self { + let stripes = input.iter().map(|c| c.into()).collect(); + Self { stripes } + } +} + +impl Display for Design { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for stripe in &self.stripes { + f.write_char(stripe.into())?; + } + Ok(()) + } +} + +#[derive(Debug)] +struct Onsen { + towels: Vec, + designs: Vec, + // ways_cache: FxHashMap<&'a [Stripe], i64> +} + +impl Display for Onsen { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.towels.iter().join(", "))?; + writeln!(f)?; + writeln!(f)?; + for d in &self.designs { + d.fmt(f)?; + writeln!(f)?; + } + Ok(()) + } +} + +impl Onsen { + fn possible(&self, d: &[Stripe]) -> bool { + if d.len() == 0 { + return true; + } + for t in &self.towels { + if d.starts_with(&t.stripes) { + if self.possible(d.split_at(t.stripes.len()).1) { + return true; + } + } + } + false + } + // Count the ways to construct a given substring + fn ways<'a>(&'a self, d: &'a [Stripe], mut cache: FxHashMap<&'a [Stripe], i64>) -> (FxHashMap<&'a [Stripe], i64>, i64) { + if d.len() == 0 { + // println!("ways to make {} - 0", d.iter().join("")); + return (cache, 1); + } + if cache.contains_key(d) { + let val = cache[d]; + return (cache, val); + } + + let mut count = 0; + for t in &self.towels { + if d.starts_with(&t.stripes) { + let res_count; + (cache, res_count) = self.ways(&d[t.stripes.len()..d.len()], cache); + count += res_count; + } + } + // println!("ways to make {} - {}", d.iter().join(""), count); + cache.insert(d, count); + (cache, count) + } + fn count_possible(&self) -> i64 { + self.designs + .iter() + .map(|d| self.possible(&d.stripes)) + .filter(|p| *p) + .count() as i64 + } + fn count_ways(&self) -> i64 { + self.designs.iter().map(|d| self.ways(&d.stripes, FxHashMap::default()).1).sum::() + } +} + +fn parse(input: &str) -> Onsen { + let mut lines = input.lines(); + + let towels = lines + .next() + .unwrap() + .split(&[',', ' ']) + .filter(|s| !s.is_empty()) + .map(|s| s.as_bytes().into()) + .collect(); + lines.next().unwrap(); // discard empty line + + let designs = lines.map(|l| l.as_bytes().into()).collect(); + + Onsen { towels, designs } } #[aoc(day19, part1)] fn part1(input: &str) -> i64 { - todo!() + let onsen = parse(input); + + onsen.count_possible() } #[aoc(day19, part2)] fn part2(input: &str) -> i64 { - todo!() + let onsen = parse(input); + + onsen.count_ways() } #[cfg(test)] mod tests { use super::*; - const EXAMPLE: &str = ""; + const EXAMPLE: &str = "r, wr, b, g, bwu, rb, gb, br + +brwrr +bggr +gbbr +rrbgbr +ubwu +bwurrg +brgr +bbrgwb"; +const EXAMPLE2: &str = "r, wr, b, g, bwu, rb, gb, br + +rrbgbr"; #[test] fn part1_example() { - assert_eq!(part1(EXAMPLE), 0); + assert_eq!(part1(EXAMPLE), 6); } #[test] fn part2_example() { - assert_eq!(part2(EXAMPLE), 0); + assert_eq!(part2(EXAMPLE), 16); } }