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(
25 l: &[i64],
26 diff_range: Range<i64>,
27 enforce_one_way: bool,
28 allow_eq: bool,
29) -> FollowRangeResult {
30 if l.len() < 2 {
31 FollowRangeResult::ListTooShort
32 } else {
33 let first_diff = l[1] - l[0];
34 if diff_range.contains(&first_diff) {
35 let mut ordering = FollowRangeResult::Fluctuates;
36
37 let failing_pair = l.windows(2).skip(1).find_map(|w| {
38 let (x, y) = (w[0], w[1]);
39 let diff = y - x;
40 if diff_range.contains(&diff) && (allow_eq || diff != 0) {
41 if ordering == FollowRangeResult::Fluctuates && diff != 0 {
42 ordering = if diff < 0 {
43 FollowRangeResult::Decreasing
44 } else {
45 FollowRangeResult::Increasing
46 };
47 None
48 } else if enforce_one_way
49 && (ordering == FollowRangeResult::Increasing && diff < 0)
50 || (ordering == FollowRangeResult::Decreasing && diff > 0)
51 {
52 Some((x, y))
53 } else {
54 None
55 }
56 } else {
57 Some((x, y))
58 }
59 });
60
61 match failing_pair {
62 Some((x, y)) => FollowRangeResult::InvalidPair(x, y),
63 None => ordering,
64 }
65 } else {
66 FollowRangeResult::InvalidPair(l[0], l[1])
67 }
68 }
69}
70
71pub fn all_combos_remove_one<T>(l: &[T]) -> impl Iterator<Item = impl Iterator<Item = &T>> {
72 (0..l.len()).map(|exclude| {
73 l.iter()
74 .enumerate()
75 .filter_map(move |(i, e)| Some(e).filter(|_| i != exclude))
76 })
77}