aoc/year2025/
day02.rs

1//! # Gift Shop
2use crate::util::iter::*;
3use crate::util::parse::*;
4
5type Range = [u32; 2];
6type Pair = [u64; 2];
7
8const FIRST: [Range; 5] = [[2, 1], [4, 2], [6, 3], [8, 4], [10, 5]];
9const SECOND: [Range; 6] = [[3, 1], [5, 1], [6, 2], [7, 1], [9, 3], [10, 2]];
10const THIRD: [Range; 2] = [[6, 1], [10, 1]];
11
12pub fn parse(input: &str) -> Vec<Pair> {
13    input.iter_unsigned::<u64>().chunk::<2>().collect()
14}
15
16pub fn part1(input: &[Pair]) -> u64 {
17    sum(&FIRST, input)
18}
19
20pub fn part2(input: &[Pair]) -> u64 {
21    sum(&FIRST, input) + sum(&SECOND, input) - sum(&THIRD, input)
22}
23
24fn sum(ranges: &[Range], input: &[Pair]) -> u64 {
25    let mut result = 0;
26
27    for &[digits, size] in ranges {
28        let digits_power = 10_u64.pow(digits);
29        let size_power = 10_u64.pow(size);
30
31        let step = (digits_power - 1) / (size_power - 1);
32        let start = step * (size_power / 10);
33        let end = step * (size_power - 1);
34
35        for &[from, to] in input {
36            let lower = from.next_multiple_of(step).max(start);
37            let upper = to.min(end);
38
39            if lower <= upper {
40                let n = (upper - lower) / step;
41                let triangular = n * (n + 1) / 2;
42                result += lower * (n + 1) + step * triangular;
43            }
44        }
45    }
46
47    result
48}