optimized day 19

This commit is contained in:
Ishan Jain 2024-12-20 12:35:45 +05:30
parent b319e46483
commit b2744f9a7b
2 changed files with 39 additions and 14 deletions

View File

@ -19,24 +19,23 @@ bbrgwb",
pub fn run(input: &str) -> i64 { pub fn run(input: &str) -> i64 {
let (towels, to_make) = input.split_once("\n\n").unwrap(); let (towels, to_make) = input.split_once("\n\n").unwrap();
let towels = towels.split(", ").map(|x| x.bytes().collect::<Vec<u8>>()).collect::<FxHashSet<Vec<u8>>>(); let towels = towels.split(", ").map(|x| remap(x.as_bytes())).collect::<FxHashSet<u64>>();
let to_make = to_make.lines().map(|x| x.bytes().collect::<Vec<u8>>());
let mut count = 0; let mut count = 0;
for pattern in to_make { for pattern in to_make.lines() {
count += test(&towels, &pattern) as i64; count += test(&towels, pattern.as_bytes()) as i64;
} }
count count
} }
fn test(towels: &FxHashSet<Vec<u8>>, pattern: &[u8]) -> bool { fn test(towels: &FxHashSet<u64>, pattern: &[u8]) -> bool {
let n = pattern.len(); let n = pattern.len();
let mut dp = vec![false; n + 1]; let mut dp = vec![false; n + 1];
dp[0] = true; dp[0] = true;
for i in 1..n+1 { for i in 1..n+1 {
for j in 0..i { 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; dp[i] = true;
break; break;
} }
@ -46,6 +45,18 @@ fn test(towels: &FxHashSet<Vec<u8>>, pattern: &[u8]) -> bool {
dp[n] 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() { fn main() {
for input in INPUTS.iter() { for input in INPUTS.iter() {
println!("answer = {}", run(input)); println!("answer = {}", run(input));

View File

@ -19,25 +19,27 @@ bbrgwb",
pub fn run(input: &str) -> i64 { pub fn run(input: &str) -> i64 {
let (towels, to_make) = input.split_once("\n\n").unwrap(); let (towels, to_make) = input.split_once("\n\n").unwrap();
let towels = towels.split(", ").map(|x| x.bytes().collect::<Vec<u8>>()).collect::<FxHashSet<Vec<u8>>>(); let towels = towels.split(", ").map(|x| remap(x.as_bytes())).collect::<FxHashSet<u64>>();
let to_make = to_make.lines().map(|x| x.bytes().collect::<Vec<u8>>());
let mut count = 0; let mut count = 0;
for pattern in to_make { for pattern in to_make.lines() {
let sum = test(&towels, &pattern); count += test(&towels, pattern.as_bytes());
count += sum;
} }
count count
} }
fn test(towels: &FxHashSet<Vec<u8>>, pattern: &[u8]) -> i64 { fn test(towels: &FxHashSet<u64>, pattern: &[u8]) -> i64 {
let n = pattern.len(); let n = pattern.len();
let mut dp = vec![0; n + 1]; let mut dp = vec![0; n + 1];
dp[0] = 1; // only 1 way to make an empty string dp[0] = 1; // only 1 way to make an empty string
for i in 1..n+1 { for i in 1..n+1 {
for j in 0..i { 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]; dp[i] += dp[j];
} }
} }
@ -46,6 +48,18 @@ fn test(towels: &FxHashSet<Vec<u8>>, pattern: &[u8]) -> i64 {
dp[n] 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() { fn main() {
for input in INPUTS.iter() { for input in INPUTS.iter() {
println!("answer = {}", run(input)); println!("answer = {}", run(input));
@ -53,7 +67,7 @@ fn main() {
} }
#[bench] #[bench]
fn part1(b: &mut test::Bencher) { fn part2(b: &mut test::Bencher) {
b.iter(|| { b.iter(|| {
let v = run(INPUTS[1]); let v = run(INPUTS[1]);
test::black_box(v); test::black_box(v);