From 1b194e4f1c2e0cd87a772d317f41be14675cafbd Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:34:16 +0100 Subject: [PATCH] hi clubby --- 2024/Cargo.lock | 7 ++ 2024/day01/Cargo.toml | 1 + 2024/day01/src/lib.rs | 154 +++++++++++++++++++++++++++++++++++++++++- helper/src/hash.rs | 24 +++++++ helper/src/lib.rs | 2 + 5 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 helper/src/hash.rs diff --git a/2024/Cargo.lock b/2024/Cargo.lock index afa4d21..5375bd6 100644 --- a/2024/Cargo.lock +++ b/2024/Cargo.lock @@ -119,6 +119,7 @@ dependencies = [ "divan", "helper", "nom", + "rustc-hash", ] [[package]] @@ -229,6 +230,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + [[package]] name = "rustix" version = "0.38.41" diff --git a/2024/day01/Cargo.toml b/2024/day01/Cargo.toml index 778d525..fe76360 100644 --- a/2024/day01/Cargo.toml +++ b/2024/day01/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" nom.workspace = true helper.workspace = true divan.workspace = true +rustc-hash = "2.1.0" [[bench]] name = "benches" diff --git a/2024/day01/src/lib.rs b/2024/day01/src/lib.rs index dc05304..4ab6cc4 100644 --- a/2024/day01/src/lib.rs +++ b/2024/day01/src/lib.rs @@ -1,4 +1,7 @@ -use helper::{Day, IteratorExt, Variants}; +use std::{collections::HashMap, hash::BuildHasherDefault}; + +use helper::{Day, IteratorExt, NoHasher, Variants}; +use rustc_hash::FxHashMap; pub fn main() { helper::main::(include_str!("../input.txt")); @@ -13,6 +16,11 @@ helper::define_variants! { } part2 { basic => crate::part2; + hash => crate::part2_hash; + hash_no_hash => crate::part2_hash_nohash; + faster_parsing => crate::part2_parsing; + array => crate::part2_array; + μopt_parsing => crate::part2_μopt_parsing; } } @@ -61,6 +69,150 @@ fn part2(input: &str) -> u64 { score } +fn part2_hash(input: &str) -> u64 { + let (left, right) = parse(input); + + let mut right_map = FxHashMap::::default(); + for number in right { + *right_map.entry(number).or_default() += 1; + } + + let mut score = 0; + + for number in left { + let occurs = right_map.get(&number).copied().unwrap_or_default(); + score += number * (occurs as u64); + } + + score +} + +fn part2_hash_nohash(input: &str) -> u64 { + let (left, right) = parse(input); + + let mut right_map = HashMap::>::default(); + for number in right { + *right_map.entry(number).or_default() += 1; + } + + let mut score = 0; + + for number in left { + let occurs = right_map.get(&number).copied().unwrap_or_default(); + score += number * (occurs as u64); + } + + score +} + +fn part2_parsing(input: &str) -> u64 { + let mut right_map = FxHashMap::::with_capacity_and_hasher( + input.len() / 8, + rustc_hash::FxBuildHasher::default(), + ); + let mut left = Vec::with_capacity(input.len() / 8); + + let mut input = input; + loop { + let Some(space) = input.as_bytes().iter().position(|b| *b == b' ') else { + break; + }; + let number = input[..space].parse::().unwrap(); + left.push(number); + input = &input[(space + 3)..]; + let Some(newline) = input.as_bytes().iter().position(|b| *b == b'\n') else { + break; + }; + let number = input[..space].parse::().unwrap(); + *right_map.entry(number).or_default() += 1; + input = &input[newline..]; + // handle lack of trailing newline + if !input.is_empty() { + input = &input[1..]; + } + } + + let mut score = 0; + + for number in left { + let occurs = right_map.get(&number).copied().unwrap_or_default(); + score += number * (occurs as u64); + } + + score +} + +fn part2_array(input: &str) -> u64 { + const BIGGEST_ELEMENT: usize = 100_000; + let mut right_map = vec![0_u16; BIGGEST_ELEMENT]; + let mut left = Vec::with_capacity(input.len() / 8); + + let mut input = input; + loop { + let Some(space) = input.as_bytes().iter().position(|b| *b == b' ') else { + break; + }; + let number = input[..space].parse::().unwrap(); + left.push(number); + input = &input[(space + 3)..]; + let Some(newline) = input.as_bytes().iter().position(|b| *b == b'\n') else { + break; + }; + let number = input[..space].parse::().unwrap(); + right_map[number as usize] += 1; + input = &input[newline..]; + // handle lack of trailing newline + if !input.is_empty() { + input = &input[1..]; + } + } + + let mut score = 0; + + for number in left { + let occurs = right_map[number as usize]; + score += number * (occurs as u64); + } + + score +} + + +fn part2_μopt_parsing(input: &str) -> u64 { + const BIGGEST_ELEMENT: usize = 100_000; + let mut right_map = vec![0_u16; BIGGEST_ELEMENT]; + let mut left = Vec::with_capacity(input.len() / 8); + + let mut input = input; + loop { + let Some(space) = input.as_bytes().iter().position(|b| *b == b' ') else { + break; + }; + let number = input[..space].parse::().unwrap(); + left.push(number); + input = &input[(space + 3)..]; + let Some(newline) = input.as_bytes().iter().position(|b| *b == b'\n') else { + break; + }; + let number = input[..space].parse::().unwrap(); + right_map[number as usize] += 1; + input = &input[newline..]; + // handle lack of trailing newline + if !input.is_empty() { + input = &input[1..]; + } + } + + let mut score = 0; + + for number in left { + let occurs = right_map[number as usize]; + score += number * (occurs as u64); + } + + score +} + helper::tests! { day01 Day01; part1 { diff --git a/helper/src/hash.rs b/helper/src/hash.rs new file mode 100644 index 0000000..1c3e5a8 --- /dev/null +++ b/helper/src/hash.rs @@ -0,0 +1,24 @@ +use std::hash::Hasher; + +#[derive(Default)] +pub struct NoHasher { + value: u64, +} + +impl Hasher for NoHasher { + fn finish(&self) -> u64 { + self.value + } + + fn write_u32(&mut self, i: u32) { + self.value = i as u64; + } + + fn write_u64(&mut self, i: u64) { + self.value = i; + } + + fn write(&mut self, _: &[u8]) { + unimplemented!() + } +} diff --git a/helper/src/lib.rs b/helper/src/lib.rs index bca0934..c136a0d 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -1,10 +1,12 @@ mod cmd; mod ext; +mod hash; use std::{borrow::Cow, fmt::Debug}; pub use self::cmd::main; pub use self::ext::*; +pub use self::hash::*; pub type Solution = fn(&str) -> u64;