diff --git a/src/bin/d19.rs b/src/bin/d19.rs index 61930b8..6cf5271 100644 --- a/src/bin/d19.rs +++ b/src/bin/d19.rs @@ -1,4 +1,3 @@ - use std::collections::{HashMap, HashSet}; use advent_of_code_2024::{make_main, SResult}; @@ -15,43 +14,45 @@ fn solve(lines: Vec) -> SResult<(usize, usize)> { // see if we can form it using shorter patterns. If we can, ignore it. patterns.sort_by(|a, b| a.len().cmp(&b.len())); // Stores a mapping of 'char' => (pattern, larger_patterns) - let mut new_patterns: HashMap)>> = HashMap::default(); + let mut new_patterns: Vec<(&str, HashSet<&str>)> = Vec::new(); let mut small_patterns = HashSet::new(); for pattern in &patterns { - if let Some(c) = rec(&pattern, &new_patterns, &mut memo) { - *memo.entry(&pattern).or_insert(0) = c + 1; + if let Some(c) = rec(&pattern, &new_patterns, &mut HashMap::new()) { + // At this point, we haven't loaded the larger patterns into the hashsets + // in the new_patterns, so we never check if it matches. We always + // add one to the computed value. + //*memo.entry(&pattern).or_insert(0) = c + 1; } else { - let start = pattern.chars().next().unwrap(); - new_patterns.entry(start).or_insert_with(Vec::new).push((pattern, HashSet::new())); + new_patterns.push((pattern, HashSet::new())); small_patterns.insert(pattern); } } - for (_, v) in new_patterns.iter_mut() { - v.sort_by(|a, b| a.0.cmp(&b.0)); + new_patterns.sort_by(|a, b| a.0.cmp(&b.0)); - for v in v { - for pattern in &patterns { - if small_patterns.contains(pattern) { - continue; - } - if let Some(_) = pattern.strip_prefix(v.0) { - v.1.insert(pattern); - } + for v in &mut new_patterns { + for pattern in &patterns { + if small_patterns.contains(pattern) { + continue; + } + if let Some(_) = pattern.strip_prefix(v.0) { + v.1.insert(pattern); } } } - println!("Patterns: {:?}", new_patterns); - - let mut memo_vec: Vec<(&str, usize)> = memo.clone().into_iter().collect(); - memo_vec.sort_by(|a, b| a.0.cmp(&b.0)); - println!("Memo: {:?}", memo_vec); + // Reset the memoization + let mut memo: HashMap<&str, usize> = HashMap::default(); + memo.insert("", 1); + + for pattern in &patterns { + rec(&pattern, &new_patterns, &mut memo); + } let mut count = 0; let mut count2 = 0; for (i, line) in (&lines[2..]).iter().enumerate() { - //println!("Line {} of {}", i, lines.len()-2); + println!("Line {} of {}", i, lines.len()-2); if let Some(c) = rec(&line, &new_patterns, &mut memo) { count += 1; count2 += c; @@ -59,17 +60,19 @@ fn solve(lines: Vec) -> SResult<(usize, usize)> { } let mut memo_vec: Vec<(&str, usize)> = memo.into_iter().collect(); memo_vec.sort_by(|a, b| a.0.cmp(&b.0)); - println!("Memo: {:?}", memo_vec); Ok((count, count2)) } -fn rec<'a>(left: &'a str, patterns: &HashMap)>>, memo: &mut HashMap<&'a str, usize>) -> Option { +fn rec<'a>( + left: &'a str, + patterns: &Vec<(&'a str, HashSet<&'a str>)>, + memo: &mut HashMap<&'a str, usize>, +) -> Option { if let Some(val) = memo.get(&left) { return Some(*val); } let mut count = 0; - let start = left.chars().next().unwrap(); - for (pattern, large_patterns) in patterns.get(&start).unwrap_or(&vec!()) { + for (pattern, large_patterns) in patterns { if let Some(substr) = left.strip_prefix(pattern) { if let Some(c) = rec(substr, patterns, memo) { count += c; @@ -103,4 +106,4 @@ mod tests { let got = solve(strings).unwrap(); assert_eq!(got, (6, 16)); } -} \ No newline at end of file +}