Advent of Code solutions
1use core::ops::Range;
2use std::{collections::HashMap, hash::Hash};
3
4pub fn counts<T: Hash + Eq + PartialEq>(l: impl Iterator<Item = T>) -> HashMap<T, u64> {
5 let (min, max) = l.size_hint();
6 l.fold(
7 HashMap::with_capacity(max.unwrap_or(min)),
8 |mut agg, curr| {
9 agg.entry(curr).and_modify(|x| *x += 1).or_insert(1);
10 agg
11 },
12 )
13}
14
15#[derive(Debug, Eq, PartialEq, Clone, Copy)]
16pub enum FollowRangeResult {
17 InvalidPair(i64, i64),
18 Increasing,
19 Decreasing,
20 Fluctuates,
21 ListTooShort
22}
23
24pub fn follows_diff_range(l: &[i64], diff_range: Range<i64>, enforce_one_way: bool, allow_eq: bool) -> FollowRangeResult {
25 if l.len() < 2 {
26 FollowRangeResult::ListTooShort
27 } else {
28 let first_diff = l[1] - l[0];
29 if diff_range.contains(&first_diff) {
30 let mut ordering = FollowRangeResult::Fluctuates;
31
32 let failing_pair = l.windows(2).skip(1).find_map(|w| {
33 let (x, y) = (w[0], w[1]);
34 let diff = y - x;
35 if diff_range.contains(&diff) && (allow_eq || diff != 0) {
36 if ordering == FollowRangeResult::Fluctuates && diff != 0 {
37 ordering = if diff < 0 { FollowRangeResult::Decreasing } else { FollowRangeResult::Increasing };
38 None
39 } else if enforce_one_way && (ordering == FollowRangeResult::Increasing && diff < 0) || (ordering == FollowRangeResult::Decreasing && diff > 0) {
40 Some((x, y))
41 } else {
42 None
43 }
44 } else {
45 Some((x, y))
46 }
47 });
48
49 match failing_pair {
50 Some((x, y)) => FollowRangeResult::InvalidPair(x, y),
51 None => ordering
52 }
53 } else {
54 FollowRangeResult::InvalidPair(l[0], l[1])
55 }
56 }
57}
58
59pub fn all_combos_remove_one<T>(l: &[T]) -> impl Iterator<Item = impl Iterator<Item = &T>> {
60 (0..l.len()).map(|exclude| {
61 l.iter().enumerate().filter_map(move |(i, e)| Some(e).filter(|_| i != exclude))
62 })
63}