From: alex <> Date: Thu, 19 Dec 2024 15:35:02 +0000 (+0100) Subject: Day19 - part 2 X-Git-Url: https://aoc.elinar.fr/?a=commitdiff_plain;h=7292bb2a6032533d6c622762ceccbc8a3001e49b;p=aoc_2024 Day19 - part 2 --- diff --git a/src/day19.rs b/src/day19.rs index 710105d..172ba24 100644 --- a/src/day19.rs +++ b/src/day19.rs @@ -1,42 +1,91 @@ use std::error::Error; use std::path::Path; -use std::collections::HashSet; +use std::collections::{HashSet, HashMap}; -fn is_valid_design(design: &str, patterns: &HashSet<&str>) -> bool { +struct Puzzle<'a> { + patterns: HashSet::<&'a str>, + designs: Vec<&'a str>, + memo: HashMap<&'a str, u64>, + n_valid: u64, +} + +impl<'a> Puzzle<'a> { + pub fn new(input: &'a str) -> Self { + let (patterns, designs) = input.split_once("\n\n").unwrap(); + let patterns = patterns.split(", ").collect(); + let designs = designs.lines().collect(); + let memo = HashMap::new(); + let n_valid = 0; - if design.is_empty() { - return true + Self { patterns, designs, memo, n_valid } } - for i in 0..design.len() { - if patterns.contains(&design[0..=i]) && - is_valid_design(&design[(i+1)..design.len()], patterns) - { + fn is_valid_design(&self, design: &str) -> bool { + if design.is_empty() { return true } + + for i in 0..design.len() { + if self.patterns.contains(&design[0..=i]) && + self.is_valid_design(&design[(i+1)..design.len()]) + { + return true; + } + } + false } - false + fn all_valid_design(&mut self, design: &'a str) -> bool { + if let Some(n) = self.memo.get(design) { + self.n_valid += n; + return true; + } + if design.is_empty() { + self.n_valid += 1; + return true + } + + let mut n = 0; + let mut is_valid = false; + for i in 0..design.len() { + if self.patterns.contains(&design[0..=i]) && + self.all_valid_design(&design[(i+1)..design.len()]) + { + n += match self.memo.get(&design[(i+1)..design.len()]) { + Some(m) => *m, + None => 1 + }; + is_valid = true; + } + } + + self.memo.insert(design, n); + + is_valid + } } fn run_part1(input: &str) -> Result> { println!("Running {} - part 1", get_day()); - let (patterns, designs) = input.split_once("\n\n").unwrap(); - let patterns: HashSet<&str> = patterns.split(", ") - .collect(); - - let res = designs.lines() - .filter(|d| is_valid_design(d, &patterns)) + let puzzle = Puzzle::new(input); + let res = puzzle.designs.iter() + .filter(|d| puzzle.is_valid_design(d)) .count() as u32; Ok(res) } -fn run_part2(input: &str) -> Result> { +fn run_part2(input: &str) -> Result> { println!("Running {} - part 2", get_day()); - Ok(0) + let mut puzzle = Puzzle::new(input); + puzzle.designs.clone().iter() + .for_each(|d| { puzzle.all_valid_design(d); }); + + let res = puzzle.n_valid; + + Ok(res) } pub fn run(input: &str) -> Result<(), Box> { @@ -99,6 +148,6 @@ abcdeea"; #[test] fn test_part2() { - assert_eq!(0, run_part2(TEXT_INPUT).unwrap()); + assert_eq!(16, run_part2(TEXT_INPUT).unwrap()); } }