Skip to content

Instantly share code, notes, and snippets.

@proegssilb
Last active December 12, 2022 04:39
Show Gist options
  • Save proegssilb/f7a3de005f54e3ffada8f4632e4dc577 to your computer and use it in GitHub Desktop.
Save proegssilb/f7a3de005f54e3ffada8f4632e4dc577 to your computer and use it in GitHub Desktop.
Test AOC Binary-Per-Year Program
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();
}
## 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