permutation_generator/single_permutation/
single_permutation_16.rs1use bit_index::BitIndex16;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub struct SinglePermutation16 {
5 elems: BitIndex16,
6 next_mod: u64,
7 current_idx: u64,
8}
9
10impl SinglePermutation16 {
11 #[must_use]
12 pub fn new(nb_elems: u8, nb_perms: u64, idx: u64) -> Option<Self> {
13 if idx >= nb_perms {
14 None
15 } else {
16 Some(Self {
17 elems: BitIndex16::new(nb_elems).unwrap(),
18 next_mod: nb_perms / u64::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 SinglePermutation16 {
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 /= u64::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::{SinglePermutation16, factorial::factorial64};
54
55 fn single_perm(nb_elems: u8, idx: u64) -> Option<SinglePermutation16> {
56 SinglePermutation16::new(nb_elems, factorial64(nb_elems), idx)
57 }
58
59 #[test]
60 fn new() {
61 assert_eq!(None, single_perm(10, 3_628_800));
62 }
63
64 #[test]
65 fn new_unchecked_iterator() {
66 assert_eq!(
67 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
68 single_perm(10, 0).unwrap().collect::<Vec<_>>().as_slice()
69 );
70
71 assert_eq!(
72 &[1, 0, 2, 3, 4, 5, 6, 7, 8, 9],
73 single_perm(10, 362_880).unwrap().collect::<Vec<_>>().as_slice()
74 );
75
76 assert_eq!(
77 &[2, 0, 1, 3, 4, 5, 6, 7, 8, 9],
78 single_perm(10, 362_880 * 2).unwrap().collect::<Vec<_>>().as_slice()
79 );
80
81 assert_eq!(
82 &[3, 0, 1, 2, 4, 5, 6, 7, 8, 9],
83 single_perm(10, 362_880 * 3).unwrap().collect::<Vec<_>>().as_slice()
84 );
85
86 assert_eq!(
87 &[9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
88 single_perm(10, 3_628_800 - 1).unwrap().collect::<Vec<_>>().as_slice()
89 );
90 }
91}