|
| 1 | +//! # Gift Shop |
| 2 | +use crate::util::iter::*; |
| 3 | +use crate::util::parse::*; |
| 4 | + |
| 5 | +type Pair = [usize; 2]; |
| 6 | + |
| 7 | +const FIRST: [Pair; 5] = [[2, 1], [4, 2], [6, 3], [8, 4], [10, 5]]; |
| 8 | +const SECOND: [Pair; 6] = [[3, 1], [5, 1], [6, 2], [7, 1], [9, 3], [10, 2]]; |
| 9 | +const THIRD: [Pair; 2] = [[6, 1], [10, 1]]; |
| 10 | + |
| 11 | +pub fn parse(input: &str) -> Pair { |
| 12 | + let ranges: Vec<_> = input.iter_unsigned::<usize>().chunk::<2>().collect(); |
| 13 | + let first = sum(&FIRST, &ranges); |
| 14 | + let second = sum(&SECOND, &ranges); |
| 15 | + let third = sum(&THIRD, &ranges); |
| 16 | + [first, first + second - third] |
| 17 | +} |
| 18 | + |
| 19 | +pub fn part1(input: &Pair) -> usize { |
| 20 | + input[0] |
| 21 | +} |
| 22 | + |
| 23 | +pub fn part2(input: &Pair) -> usize { |
| 24 | + input[1] |
| 25 | +} |
| 26 | + |
| 27 | +fn sum(ranges: &[Pair], ids: &[Pair]) -> usize { |
| 28 | + let mut result = 0; |
| 29 | + |
| 30 | + for &[digits, size] in ranges { |
| 31 | + let repeat = digits / size; |
| 32 | + let power = 10_usize.pow(size as u32); |
| 33 | + let factor = (0..repeat).fold(0, |acc, _| acc * power + 1); |
| 34 | + let start = factor * (power / 10); |
| 35 | + let end = factor * (power - 1); |
| 36 | + |
| 37 | + for &[from, to] in ids { |
| 38 | + let lower = from.next_multiple_of(factor).max(start); |
| 39 | + let upper = to.min(end); |
| 40 | + (lower..=upper).step_by(factor).for_each(|n| result += n); |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + result |
| 45 | +} |
0 commit comments