This commit is contained in:
nora 2024-12-01 14:34:00 +01:00
parent 1b194e4f1c
commit 9b527751a1
2 changed files with 69 additions and 20 deletions

View file

@ -21,6 +21,7 @@ helper::define_variants! {
faster_parsing => crate::part2_parsing;
array => crate::part2_array;
μopt_parsing => crate::part2_μopt_parsing;
part2_bytes => crate::part2_bytes;
}
}
@ -177,42 +178,90 @@ fn part2_array(input: &str) -> u64 {
score
}
fn part2_μopt_parsing(input: &str) -> u64 {
assert_eq!(input.as_bytes().last(), Some(&b'\n'));
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 left = Vec::with_capacity(input.len());
let digit_len = input.as_bytes().iter().position(|b| *b == b' ').unwrap();
let line_len = 2 * digit_len + 3 + 1;
fn parse_digit(input: &str, len: usize) -> u64 {
let mut result = 0;
for i in 0..len {
result *= 10;
result += (input.as_bytes()[i] - b'0') as u64;
}
result
}
let mut input = input;
loop {
let Some(space) = input.as_bytes().iter().position(|b| *b == b' ') else {
break;
};
let number = input[..space].parse::<u64>().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::<u64>().unwrap();
while input.len() >= line_len {
let number = parse_digit(input, digit_len);
left.push(number as u32);
input = &input[(digit_len + 3)..];
let number = parse_digit(input, digit_len);
right_map[number as usize] += 1;
input = &input[newline..];
// handle lack of trailing newline
if !input.is_empty() {
input = &input[1..];
}
input = &input[digit_len..];
input = &input[1..];
}
let mut score = 0;
for number in left {
let occurs = right_map[number as usize];
score += number * (occurs as u64);
score += (number as u64) * (occurs as u64);
}
score
}
fn part2_bytes(input: &str) -> u64 {
let input = input.as_bytes();
assert_eq!(input.last(), Some(&b'\n'));
const BIGGEST_ELEMENT: usize = 100_000;
let mut right_map = vec![0_u16; BIGGEST_ELEMENT];
let mut left = Vec::<u32>::with_capacity(input.len());
let digit_len = input.iter().position(|b| *b == b' ').unwrap();
let line_len = 2 * digit_len + 3 + 1;
fn parse_digit(input: &[u8], len: usize) -> u32 {
let mut result = 0;
for i in 0..len {
result *= 10;
result += (unsafe { input.get_unchecked(i) } - b'0') as u32;
}
result
}
let mut input = input;
while input.len() >= line_len {
let number = parse_digit(input, digit_len);
left.push(number);
input = unsafe { &input.get_unchecked((digit_len + 3)..) };
let number = parse_digit(input, digit_len);
right_map[number as usize] += 1;
input = unsafe { &input.get_unchecked((digit_len + 1)..) };
}
let mut score = 0;
for number in left {
let occurs = right_map[number as usize];
score += number * (occurs as u32);
}
score as u64
}
helper::tests! {
day01 Day01;
part1 {