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}