permutation_generator/single_permutation/
single_permutation_32.rs

1use bit_index::BitIndex32;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub struct SinglePermutation32 {
5    elems:       BitIndex32,
6    next_mod:    u128,
7    current_idx: u128,
8}
9
10impl SinglePermutation32 {
11    #[must_use]
12    pub fn new(nb_elems: u8, nb_perms: u128, idx: u128) -> Option<Self> {
13        if idx >= nb_perms {
14            None
15        } else {
16            Some(Self {
17                elems:       BitIndex32::new(nb_elems).unwrap(),
18                next_mod:    nb_perms / u128::from(nb_elems),
19                current_idx: idx,
20            })
21        }
22    }
23
24    #[inline]
25    #[must_use]
26    pub fn nb_remaining(&self) -> usize { self.elems.nb_elements() as usize }
27}
28
29impl Iterator for SinglePermutation32 {
30    type Item = u8;
31
32    #[allow(clippy::cast_possible_truncation)]
33    fn next(&mut self) -> Option<Self::Item> {
34        if self.elems.nb_elements() == 0 {
35            return None;
36        }
37        let bit_nb = self.current_idx / self.next_mod;
38        self.current_idx -= bit_nb * self.next_mod;
39        self.next_mod /= u128::from(self.elems.nb_elements()).saturating_sub(2) + 1;
40        self.elems.pop(bit_nb as u8)
41    }
42
43    fn size_hint(&self) -> (usize, Option<usize>) {
44        let nb_remaining = self.nb_remaining();
45        (nb_remaining, Some(nb_remaining))
46    }
47
48    fn count(self) -> usize { self.nb_remaining() }
49}
50
51#[cfg(test)]
52mod tests {
53    use crate::{SinglePermutation32, factorial::factorial128};
54
55    fn single_perm(nb_elems: u8, idx: u128) -> Option<SinglePermutation32> {
56        SinglePermutation32::new(nb_elems, factorial128(nb_elems), idx)
57    }
58
59    #[test]
60    fn new() {
61        assert_eq!(None, single_perm(30, 265_252_859_812_191_058_636_308_480_000_000));
62    }
63
64    #[test]
65    fn new_unchecked_iterator() {
66        assert_eq!(
67            (0..30).collect::<Vec<_>>().as_slice(),
68            single_perm(30, 0).unwrap().collect::<Vec<_>>().as_slice()
69        );
70
71        assert_eq!(
72            (0..30).rev().collect::<Vec<_>>().as_slice(),
73            single_perm(30, 265_252_859_812_191_058_636_308_480_000_000 - 1)
74                .unwrap()
75                .collect::<Vec<_>>()
76                .as_slice()
77        );
78    }
79}