mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 17:45:02 +01:00
properly speedup part2
This commit is contained in:
parent
672f2a3674
commit
93af372574
4 changed files with 94 additions and 32 deletions
|
|
@ -20,7 +20,7 @@ helper::define_variants! {
|
|||
basic => crate::part1;
|
||||
}
|
||||
part2 {
|
||||
naive => crate::naive::part2;
|
||||
naive => crate::naive::part2, sample_count=1000;
|
||||
zero_alloc => crate::zero_alloc::part2;
|
||||
branchless => |i| unsafe { crate::branchless::part2(i) };
|
||||
no_lines => |i| unsafe { crate::no_lines::part2(i) };
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
mod p2cache;
|
||||
|
||||
use helper::{Day, Variants};
|
||||
|
||||
pub fn main() {
|
||||
|
|
@ -9,10 +11,11 @@ struct Day04;
|
|||
helper::define_variants! {
|
||||
day => crate::Day04;
|
||||
part1 {
|
||||
basic => crate::part1;
|
||||
basic => crate::part1, sample_count=1000;
|
||||
}
|
||||
part2 {
|
||||
basic => crate::part2;
|
||||
basic => crate::part2, sample_count=100;
|
||||
cache => crate::p2cache::part2, sample_count=1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,21 +29,25 @@ impl Day for Day04 {
|
|||
}
|
||||
}
|
||||
|
||||
fn line_match_count(line: &str) -> usize {
|
||||
let mut numbers = line.split(':').nth(1).unwrap().split("|");
|
||||
let winning = numbers
|
||||
.next()
|
||||
.unwrap()
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>();
|
||||
let you_have = numbers.next().unwrap().split_whitespace();
|
||||
|
||||
you_have
|
||||
.filter(|have| winning.iter().any(|w| w == have))
|
||||
.count()
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> u64 {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut numbers = line.split(':').nth(1).unwrap().split("|");
|
||||
let winning = numbers
|
||||
.next()
|
||||
.unwrap()
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>();
|
||||
let you_have = numbers.next().unwrap().split_whitespace();
|
||||
|
||||
let win_amount = you_have
|
||||
.filter(|have| winning.iter().any(|w| w == have))
|
||||
.count();
|
||||
let win_amount = line_match_count(line);
|
||||
|
||||
if win_amount > 0 {
|
||||
1 << (win_amount - 1)
|
||||
|
|
@ -51,8 +58,19 @@ fn part1(input: &str) -> u64 {
|
|||
.sum()
|
||||
}
|
||||
|
||||
fn part2(_input: &str) -> u64 {
|
||||
0
|
||||
fn part2(input: &str) -> u64 {
|
||||
let lines = input.lines().map(line_match_count).collect::<Vec<_>>();
|
||||
let mut processed = 0;
|
||||
|
||||
let mut todo = (0..lines.len()).collect::<Vec<_>>();
|
||||
|
||||
while let Some(line) = todo.pop() {
|
||||
let matches = lines[line];
|
||||
todo.extend((line + 1)..(line + 1 + matches));
|
||||
processed += 1;
|
||||
}
|
||||
|
||||
processed
|
||||
}
|
||||
|
||||
helper::tests! {
|
||||
|
|
@ -62,8 +80,8 @@ helper::tests! {
|
|||
default => 24733;
|
||||
}
|
||||
part2 {
|
||||
small => 0;
|
||||
default => 0;
|
||||
small => 30;
|
||||
default => 5422730;
|
||||
}
|
||||
}
|
||||
helper::benchmarks! {}
|
||||
|
|
|
|||
31
2023/day04/src/p2cache.rs
Normal file
31
2023/day04/src/p2cache.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
pub fn part2(input: &str) -> u64 {
|
||||
let lines = input
|
||||
.lines()
|
||||
.map(crate::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
|
||||
}
|
||||
|
|
@ -72,20 +72,20 @@ macro_rules! define_variants {
|
|||
(
|
||||
day => $day:ty;
|
||||
part1 {
|
||||
$( $name1:ident => $func1:expr; )*
|
||||
$( $name1:ident => $func1:expr $(, sample_count=$sample_count1:expr)? ; )*
|
||||
}
|
||||
part2 {
|
||||
$( $name2:ident => $func2:expr; )*
|
||||
$( $name2:ident => $func2:expr $(, sample_count=$sample_count2:expr)? ; )*
|
||||
}
|
||||
) => {
|
||||
macro_rules! part1_variants {
|
||||
($macro:ident) => {
|
||||
$crate::$macro! { $day; $( ($name1, $func1) ),* }
|
||||
$crate::$macro! { $day; $( ($name1, $func1, [ $( sample_count=$sample_count1, )? ]) ),* }
|
||||
};
|
||||
}
|
||||
macro_rules! part2_variants {
|
||||
($macro:ident) => {
|
||||
$crate::$macro! { $day; $( ($name2, $func2) ),* }
|
||||
$crate::$macro! { $day; $( ($name2, $func2, [ $( sample_count=$sample_count2, )? ]) ),* }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
@ -93,7 +93,7 @@ macro_rules! define_variants {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! construct_variants {
|
||||
( $day:ty; $( ($name:ident, $func:expr) ),*) => {
|
||||
( $day:ty; $( ($name:ident, $func:expr, [ $($_:tt)* ]) ),*) => {
|
||||
$crate::Variants {
|
||||
variants: vec![$(
|
||||
$crate::Variant::new(stringify!($name), $func)
|
||||
|
|
@ -105,7 +105,6 @@ macro_rules! construct_variants {
|
|||
#[macro_export]
|
||||
macro_rules! benchmarks {
|
||||
() => {
|
||||
#[::divan::bench_group(sample_count = 10_000)]
|
||||
mod bench {
|
||||
mod part1 {
|
||||
part1_variants! { _define_benchmarks }
|
||||
|
|
@ -122,15 +121,29 @@ macro_rules! benchmarks {
|
|||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! _define_benchmarks {
|
||||
($day:ty; $( ($name:ident, $func:expr) ),*) => {
|
||||
$(
|
||||
#[::divan::bench]
|
||||
fn $name(bencher: ::divan::Bencher) {
|
||||
let input = include_str!("../input.txt");
|
||||
let input = <$day as $crate::Day>::pad_input(input);
|
||||
macro_rules! _bench_sample_count {
|
||||
(;$($tt:tt)*) => {
|
||||
#[::divan::bench(sample_count = 10_000)]
|
||||
$($tt)*
|
||||
};
|
||||
($sample_count:expr; $($tt:tt)*) => {
|
||||
#[::divan::bench(sample_count = $sample_count)]
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
bencher.with_inputs(|| input.as_ref()).bench_values($func);
|
||||
#[macro_export]
|
||||
macro_rules! _define_benchmarks {
|
||||
($day:ty; $( ($name:ident, $func:expr, [ $(sample_count=$sample_count:expr,)? ]) ),*) => {
|
||||
$(
|
||||
$crate::_bench_sample_count! {
|
||||
$($sample_count)?;
|
||||
fn $name(bencher: ::divan::Bencher) {
|
||||
let input = include_str!("../input.txt");
|
||||
let input = <$day as $crate::Day>::pad_input(input);
|
||||
|
||||
bencher.with_inputs(|| input.as_ref()).bench_values($func);
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue