mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 17:45:02 +01:00
more part2 opts
This commit is contained in:
parent
d08e7d8c7c
commit
b7db57a568
7 changed files with 814 additions and 3 deletions
|
|
@ -1,7 +1,9 @@
|
|||
mod p2basic;
|
||||
mod p2bytes;
|
||||
mod p2faster_hash;
|
||||
mod p2less_alloc;
|
||||
mod p2less_with_capacity;
|
||||
mod p2less_branching;
|
||||
mod p2with_capacity;
|
||||
|
||||
use helper::Day;
|
||||
|
||||
|
|
@ -19,8 +21,10 @@ helper::define_variants! {
|
|||
part2 {
|
||||
basic => crate::p2basic::part2;
|
||||
faster_hash => crate::p2faster_hash::part2;
|
||||
p2less_with_capacity => crate::p2less_with_capacity::part2;
|
||||
with_capacity => crate::p2with_capacity::part2;
|
||||
less_alloc => crate::p2less_alloc::part2;
|
||||
less_branching => crate::p2less_branching::part2;
|
||||
bytes => crate::p2bytes::part2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
102
2023/day03/src/p2bytes.rs
Normal file
102
2023/day03/src/p2bytes.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use std::hash::BuildHasherDefault;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct GearRatio(u64, u8);
|
||||
|
||||
impl Default for GearRatio {
|
||||
fn default() -> Self {
|
||||
Self(1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl GearRatio {
|
||||
fn push(&mut self, value: u64) {
|
||||
self.0 *= value;
|
||||
self.1 += 1;
|
||||
}
|
||||
fn get(&self) -> Option<u64> {
|
||||
(self.1 == 2).then_some(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[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.bytes().position(|c| !c.is_ascii_digit() && c != b'.')
|
||||
}
|
||||
|
||||
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::with_capacity_and_hasher(1000, BuildHasherDefault::default());
|
||||
|
||||
for (line_number, next) in input
|
||||
.lines()
|
||||
.skip(1)
|
||||
.chain(Some(empty_border.as_str()))
|
||||
.enumerate()
|
||||
{
|
||||
let mut numbers = prev1.bytes().enumerate().peekable();
|
||||
while let Some((start, c)) = numbers.next() {
|
||||
if c.is_ascii_digit() {
|
||||
let mut end = start;
|
||||
while let Some((idx, b'0'..=b'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()
|
||||
}
|
||||
102
2023/day03/src/p2less_branching.rs
Normal file
102
2023/day03/src/p2less_branching.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use std::hash::BuildHasherDefault;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct GearRatio(u64, u8);
|
||||
|
||||
impl Default for GearRatio {
|
||||
fn default() -> Self {
|
||||
Self(1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl GearRatio {
|
||||
fn push(&mut self, value: u64) {
|
||||
self.0 *= value;
|
||||
self.1 += 1;
|
||||
}
|
||||
fn get(&self) -> Option<u64> {
|
||||
(self.1 == 2).then_some(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[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::with_capacity_and_hasher(1000, BuildHasherDefault::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()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue