Last active
December 12, 2022 04:39
-
-
Save proegssilb/f7a3de005f54e3ffada8f4632e4dc577 to your computer and use it in GitHub Desktop.
Test AOC Binary-Per-Year Program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate microbench; | |
use std::{cmp::Ordering, time::Duration}; | |
// use criterion::{Criterion, criterion_group, criterion_main, black_box, PlottingBackend}; | |
// use pprof::criterion::{PProfProfiler, Output}; | |
// use pprof::flamegraph::Options as FGOptions; | |
use microbench::{Options, retain, bench}; | |
type DataLine = (u16, u16, u16, u16); | |
type DataLine2 = u64; | |
// Generators ------------------------------------------------------- | |
//#[parser(day4, parse)] | |
pub fn input_generator_tuple_parse(input: &str) -> Vec<DataLine> { | |
let mut results: Vec<DataLine> = Vec::new(); | |
for line in input.lines() { | |
let (s1, rest) = line.split_once('-').unwrap(); | |
let (e1, rest) = rest.split_once(',').unwrap(); | |
let (s2, e2) = rest.split_once('-').unwrap(); | |
results.push(( | |
s1.parse().unwrap(), | |
e1.parse().unwrap(), | |
s2.parse().unwrap(), | |
e2.parse().unwrap(), | |
)) | |
} | |
results | |
} | |
fn str_to_uint(s: &str) -> u16 { | |
let byes = s.as_bytes(); | |
match s.len() { | |
1 => u16::from_be_bytes([0, byes[0]]), | |
2 => u16::from_be_bytes([byes[0], byes[1]]), | |
_ => panic!("Inappropriately sized item found: {}", s), | |
} | |
} | |
pub fn u16_to_u64_array_assign(xs: &[u16; 4]) -> u64 { | |
let [a, b] = xs[0].to_be_bytes(); | |
let [c, d] = xs[1].to_be_bytes(); | |
let [e, f] = xs[2].to_be_bytes(); | |
let [g, h] = xs[3].to_be_bytes(); | |
u64::from_be_bytes([a, b, c, d, e, f, g, h]) | |
} | |
//#[parser(day4, tuple_bits)] | |
pub fn input_generator_tuple_bitbang(input: &str) -> Vec<DataLine> { | |
let mut results: Vec<DataLine> = Vec::new(); | |
for line in input.lines() { | |
let (s1, rest) = line.split_once('-').unwrap(); | |
let (e1, rest) = rest.split_once(',').unwrap(); | |
let (s2, e2) = rest.split_once('-').unwrap(); | |
results.push(( | |
str_to_uint(s1), | |
str_to_uint(e1), | |
str_to_uint(s2), | |
str_to_uint(e2), | |
)) | |
} | |
results | |
} | |
//#[parser(day4, uint_bits)] | |
pub fn input_generator_u64_bitbang(input: &str) -> Vec<DataLine2> { | |
let mut results: Vec<DataLine2> = Vec::new(); | |
for line in input.lines() { | |
let (s1, rest) = line.split_once('-').unwrap(); | |
let (e1, rest) = rest.split_once(',').unwrap(); | |
let (s2, e2) = rest.split_once('-').unwrap(); | |
let s1 = str_to_uint(s1); | |
let e1 = str_to_uint(e1); | |
let s2 = str_to_uint(s2); | |
let e2 = str_to_uint(e2); | |
results.push(u16_to_u64_array_assign(&[s1, e1, s2, e2])); | |
} | |
results | |
} | |
// Solutions -------------------------------------------------------- | |
//#[solver(day4, part1, tuplecmp)] | |
pub fn solve_part1_tuple_cmp(input: &[DataLine]) -> i32 { | |
input.iter().map(|dl| { | |
let (a_s, a_e, b_s, b_e) = dl; | |
let cmp1 = a_s.cmp(b_s); | |
let cmp2 = a_e.cmp(b_e); | |
let res = cmp1 != cmp2 || cmp1 == Ordering::Equal; | |
res as i32 | |
}).sum() | |
} | |
//#[solver(day4, part1, uintcmp)] | |
pub fn solve_part1_uint_cmp(input: &[DataLine2]) -> i32 { | |
input.iter().map(|dl| { | |
let [a, b, c, d, e, f, g, h] = dl.to_be_bytes(); | |
let (a_s, a_e, b_s, b_e) = ( | |
u16::from_be_bytes([a, b]), | |
u16::from_be_bytes([c, d]), | |
u16::from_be_bytes([e, f]), | |
u16::from_be_bytes([g, h]), | |
); | |
let cmp1 = a_s.cmp(&b_s); | |
let cmp2 = a_e.cmp(&b_e); | |
let res = cmp1 != cmp2 || cmp1 == Ordering::Equal; | |
res as i32 | |
}).sum() | |
} | |
//#[solver(day4, part1, tuplebits)] | |
pub fn solve_part1_tuple_bitbang(input: &[DataLine]) -> i32 { | |
input.iter().map(|dl| { | |
let (a_s, a_e, b_s, b_e) = dl; | |
let cmp1 = ((*a_s as i32) - (*b_s as i32)).signum(); | |
let cmp2 = ((*a_e as i32) - (*b_e as i32)).signum(); | |
let res = cmp1 != cmp2 || cmp1 == 0; | |
res as i32 | |
}).sum() | |
} | |
//#[solver(day4, part2, tuplecmp)] | |
pub fn solve_part2_tuple_cmp(input: &[DataLine]) -> i32 { | |
input.iter().map(|dl| { | |
let (a_s, a_e, b_s, b_e) = dl; | |
let res = !(a_e < b_s || b_e < a_s); | |
res as i32 | |
}).sum() | |
} | |
//#[solver(day4, part2, uintcmp)] | |
pub fn solve_part2_uint_cmp(input: &[DataLine2]) -> i32 { | |
input.iter().map(|dl| { | |
let [a, b, c, d, e, f, g, h] = dl.to_be_bytes(); | |
let (a_s, a_e, b_s, b_e) = ( | |
u16::from_be_bytes([a, b]), | |
u16::from_be_bytes([c, d]), | |
u16::from_be_bytes([e, f]), | |
u16::from_be_bytes([g, h]), | |
); | |
let res = !(a_e < b_s || b_e < a_s); | |
res as i32 | |
}).sum() | |
} | |
// Auto-generated section | |
fn p1_1(input: &str) -> i32 { | |
solve_part1_tuple_cmp(&input_generator_tuple_parse(input)) | |
} | |
fn p1_2(input: &str) -> i32 { | |
solve_part1_tuple_bitbang(&input_generator_tuple_parse(input)) | |
} | |
fn p1_3(input: &str) -> i32 { | |
solve_part1_tuple_cmp(&input_generator_tuple_bitbang(input)) | |
} | |
fn p1_4(input: &str) -> i32 { | |
solve_part1_tuple_bitbang(&input_generator_tuple_bitbang(input)) | |
} | |
fn p1_5(input: &str) -> i32 { | |
solve_part1_uint_cmp(&input_generator_u64_bitbang(input)) | |
} | |
fn p2_1(input: &str) -> i32 { | |
solve_part2_tuple_cmp(&input_generator_tuple_bitbang(input)) | |
} | |
fn p2_2(input: &str) -> i32 { | |
solve_part2_uint_cmp(&input_generator_u64_bitbang(input)) | |
} | |
const P1S: [for<'r> fn(&'r str) -> i32; 5] = [p1_1, p1_2, p1_3, p1_4, p1_5]; | |
const P2S: [for<'r> fn(&'r str) -> i32; 2] = [p2_1, p2_2]; | |
// Testing ---------------------------------------------------------- | |
/* User-supplied Test: | |
#[aoc_test(Part1)] | |
fn aoc_test(p1: F) | |
where F: Fn(&str) -> impl Into<i32> | |
{ | |
assert_eq!(2i32, p1(sample_in1)); | |
} | |
#[aoc_test(Part2)] | |
fn aoc_test(p2: F) | |
where F: Fn(&str) -> impl Into<i32> | |
{ | |
assert_eq!(4i32, p2(sample_in1)); | |
} | |
*/ | |
// User should supply this | |
#[allow(unused)] | |
const SAMPLE_IN1: &str = r#"2-4,6-8 | |
2-3,4-5 | |
5-7,7-9 | |
2-8,3-7 | |
6-6,4-6 | |
2-6,4-8 | |
"#; | |
// Auto-generated Result (ideally): | |
#[test] | |
fn aoc_test() { | |
for p1 in P1S { | |
assert_eq!(2i32, p1(SAMPLE_IN1)); | |
} | |
for p2 in P2S { | |
assert_eq!(4i32, p2(SAMPLE_IN1)); | |
} | |
} | |
// Auto-Genned Benches ---------------------------------------------- | |
// Microbench | |
fn run_benches() { | |
let options = Options::default().time(Duration::from_secs(5)); | |
bench(&options, "Part 1 - tuple_parse / tuple_cmp", || p1_1(retain(AOC_RAW_INPUT)) ); | |
bench(&options, "Part 1 - tuple_parse / tuple_bitbang", || p1_2(retain(AOC_RAW_INPUT)) ); | |
bench(&options, "Part 1 - tuple_bitbang / tuple_bitbang", || p1_4(retain(AOC_RAW_INPUT)) ); | |
bench(&options, "Part 1 - uint_bitbang / uint_cmp", || p1_5(retain(AOC_RAW_INPUT)) ); | |
bench(&options, "Part 2 - tuple_bitbang / tuple_cmp", || p2_1(retain(AOC_RAW_INPUT)) ); | |
bench(&options, "Part 2 - uint_bitbang / uint_cmp", || p2_2(retain(AOC_RAW_INPUT)) ); | |
} | |
// Criterion | |
// fn bench(c: &mut Criterion) { | |
// let mut group1 = c.benchmark_group("Part 1"); | |
// group1.bench_function("tuple_parse/tuple_cmp", |b| b.iter(|| p1_1(black_box(AOC_RAW_INPUT)))); | |
// group1.bench_function("tuple_parse/tuple_bitbang", |b| b.iter(|| p1_2(black_box(AOC_RAW_INPUT)))); | |
// group1.bench_function("tuple_bitbang/tuple_bitbang", |b| b.iter(|| p1_4(black_box(AOC_RAW_INPUT)))); | |
// group1.bench_function("uint_bitbang/uint_cmp", |b| b.iter(|| p1_5(black_box(AOC_RAW_INPUT)))); | |
// group1.finish(); | |
// let mut group2 = c.benchmark_group("Part 2"); | |
// group2.bench_function("tuple_bitbang / tuple_cmp", |b| b.iter(|| p2_1(black_box(AOC_RAW_INPUT)))); | |
// group2.bench_function("uint_bitbang / uint_cmp", |b| b.iter(|| p2_2(black_box(AOC_RAW_INPUT)))); | |
// group2.finish(); | |
// } | |
// criterion_group! { | |
// name = benches; | |
// config = Criterion::default() | |
// //.with_profiler(PProfProfiler::new(100, Output::Flamegraph(Some(FGOptions::default())))) | |
// .with_output_color(true) | |
// .with_plots() | |
// .plotting_backend(PlottingBackend::Plotters); | |
// targets = bench | |
// } | |
// criterion_main!(benches); | |
// Auto-Genned Main ------------------------------------------------ | |
const AOC_RAW_INPUT: &str = include_str!("../input/2022/4.txt"); | |
fn main() { | |
println!("## AOC 2022, Day 4 ----------"); | |
let solution_p1 = P1S[0](AOC_RAW_INPUT); | |
println!("Part 1 / parse Solution: {}", solution_p1); | |
let solution_p2 = P2S[0](AOC_RAW_INPUT); | |
println!("Part 2 / parse Solution: {}", solution_p2); | |
println!("Checking alternative solutions..."); | |
for (idx, solver) in P1S.iter().enumerate().skip(1) { | |
let solution = solver(AOC_RAW_INPUT); | |
if solution == solution_p1 { | |
print!("✅"); | |
} else { | |
println!(""); | |
println!("Solver dispute: #{} found {}", idx, solution); | |
} | |
} | |
for (idx, solver) in P2S.iter().enumerate().skip(1) { | |
let solution = solver(AOC_RAW_INPUT); | |
if solution == solution_p2 { | |
print!("✅"); | |
} else { | |
println!(""); | |
println!("Solver dispute: #{} found {}", idx, solution); | |
} | |
} | |
println!(""); | |
println!(" ---- Benches ----- "); | |
run_benches(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## AOC 2022, Day 4 ---------- | |
Part 1 / parse Solution: 305 | |
Part 2 / parse Solution: 811 | |
Checking alternative solutions... | |
✅✅✅✅✅ | |
---- Benches ----- | |
Part 1 - tuple_parse / tuple_cmp (5.1s) ... 428_638.846 ns/iter (0.997 R²) | |
Part 1 - tuple_parse / tuple_bitbang (5.0s) ... 416_454.694 ns/iter (1.000 R²) | |
Part 1 - tuple_bitbang / tuple_bitbang (5.1s) ... 484_888.807 ns/iter (1.000 R²) | |
Part 1 - uint_bitbang / uint_cmp (5.0s) ... 618_806.683 ns/iter (0.999 R²) | |
Part 2 - tuple_bitbang / tuple_cmp (5.0s) ... 495_858.733 ns/iter (0.999 R²) | |
Part 2 - uint_bitbang / uint_cmp (5.0s) ... 611_008.860 ns/iter (0.999 R²) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment