From b2744f9a7bcceb036cc138a836723357e21ae1f7 Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Fri, 20 Dec 2024 12:35:45 +0530 Subject: [PATCH] optimized day 19 --- src/day19/1.rs | 23 +++++++++++++++++------ src/day19/2.rs | 30 ++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/day19/1.rs b/src/day19/1.rs index 73ed073..ab740d4 100644 --- a/src/day19/1.rs +++ b/src/day19/1.rs @@ -19,24 +19,23 @@ bbrgwb", pub fn run(input: &str) -> i64 { let (towels, to_make) = input.split_once("\n\n").unwrap(); - let towels = towels.split(", ").map(|x| x.bytes().collect::>()).collect::>>(); - let to_make = to_make.lines().map(|x| x.bytes().collect::>()); + let towels = towels.split(", ").map(|x| remap(x.as_bytes())).collect::>(); let mut count = 0; - for pattern in to_make { - count += test(&towels, &pattern) as i64; + for pattern in to_make.lines() { + count += test(&towels, pattern.as_bytes()) as i64; } count } -fn test(towels: &FxHashSet>, pattern: &[u8]) -> bool { +fn test(towels: &FxHashSet, pattern: &[u8]) -> bool { let n = pattern.len(); let mut dp = vec![false; n + 1]; dp[0] = true; for i in 1..n+1 { for j in 0..i { - if dp[j] && towels.contains(&pattern[j..i]) { + if dp[j] && (i - j <= 8 && towels.contains(&remap(&pattern[j..i]))) { dp[i] = true; break; } @@ -46,6 +45,18 @@ fn test(towels: &FxHashSet>, pattern: &[u8]) -> bool { dp[n] } +#[inline] +const fn remap(n: &[u8]) -> u64 { + let mut out = 0; + let mut i = 0; + while i < n.len() { + out <<= 8; + out |= n[i as usize] as u64; + i += 1; + } + out +} + fn main() { for input in INPUTS.iter() { println!("answer = {}", run(input)); diff --git a/src/day19/2.rs b/src/day19/2.rs index 878ccb7..17048b0 100644 --- a/src/day19/2.rs +++ b/src/day19/2.rs @@ -19,25 +19,27 @@ bbrgwb", pub fn run(input: &str) -> i64 { let (towels, to_make) = input.split_once("\n\n").unwrap(); - let towels = towels.split(", ").map(|x| x.bytes().collect::>()).collect::>>(); - let to_make = to_make.lines().map(|x| x.bytes().collect::>()); + let towels = towels.split(", ").map(|x| remap(x.as_bytes())).collect::>(); let mut count = 0; - for pattern in to_make { - let sum = test(&towels, &pattern); - count += sum; + for pattern in to_make.lines() { + count += test(&towels, pattern.as_bytes()); } count } -fn test(towels: &FxHashSet>, pattern: &[u8]) -> i64 { +fn test(towels: &FxHashSet, pattern: &[u8]) -> i64 { let n = pattern.len(); let mut dp = vec![0; n + 1]; dp[0] = 1; // only 1 way to make an empty string for i in 1..n+1 { for j in 0..i { - if towels.contains(&pattern[j..i]) { + // no word bigger than 8 chars + if i - j > 8 { + continue; + } + if towels.contains(&remap(&pattern[j..i])) { dp[i] += dp[j]; } } @@ -46,6 +48,18 @@ fn test(towels: &FxHashSet>, pattern: &[u8]) -> i64 { dp[n] } +#[inline] +const fn remap(n: &[u8]) -> u64 { + let mut out = 0; + let mut i = 0; + while i < n.len() { + out <<= 8; + out |= n[i as usize] as u64; + i += 1; + } + out +} + fn main() { for input in INPUTS.iter() { println!("answer = {}", run(input)); @@ -53,7 +67,7 @@ fn main() { } #[bench] -fn part1(b: &mut test::Bencher) { +fn part2(b: &mut test::Bencher) { b.iter(|| { let v = run(INPUTS[1]); test::black_box(v);