Skip to main content

aoc/year2024/
day05.rs

1//! # Print Queue
2//!
3//! The input is constructed so that each possible pair that occurs in a row has a defined
4//! ordering that enables sorting with a custom `Ordering` definition. Numbers are always
5//! 2 digits so storing ordering in a fixed-size 100 × 100 array is faster than using a `HashMap`.
6use std::cmp::Ordering::*;
7
8use crate::util::iter::*;
9use crate::util::parse::*;
10
11type Input = (usize, usize);
12
13pub fn parse(input: &str) -> Input {
14    let (prefix, suffix) = input.split_once("\n\n").unwrap();
15    let mut order = [[Greater; 100]; 100];
16
17    for [from, to] in prefix.iter_unsigned::<usize>().chunk::<2>() {
18        order[from][to] = Less;
19    }
20
21    let mut update = Vec::new();
22    let mut part_one = 0;
23    let mut part_two = 0;
24
25    for line in suffix.lines() {
26        update.clear();
27        update.extend(line.iter_unsigned::<usize>());
28        let middle = update.len() / 2;
29
30        if update.is_sorted_by(|&from, &to| order[from][to] == Less) {
31            part_one += update[middle];
32        } else {
33            // We only need the middle index so this is slightly faster than "sort_unstable_by"
34            update.select_nth_unstable_by(middle, |&from, &to| order[from][to]);
35            part_two += update[middle];
36        }
37    }
38
39    (part_one, part_two)
40}
41
42pub fn part1(input: &Input) -> usize {
43    input.0
44}
45
46pub fn part2(input: &Input) -> usize {
47    input.1
48}