permutation_generator/single_permutation/
single_permutation_32.rs1use 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}