This commit is contained in:
nora 2023-12-04 21:21:19 +01:00
parent 93af372574
commit b12e92a5cb
8 changed files with 238 additions and 10 deletions

View file

@ -9,6 +9,8 @@ edition = "2021"
nom.workspace = true
helper.workspace = true
divan.workspace = true
arrayvec = "0.7.4"
bstr = "1.8.0"
[[bench]]
name = "benches"

View file

@ -1,4 +1,7 @@
mod p2ascii;
mod p2cache;
mod p2chunks;
mod p2no_alloc;
use helper::{Day, Variants};
@ -11,11 +14,14 @@ struct Day04;
helper::define_variants! {
day => crate::Day04;
part1 {
basic => crate::part1, sample_count=1000;
basic => crate::part1;
}
part2 {
basic => crate::part2, sample_count=100;
cache => crate::p2cache::part2, sample_count=1000;
cache => crate::p2cache::part2;
no_alloc => crate::p2no_alloc::part2;
ascii => crate::p2ascii::part2;
chunks => crate::p2chunks::part2;
}
}

43
2023/day04/src/p2ascii.rs Normal file
View file

@ -0,0 +1,43 @@
fn line_match_count(line: &str) -> usize {
let mut numbers = line.split(':').nth(1).unwrap().split("|");
let winning = numbers
.next()
.unwrap()
.split_ascii_whitespace()
.collect::<arrayvec::ArrayVec<_, 16>>();
let you_have = numbers.next().unwrap().split_ascii_whitespace();
you_have
.filter(|have| winning.iter().any(|w| w == have))
.count()
}
pub fn part2(input: &str) -> u64 {
let lines = input.lines().map(line_match_count).collect::<Vec<_>>();
let mut cache = vec![0; lines.len()];
let mut processed = 0;
// By iterating backwards, we ensure the cache is always populated for every subsequent line.
for (i, result) in lines.iter().copied().enumerate().rev() {
let before = processed;
processed += 1; // Every card gives us one card.
// Now, let's see how many cards this card will expand to.
for expand in (i + 1)..((i + 1) + result) {
#[cfg(debug_assertions)]
eprintln!(
"{} expands to {} which is worth {}",
i + 1,
expand + 1,
cache[expand]
);
// Since the value is bigger than i, it must be cached!
processed += cache[expand];
}
cache[i] = processed - before;
}
processed
}

View file

@ -0,0 +1,49 @@
fn line_match_count(line: &str) -> usize {
let mut numbers = line.split(':').nth(1).unwrap().split("|");
let winning = numbers
.next()
.unwrap()
.as_bytes()
// Chunks of double digit numbers with a leading space. We don't care about the trailing space.
.chunks_exact(3)
.collect::<arrayvec::ArrayVec<_, 16>>();
let you_have = numbers.next().unwrap().as_bytes().chunks_exact(3);
you_have
.filter(|have| {
winning.iter().any(|w| {
w == have
})
})
.count()
}
pub fn part2(input: &str) -> u64 {
let lines = input.lines().map(line_match_count).collect::<Vec<_>>();
let mut cache = vec![0; lines.len()];
let mut processed = 0;
// By iterating backwards, we ensure the cache is always populated for every subsequent line.
for (i, result) in lines.iter().copied().enumerate().rev() {
let before = processed;
processed += 1; // Every card gives us one card.
// Now, let's see how many cards this card will expand to.
for expand in (i + 1)..((i + 1) + result) {
#[cfg(debug_assertions)]
eprintln!(
"{} expands to {} which is worth {}",
i + 1,
expand + 1,
cache[expand]
);
// Since the value is bigger than i, it must be cached!
processed += cache[expand];
}
cache[i] = processed - before;
}
processed
}

View file

@ -0,0 +1,43 @@
fn line_match_count(line: &str) -> usize {
let mut numbers = line.split(':').nth(1).unwrap().split("|");
let winning = numbers
.next()
.unwrap()
.split_whitespace()
.collect::<arrayvec::ArrayVec<_, 16>>();
let you_have = numbers.next().unwrap().split_whitespace();
you_have
.filter(|have| winning.iter().any(|w| w == have))
.count()
}
pub fn part2(input: &str) -> u64 {
let lines = input.lines().map(line_match_count).collect::<Vec<_>>();
let mut cache = vec![0; lines.len()];
let mut processed = 0;
// By iterating backwards, we ensure the cache is always populated for every subsequent line.
for (i, result) in lines.iter().copied().enumerate().rev() {
let before = processed;
processed += 1; // Every card gives us one card.
// Now, let's see how many cards this card will expand to.
for expand in (i + 1)..((i + 1) + result) {
#[cfg(debug_assertions)]
eprintln!(
"{} expands to {} which is worth {}",
i + 1,
expand + 1,
cache[expand]
);
// Since the value is bigger than i, it must be cached!
processed += cache[expand];
}
cache[i] = processed - before;
}
processed
}