2023-12-28 12:35:58 -06:00
|
|
|
use aoc_runner_derive::{aoc, aoc_generator};
|
|
|
|
use itertools::Itertools;
|
|
|
|
|
2023-12-29 09:32:23 -06:00
|
|
|
const PREAMBLE_LEN: usize = 5;
|
2023-12-28 12:35:58 -06:00
|
|
|
|
|
|
|
#[aoc_generator(day9)]
|
|
|
|
fn parse(input: &str) -> Vec<u64> {
|
|
|
|
input.lines().map(str::parse).map(Result::unwrap).collect_vec()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day9, part1)]
|
|
|
|
fn part1(input: &Vec<u64>) -> u64 {
|
|
|
|
for i in PREAMBLE_LEN..input.len() {
|
|
|
|
if let None = input[i - PREAMBLE_LEN..i]
|
|
|
|
.iter()
|
|
|
|
.combinations(2)
|
|
|
|
.find(|x| x.iter().cloned().sum::<u64>() == input[i]) {
|
|
|
|
return input[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day9, part2)]
|
|
|
|
fn part2(input: &Vec<u64>) -> u64 {
|
|
|
|
let to_find = part1(input);
|
|
|
|
|
|
|
|
for len in 2..input.len() {
|
|
|
|
if let Some(nums) = input
|
|
|
|
.windows(len)
|
|
|
|
.find(|x| x.iter().cloned().sum::<u64>() == to_find) {
|
|
|
|
return nums.iter().min().unwrap() + nums.iter().max().unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
const EX: &str = r"35
|
|
|
|
20
|
|
|
|
15
|
|
|
|
25
|
|
|
|
47
|
|
|
|
40
|
|
|
|
62
|
|
|
|
55
|
|
|
|
65
|
|
|
|
95
|
|
|
|
102
|
|
|
|
117
|
|
|
|
150
|
|
|
|
182
|
|
|
|
127
|
|
|
|
219
|
|
|
|
299
|
|
|
|
277
|
|
|
|
309
|
|
|
|
576";
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part1_example() {
|
|
|
|
assert_eq!(part1(&parse(EX)), 127);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part2_example() {
|
|
|
|
assert_eq!(part2(&parse(EX)), 62);
|
|
|
|
}
|
|
|
|
}
|