use aoc_runner_derive::{aoc, aoc_generator}; use nom::character::complete::multispace0; use nom::multi::many1; use nom::{character::complete::u64 as parse_u64, IResult}; #[aoc_generator(day1)] pub fn generator(input: &str) -> Vec<(u64, u64)> { many1(parse_line)(input).unwrap().1 } fn parse_line(input: &str) -> IResult<&str, (u64, u64)> { let (input, left) = parse_u64(input)?; let (input, _) = multispace0(input)?; let (input, right) = parse_u64(input)?; let (input, _) = multispace0(input)?; Ok((input, (left, right))) } #[aoc(day1, part1)] pub fn part1(input: &[(u64, u64)]) -> u64 { let (mut left, mut right): (Vec, Vec) = input.iter().copied().unzip(); left.sort(); right.sort(); left.iter() .zip(right.iter()) .map(|(l, r)| (*l).abs_diff(*r)) .sum() } #[aoc(day1, part2)] pub fn part2(input: &[(u64, u64)]) -> usize { let (mut left, mut right): (Vec, Vec) = input.iter().copied().unzip(); left.sort(); right.sort(); let mut l; let mut r = 0; let mut score = 0usize; for value in left { l = r; while l < right.len() && right[l] < value { l += 1 } r = l; while r < right.len() && right[r] <= value { r += 1 } score += (value as usize) * (r - l); if r == right.len() - 1 { break; }; } score }