open_pql/prim/math/combinatorics/
perm_range_cond_idx.rs

1use std::sync::LazyLock;
2
3use itertools::Itertools;
4
5pub static PERM11: LazyLock<Vec<Vec<u8>>> =
6    LazyLock::new(|| (0..1).permutations(1).collect_vec());
7pub static PERM21: LazyLock<Vec<Vec<u8>>> =
8    LazyLock::new(|| (0..2).permutations(1).collect_vec());
9pub static PERM22: LazyLock<Vec<Vec<u8>>> =
10    LazyLock::new(|| (0..2).permutations(2).collect_vec());
11pub static PERM31: LazyLock<Vec<Vec<u8>>> =
12    LazyLock::new(|| (0..3).permutations(1).collect_vec());
13pub static PERM32: LazyLock<Vec<Vec<u8>>> =
14    LazyLock::new(|| (0..3).permutations(2).collect_vec());
15pub static PERM33: LazyLock<Vec<Vec<u8>>> =
16    LazyLock::new(|| (0..3).permutations(3).collect_vec());
17pub static PERM41: LazyLock<Vec<Vec<u8>>> =
18    LazyLock::new(|| (0..4).permutations(1).collect_vec());
19pub static PERM42: LazyLock<Vec<Vec<u8>>> =
20    LazyLock::new(|| (0..4).permutations(2).collect_vec());
21pub static PERM43: LazyLock<Vec<Vec<u8>>> =
22    LazyLock::new(|| (0..4).permutations(3).collect_vec());
23pub static PERM44: LazyLock<Vec<Vec<u8>>> =
24    LazyLock::new(|| (0..4).permutations(4).collect_vec());
25
26pub static PERM_BOARD_4: LazyLock<Vec<Vec<u8>>> = LazyLock::new(|| {
27    vec![
28        vec![0, 1, 2, 3],
29        vec![0, 2, 1, 3],
30        vec![1, 0, 2, 3],
31        vec![1, 2, 0, 3],
32        vec![2, 0, 1, 3],
33        vec![2, 1, 0, 3],
34    ]
35});
36
37pub static PERM_BOARD_5: LazyLock<Vec<Vec<u8>>> = LazyLock::new(|| {
38    vec![
39        vec![0, 1, 2, 3, 4],
40        vec![0, 2, 1, 3, 4],
41        vec![1, 0, 2, 3, 4],
42        vec![1, 2, 0, 3, 4],
43        vec![2, 0, 1, 3, 4],
44        vec![2, 1, 0, 3, 4],
45    ]
46});
47
48#[inline]
49pub fn range_cond_indices(
50    n: usize,
51    r: usize,
52    board: bool,
53) -> &'static Vec<Vec<u8>> {
54    match (n, r, board) {
55        (1, 1, false) => PERM11.as_ref(),
56
57        (2, 1, false) => PERM21.as_ref(),
58        (2, 2, false) => PERM22.as_ref(),
59
60        (3, 1, false) | (5, 1, true) => PERM31.as_ref(),
61        (3, 2, false) | (5, 2, true) => PERM32.as_ref(),
62        (3, 3, false) | (5, 3, true) => PERM33.as_ref(),
63
64        (4, 1, false) => PERM41.as_ref(),
65        (4, 2, false) => PERM42.as_ref(),
66        (4, 3, false) => PERM43.as_ref(),
67        (4, 4, false) => PERM44.as_ref(),
68
69        (5, 4, true) => PERM_BOARD_4.as_ref(),
70        (5, 5, true) => PERM_BOARD_5.as_ref(),
71
72        _ => unimplemented!("n={n}; r={r}; board: {board}"),
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use self::range_cond_indices as indices;
79    use super::*;
80
81    #[test]
82    fn test_indices() {
83        assert_eq!(*indices(1, 1, false), [[0]]);
84        assert_eq!(*indices(2, 1, false), [[0], [1]]);
85        assert_eq!(*indices(2, 2, false), [[0, 1], [1, 0]]);
86        assert_eq!(*indices(3, 1, false), [[0], [1], [2]]);
87        assert_eq!(indices(3, 2, false).len(), 6);
88        assert_eq!(indices(3, 3, false).len(), 6);
89        assert_eq!(*indices(4, 1, false), [[0], [1], [2], [3]]);
90        assert_eq!(indices(4, 2, false).len(), 12);
91        assert_eq!(indices(4, 3, false).len(), 24);
92        assert_eq!(indices(4, 4, false).len(), 24);
93    }
94
95    #[test]
96    fn test_indices_board() {
97        assert_eq!(*indices(5, 1, true), *indices(3, 1, false));
98        assert_eq!(*indices(5, 2, true), *indices(3, 2, false));
99        assert_eq!(*indices(5, 3, true), *indices(3, 3, false));
100        assert_eq!(
101            *indices(5, 4, true),
102            [
103                [0, 1, 2, 3],
104                [0, 2, 1, 3],
105                [1, 0, 2, 3],
106                [1, 2, 0, 3],
107                [2, 0, 1, 3],
108                [2, 1, 0, 3],
109            ]
110        );
111
112        assert_eq!(
113            *indices(5, 5, true),
114            [
115                [0, 1, 2, 3, 4],
116                [0, 2, 1, 3, 4],
117                [1, 0, 2, 3, 4],
118                [1, 2, 0, 3, 4],
119                [2, 0, 1, 3, 4],
120                [2, 1, 0, 3, 4],
121            ]
122        );
123    }
124
125    #[test]
126    #[should_panic(expected = "not implemented: n=5; r=1; board: false")]
127    fn test_unimpl() {
128        let _ = indices(5, 1, false);
129    }
130}