mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-16 10:35:02 +01:00
benchmarks
This commit is contained in:
parent
5dff963dc2
commit
546149ae38
16 changed files with 517 additions and 188 deletions
|
|
@ -7,3 +7,8 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
helper.workspace = true
|
||||
divan.workspace = true
|
||||
|
||||
[[bench]]
|
||||
name = "benches"
|
||||
harness = false
|
||||
|
|
|
|||
3
2023/day1/benches/benches.rs
Normal file
3
2023/day1/benches/benches.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
day1::bench();
|
||||
}
|
||||
83
2023/day1/src/lib.rs
Normal file
83
2023/day1/src/lib.rs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
use std::mem::MaybeUninit;
|
||||
|
||||
use helper::{Day, Variants};
|
||||
|
||||
mod branchless;
|
||||
mod naive;
|
||||
mod no_lines;
|
||||
mod vectorized;
|
||||
mod zero_alloc;
|
||||
|
||||
pub fn main() {
|
||||
helper::main::<Day1>(include_str!("../input.txt"));
|
||||
}
|
||||
|
||||
struct Day1;
|
||||
|
||||
helper::define_variants! {
|
||||
day => crate::Day1;
|
||||
part1 {
|
||||
basic => crate::part1;
|
||||
}
|
||||
part2 {
|
||||
naive => crate::naive::part2;
|
||||
zero_alloc => crate::zero_alloc::part2;
|
||||
branchless => |i| unsafe { crate::branchless::part2(i) };
|
||||
no_lines => |i| unsafe { crate::no_lines::part2(i) };
|
||||
vectorized => |i| unsafe { crate::vectorized::part2(i) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Day for Day1 {
|
||||
fn pad_input(input: &str) -> std::borrow::Cow<str> {
|
||||
let mut input = input.to_owned();
|
||||
input.reserve(10); // enough to read u64
|
||||
unsafe {
|
||||
input
|
||||
.as_mut_vec()
|
||||
.spare_capacity_mut()
|
||||
.fill(MaybeUninit::new(0))
|
||||
};
|
||||
std::borrow::Cow::Owned(input)
|
||||
}
|
||||
fn part1() -> Variants {
|
||||
part1_variants!(construct_variants)
|
||||
}
|
||||
|
||||
fn part2() -> Variants {
|
||||
part2_variants!(construct_variants)
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> u64 {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut chars = line.chars().filter(|c| c.is_ascii_digit());
|
||||
let first = chars.next().unwrap();
|
||||
let last = chars.next_back().unwrap_or(first);
|
||||
|
||||
[first, last]
|
||||
.into_iter()
|
||||
.collect::<String>()
|
||||
.parse::<u64>()
|
||||
.unwrap()
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
helper::tests! {
|
||||
day1 Day1;
|
||||
part1 {
|
||||
"../input_small1.txt" => 142;
|
||||
"../input.txt" => 54632;
|
||||
}
|
||||
part2 {
|
||||
"../input_small2.txt" => 281;
|
||||
"../input.txt" => 54019;
|
||||
}
|
||||
}
|
||||
|
||||
helper::benchmarks! {}
|
||||
|
|
@ -1,75 +1,3 @@
|
|||
use std::mem::MaybeUninit;
|
||||
|
||||
use helper::{Day, Variant, Variants};
|
||||
|
||||
mod branchless;
|
||||
mod naive;
|
||||
mod no_lines;
|
||||
mod vectorized;
|
||||
mod zero_alloc;
|
||||
|
||||
fn main() {
|
||||
helper::main::<Day1>(include_str!("../input.txt"));
|
||||
}
|
||||
|
||||
struct Day1;
|
||||
|
||||
impl Day for Day1 {
|
||||
fn pad_input(input: &str) -> std::borrow::Cow<str> {
|
||||
let mut input = input.to_owned();
|
||||
input.reserve(10); // enough to read u64
|
||||
unsafe {
|
||||
input
|
||||
.as_mut_vec()
|
||||
.spare_capacity_mut()
|
||||
.fill(MaybeUninit::new(0))
|
||||
};
|
||||
std::borrow::Cow::Owned(input)
|
||||
}
|
||||
fn part1() -> Variants {
|
||||
Variants::basic(part1)
|
||||
}
|
||||
|
||||
fn part2() -> Variants {
|
||||
Variants {
|
||||
variants: vec![
|
||||
Variant::new("naive", naive::part2),
|
||||
Variant::new("zero_alloc", zero_alloc::part2),
|
||||
Variant::new("branchless", |i| unsafe { branchless::part2(i) }),
|
||||
Variant::new("no_lines", |i| unsafe { no_lines::part2(i) }),
|
||||
Variant::new("vectorized", |i| unsafe { vectorized::part2(i) }),
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> u64 {
|
||||
let sum = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut chars = line.chars().filter(|c| c.is_ascii_digit());
|
||||
let first = chars.next().unwrap();
|
||||
let last = chars.next_back().unwrap_or(first);
|
||||
|
||||
[first, last]
|
||||
.into_iter()
|
||||
.collect::<String>()
|
||||
.parse::<u64>()
|
||||
.unwrap()
|
||||
})
|
||||
.sum::<u64>();
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
helper::tests! {
|
||||
day1 Day1;
|
||||
part1 {
|
||||
"../input_small1.txt" => 142;
|
||||
"../input.txt" => 54632;
|
||||
}
|
||||
part2 {
|
||||
"../input_small2.txt" => 281;
|
||||
"../input.txt" => 54019;
|
||||
}
|
||||
day1::main();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,3 +8,8 @@ edition = "2021"
|
|||
[dependencies]
|
||||
nom.workspace = true
|
||||
helper.workspace = true
|
||||
divan.workspace = true
|
||||
|
||||
[[bench]]
|
||||
name = "benches"
|
||||
harness = false
|
||||
|
|
|
|||
3
2023/day2/benches/benches.rs
Normal file
3
2023/day2/benches/benches.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
day2::bench();
|
||||
}
|
||||
113
2023/day2/src/lib.rs
Normal file
113
2023/day2/src/lib.rs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
use helper::Day;
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::tag,
|
||||
combinator::{all_consuming, map},
|
||||
multi::separated_list0,
|
||||
sequence::{preceded, tuple},
|
||||
Finish, IResult,
|
||||
};
|
||||
|
||||
pub fn main() {
|
||||
helper::main::<Day2>(include_str!("../input.txt"));
|
||||
}
|
||||
|
||||
struct Day2;
|
||||
|
||||
helper::define_variants! {
|
||||
day => crate::Day2;
|
||||
part1 {
|
||||
basic => crate::part1;
|
||||
}
|
||||
part2 {
|
||||
basic => crate::part2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Day for Day2 {
|
||||
fn part1() -> helper::Variants {
|
||||
part1_variants!(construct_variants)
|
||||
}
|
||||
|
||||
fn part2() -> helper::Variants {
|
||||
part2_variants!(construct_variants)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Color {
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
}
|
||||
|
||||
fn parse_line(line: &str) -> (u64, Vec<Vec<(u64, Color)>>) {
|
||||
let parse_color = |i| -> IResult<&str, Color> {
|
||||
alt((
|
||||
map(tag("blue"), |_| Color::Blue),
|
||||
map(tag("red"), |_| Color::Red),
|
||||
map(tag("green"), |_| Color::Green),
|
||||
))(i)
|
||||
};
|
||||
let parse_cubes = tuple((helper::integer, preceded(tag(" "), parse_color)));
|
||||
let parse_round = separated_list0(tag(", "), parse_cubes);
|
||||
let parse_game = separated_list0(tag("; "), parse_round);
|
||||
let parse_line = tuple((
|
||||
preceded(tag("Game "), helper::integer),
|
||||
preceded(tag(": "), parse_game),
|
||||
));
|
||||
|
||||
all_consuming(parse_line)(line).finish().unwrap().1
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> u64 {
|
||||
const MAX: [u64; 3] = [12, 13, 14];
|
||||
|
||||
input
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let line = parse_line(line);
|
||||
for round in line.1 {
|
||||
for (amount, color) in round {
|
||||
if MAX[color as usize] < amount {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(line.0)
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> u64 {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let line = parse_line(line);
|
||||
let mut min = [0, 0, 0];
|
||||
for round in line.1 {
|
||||
for (amount, color) in round {
|
||||
min[color as usize] = min[color as usize].max(amount);
|
||||
}
|
||||
}
|
||||
|
||||
let power = min[0] * min[1] * min[2];
|
||||
power
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
helper::tests! {
|
||||
day2 Day2;
|
||||
part1 {
|
||||
small => 8;
|
||||
default => 1931;
|
||||
}
|
||||
part2 {
|
||||
small => 2286;
|
||||
default => 83105;
|
||||
}
|
||||
}
|
||||
|
||||
helper::benchmarks! {}
|
||||
|
|
@ -1,101 +1,3 @@
|
|||
use helper::{Day, Variants};
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::tag,
|
||||
combinator::{all_consuming, map},
|
||||
multi::separated_list0,
|
||||
sequence::{preceded, tuple},
|
||||
Finish, IResult,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
helper::main::<Day2>(include_str!("../input.txt"));
|
||||
}
|
||||
|
||||
struct Day2;
|
||||
|
||||
impl Day for Day2 {
|
||||
fn part1() -> helper::Variants {
|
||||
Variants::basic(part1)
|
||||
}
|
||||
|
||||
fn part2() -> helper::Variants {
|
||||
Variants::basic(part2)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Color {
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
}
|
||||
|
||||
fn parse_line(line: &str) -> (u64, Vec<Vec<(u64, Color)>>) {
|
||||
let parse_color = |i| -> IResult<&str, Color> {
|
||||
alt((
|
||||
map(tag("blue"), |_| Color::Blue),
|
||||
map(tag("red"), |_| Color::Red),
|
||||
map(tag("green"), |_| Color::Green),
|
||||
))(i)
|
||||
};
|
||||
let parse_cubes = tuple((helper::integer, preceded(tag(" "), parse_color)));
|
||||
let parse_round = separated_list0(tag(", "), parse_cubes);
|
||||
let parse_game = separated_list0(tag("; "), parse_round);
|
||||
let parse_line = tuple((
|
||||
preceded(tag("Game "), helper::integer),
|
||||
preceded(tag(": "), parse_game),
|
||||
));
|
||||
|
||||
all_consuming(parse_line)(line).finish().unwrap().1
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> u64 {
|
||||
const MAX: [u64; 3] = [12, 13, 14];
|
||||
|
||||
input
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let line = parse_line(line);
|
||||
for round in line.1 {
|
||||
for (amount, color) in round {
|
||||
if MAX[color as usize] < amount {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(line.0)
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> u64 {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let line = parse_line(line);
|
||||
let mut min = [0, 0, 0];
|
||||
for round in line.1 {
|
||||
for (amount, color) in round {
|
||||
min[color as usize] = min[color as usize].max(amount);
|
||||
}
|
||||
}
|
||||
|
||||
let power = min[0] * min[1] * min[2];
|
||||
power
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
helper::tests! {
|
||||
day2 Day2;
|
||||
part1 {
|
||||
small => 8;
|
||||
default => 1931;
|
||||
}
|
||||
part2 {
|
||||
small => 2286;
|
||||
default => 83105;
|
||||
}
|
||||
day2::main();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,3 +8,8 @@ edition = "2021"
|
|||
[dependencies]
|
||||
nom.workspace = true
|
||||
helper.workspace = true
|
||||
divan.workspace = true
|
||||
|
||||
[[bench]]
|
||||
name = "benches"
|
||||
harness = false
|
||||
|
|
|
|||
3
2023/day3/benches/benches.rs
Normal file
3
2023/day3/benches/benches.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
day3::bench();
|
||||
}
|
||||
|
|
@ -1,20 +1,30 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use helper::{Day, Variants};
|
||||
use helper::Day;
|
||||
|
||||
fn main() {
|
||||
pub fn main() {
|
||||
helper::main::<Day3>(include_str!("../input.txt"));
|
||||
}
|
||||
|
||||
struct Day3;
|
||||
|
||||
helper::define_variants! {
|
||||
day => crate::Day3;
|
||||
part1 {
|
||||
basic => crate::part1;
|
||||
}
|
||||
part2 {
|
||||
basic => crate::part2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Day for Day3 {
|
||||
fn part1() -> Variants {
|
||||
Variants::basic(part1)
|
||||
fn part1() -> helper::Variants {
|
||||
part1_variants!(construct_variants)
|
||||
}
|
||||
|
||||
fn part2() -> Variants {
|
||||
Variants::basic(part2)
|
||||
fn part2() -> helper::Variants {
|
||||
part2_variants!(construct_variants)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,3 +138,5 @@ helper::tests! {
|
|||
default => 81939900;
|
||||
}
|
||||
}
|
||||
|
||||
helper::benchmarks! {}
|
||||
3
2023/day3/src/mainrs
Normal file
3
2023/day3/src/mainrs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
day3::main();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue