mirror of
https://github.com/javalsai/aoc.git
synced 2026-01-13 01:19:59 +01:00
add: d05 & debug utils
- includes a script to generate a 2GB big challenge - added utils to internally time functions with minimal overhead - add functionality to tester.rs
This commit is contained in:
88
2025/05/p1-opt3.rs
Normal file
88
2025/05/p1-opt3.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub type RangeU = u128;
|
||||
pub type NestingCountT = i16;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub static mut TIMERS: [(&str, Duration); TIMERS_LEN] = [
|
||||
("after-parse", Duration::ZERO),
|
||||
("flatten-vec", Duration::ZERO),
|
||||
("count-ids", Duration::ZERO),
|
||||
];
|
||||
#[unsafe(no_mangle)]
|
||||
pub static TIMERS_LEN: usize = 3;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "Rust" fn challenge_t_usize(buf: &[u8], t: &Instant) -> usize {
|
||||
let mut count = 0;
|
||||
let s = unsafe { str::from_utf8_unchecked(buf) };
|
||||
let mut lines = s.lines();
|
||||
|
||||
let mut bmap = BTreeMap::<_, NestingCountT>::new();
|
||||
|
||||
(&mut lines)
|
||||
.take_while(|ln| !ln.is_empty())
|
||||
.for_each(|range| {
|
||||
let (l, r) = range.split_once('-').unwrap();
|
||||
let (l, r) = (l.parse().unwrap(), r.parse().unwrap());
|
||||
|
||||
bmap.entry(l).and_modify(|k| *k += 1).or_insert(1);
|
||||
bmap.entry(r).and_modify(|k| *k -= 1).or_insert(-1);
|
||||
});
|
||||
|
||||
unsafe { TIMERS[0].1 = t.elapsed() };
|
||||
|
||||
let mut arr = Vec::with_capacity(size_of::<bool>() * bmap.len());
|
||||
// I could directly search on the btree, but I feel flattening at once and then searching can
|
||||
// speed up things bcs continuity indirection and stuff. It also makes it easier to iterate at
|
||||
// once. This would be O(n) and the latter access in O(log n) (O(n log n) bcs it iterates for
|
||||
// each id)
|
||||
let mut last_pushed = false;
|
||||
let mut nested_ran_acc = 0;
|
||||
for (idx, nesting) in bmap {
|
||||
nested_ran_acc += nesting;
|
||||
if last_pushed != (nested_ran_acc > 0) {
|
||||
last_pushed = !last_pushed;
|
||||
arr.push((idx, last_pushed));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { TIMERS[1].1 = t.elapsed() };
|
||||
|
||||
let all_ranges_bounds = (arr[0].0, arr[arr.len() - 1].0);
|
||||
for id in lines {
|
||||
let id: RangeU = id.parse().unwrap();
|
||||
if id < all_ranges_bounds.0 || id > all_ranges_bounds.1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// let idx = arr.binary_search_by_key(&id, |p| p.0).err(|i| i);
|
||||
// let is_in_any_range = arr.get(idx).map(|p| p.1).unwrap();
|
||||
let is_in_any_range = binary_search_inclusive_or_lower_bound(&arr, id);
|
||||
|
||||
if is_in_any_range {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { TIMERS[2].1 = t.elapsed() };
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
fn binary_search_inclusive_or_lower_bound(arr: &[(RangeU, bool)], id: RangeU) -> bool {
|
||||
let all_ranges_bounds = (arr[0].0, arr[arr.len() - 1].0);
|
||||
|
||||
if id < all_ranges_bounds.0 || id > all_ranges_bounds.1 {
|
||||
return false;
|
||||
}
|
||||
|
||||
match arr.binary_search_by_key(&id, |p| p.0) {
|
||||
Ok(_) => true, // the rising edge is true and if falling edge its false but included so
|
||||
// should get truthed. In general if its found it was an edge so return true
|
||||
Err(idx) => arr[idx - 1].1,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user