mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 17:45:02 +01:00
more optimization
This commit is contained in:
parent
485b24b202
commit
d47ca1f175
3 changed files with 114 additions and 4 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
mod p2faster_hash;
|
|
||||||
mod p2basic;
|
mod p2basic;
|
||||||
|
mod p2faster_hash;
|
||||||
|
mod p2less_alloc;
|
||||||
|
|
||||||
use helper::Day;
|
use helper::Day;
|
||||||
|
|
||||||
|
|
@ -16,7 +17,8 @@ helper::define_variants! {
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
basic => crate::p2basic::part2;
|
basic => crate::p2basic::part2;
|
||||||
fasher_hash => crate::p2faster_hash::part2;
|
faster_hash => crate::p2faster_hash::part2;
|
||||||
|
less_alloc => crate::p2less_alloc::part2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +73,6 @@ fn part1(input: &str) -> u64 {
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
helper::tests! {
|
helper::tests! {
|
||||||
day03 Day03;
|
day03 Day03;
|
||||||
part1 {
|
part1 {
|
||||||
|
|
|
||||||
109
2023/day03/src/p2less_alloc.rs
Normal file
109
2023/day03/src/p2less_alloc.rs
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
/// States:
|
||||||
|
/// - `=0`` -> 0 elements
|
||||||
|
/// - `>0, HIGH 0` -> 1 element
|
||||||
|
/// - `>0, HIGH 1` -> 2 elements
|
||||||
|
/// - `=MAX` -> >2 elements
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct GearRatio(u64);
|
||||||
|
|
||||||
|
const HIGH: u64 = 1 << 63;
|
||||||
|
impl GearRatio {
|
||||||
|
fn push(&mut self, value: u64) {
|
||||||
|
if self.0 == 0 {
|
||||||
|
self.0 = value;
|
||||||
|
} else if (self.0 & HIGH) == 0 {
|
||||||
|
self.0 *= value;
|
||||||
|
self.0 |= HIGH;
|
||||||
|
} else {
|
||||||
|
self.0 = u64::MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get(&self) -> Option<u64> {
|
||||||
|
if self.0 > 0 && self.0 != u64::MAX && (self.0 & HIGH) > 1 {
|
||||||
|
Some(self.0 & (HIGH - 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::GearRatio;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gear_ratio() {
|
||||||
|
let mut r = GearRatio::default();
|
||||||
|
assert_eq!(r.get(), None);
|
||||||
|
r.push(2);
|
||||||
|
assert_eq!(r.get(), None);
|
||||||
|
r.push(3);
|
||||||
|
eprintln!("{:b}", r.0);
|
||||||
|
assert_eq!(r.get(), Some(6));
|
||||||
|
r.push(1);
|
||||||
|
assert_eq!(r.get(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &str) -> u64 {
|
||||||
|
fn contains_gear(s: &str) -> Option<usize> {
|
||||||
|
s.chars().position(|c| !c.is_ascii_digit() && c != '.')
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = input.lines().next().unwrap().len();
|
||||||
|
let empty_border = std::iter::repeat('.').take(len).collect::<String>();
|
||||||
|
|
||||||
|
let mut prev2 = empty_border.as_str();
|
||||||
|
let mut prev1 = input.lines().next().unwrap();
|
||||||
|
|
||||||
|
let mut gears: FxHashMap<u32, GearRatio> = FxHashMap::default();
|
||||||
|
|
||||||
|
for (line_number, next) in input
|
||||||
|
.lines()
|
||||||
|
.skip(1)
|
||||||
|
.chain(Some(empty_border.as_str()))
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
let mut numbers = prev1.char_indices().peekable();
|
||||||
|
while let Some((start, c)) = numbers.next() {
|
||||||
|
if c.is_ascii_digit() {
|
||||||
|
let mut end = start;
|
||||||
|
while let Some((idx, '0'..='9')) = numbers.next() {
|
||||||
|
end = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
let box_bounds = (start.saturating_sub(1))..std::cmp::min(end + 2, len);
|
||||||
|
let number = prev1[start..=end].parse::<u64>().unwrap();
|
||||||
|
|
||||||
|
let mut push = |key: (usize, usize)| {
|
||||||
|
gears
|
||||||
|
.entry(((key.1 as u32) << 16) | (key.0 as u32))
|
||||||
|
.or_default()
|
||||||
|
.push(number)
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(position) = contains_gear(&prev2[box_bounds.clone()]) {
|
||||||
|
let key = (line_number - 1, box_bounds.start + position);
|
||||||
|
push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(position) = contains_gear(&prev1[box_bounds.clone()]) {
|
||||||
|
let key = (line_number, box_bounds.start + position);
|
||||||
|
push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(position) = contains_gear(&next[box_bounds.clone()]) {
|
||||||
|
let key = (line_number + 1, box_bounds.start + position);
|
||||||
|
push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev2 = prev1;
|
||||||
|
prev1 = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
gears.values().filter_map(|v| v.get()).sum()
|
||||||
|
}
|
||||||
|
|
@ -104,7 +104,7 @@ macro_rules! construct_variants {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! benchmarks {
|
macro_rules! benchmarks {
|
||||||
() => {
|
() => {
|
||||||
#[::divan::bench_group(sample_count = 1_000)]
|
#[::divan::bench_group(sample_count = 10_000)]
|
||||||
mod bench {
|
mod bench {
|
||||||
mod part1 {
|
mod part1 {
|
||||||
part1_variants! { _define_benchmarks }
|
part1_variants! { _define_benchmarks }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue