aoc/util/
slice.rs

1//! Extension methods for slices.
2//!
3//! # Methods
4//!
5//! [`permutations`]
6//!
7//! Generates all possible permutations of a mutable slice, passing them one at a time to a
8//! callback function.
9//! Uses [Heap's algorithm](https://en.wikipedia.org/wiki/Heap%27s_algorithm) for efficiency,
10//! modifying the slice in place.
11//!
12//! [`fold_decimal`]
13//!
14//! Accumulates a slice of digits from 0 to 9 inclusive into a single integer.
15//!
16//! [`permutations`]: SliceOps::permutations
17//! [`fold_decimal`]: SliceOps2::fold_decimal
18use super::integer::*;
19
20pub trait SliceOps<T> {
21    fn permutations(self, callback: impl FnMut(&[T]));
22}
23
24impl<T> SliceOps<T> for &mut [T] {
25    fn permutations(self, mut callback: impl FnMut(&[T])) {
26        callback(self);
27
28        let n = self.len();
29        let mut c = vec![0; n];
30        let mut i = 1;
31
32        while i < n {
33            if c[i] < i {
34                if i % 2 == 0 {
35                    self.swap(0, i);
36                } else {
37                    self.swap(c[i], i);
38                }
39                callback(self);
40                c[i] += 1;
41                i = 1;
42            } else {
43                c[i] = 0;
44                i += 1;
45            }
46        }
47    }
48}
49
50pub trait SliceOps2<T: Integer<T>> {
51    /// Folds a slice of digits into an integer.
52    fn fold_decimal(self) -> T;
53}
54
55impl<T: Integer<T>> SliceOps2<T> for &[T] {
56    #[inline]
57    fn fold_decimal(self) -> T {
58        self.iter().fold(T::ZERO, |acc, &b| T::TEN * acc + b)
59    }
60}