1
2use std::marker::PhantomData;
3use std::ops::{
4 AddAssign,
5 MulAssign,
6 Sub,
7 Mul,
8 SubAssign,
9 DivAssign,
10 Div,
11};
12use std::convert::TryInto;
13use std::fmt::Debug;
14
15use num::BigUint;
16
17use Construct;
18use Data;
19use Of;
20use space::Space;
21
22pub struct Permutation<T = Data>(PhantomData<T>);
24
25impl<T> Construct for Permutation<T> {
26 fn new() -> Self { Permutation(PhantomData) }
27}
28
29impl Space<usize> for Permutation<Data> {
30 type Dim = usize;
31 type Pos = Vec<usize>;
32 fn count(&self, dim: &usize) -> usize {
33 let mut res = 1;
34 for x in 1..dim + 1 {
35 res *= x;
36 }
37 res
38 }
39 fn zero(&self, dim: &usize) -> Vec<usize> {
40 vec![0; *dim]
41 }
42 fn to_index(&self, dim: &usize, pos: &Vec<usize>) -> usize {
43 let mut index = 0;
44 let mut count = 1;
45 for (i, &x) in pos.iter().enumerate().rev() {
46 let lower = pos[..i].iter().filter(|&&y| y < x).count();
47 index += count * (x - lower);
48 count *= dim - i;
49 }
50 index
51 }
52 fn to_pos(&self, dim: &usize, mut index: usize, pos: &mut Vec<usize>) {
53 unsafe { pos.set_len(0); }
54
55 let mut count = 1;
56 for (j, x) in (1..dim + 1).enumerate() {
57 count *= x;
58 pos.push(j);
59 }
60
61 for i in 0..*dim {
62 let block = count / (dim - i);
63 let ind = index / block;
64 let item = pos.remove(ind);
65 pos.push(item);
66 count /= dim - i;
67 index -= ind * block;
68 }
69 }
70}
71
72impl Space<BigUint> for Permutation<Data> {
73 type Dim = BigUint;
74 type Pos = Vec<BigUint>;
75 fn count(&self, dim: &BigUint) -> BigUint {
76 let _1: BigUint = 1usize.into();
77 let mut res: BigUint = _1.clone();
78 let mut x = _1.clone();
79 loop {
80 if &x > dim {break}
81 res *= &x;
82 x += &_1;
83 }
84 res
85 }
86 fn zero(&self, dim: &BigUint) -> Vec<BigUint> {
87 let dim: usize = dim.try_into().unwrap();
88 vec![0usize.into(); dim]
89 }
90 fn to_index(&self, dim: &Self::Dim, pos: &Self::Pos) -> BigUint {
91 let mut index: BigUint = 0usize.into();
92 let mut count: BigUint = 1usize.into();
93 for (i, x) in pos.iter().enumerate().rev() {
94 let lower = pos[..i].iter().filter(|&y| y < x).count();
95 index += &count * (x - lower);
96 count *= dim - i;
97 }
98 index
99 }
100 fn to_pos(&self, dim: &Self::Dim, mut index: BigUint, pos: &mut Self::Pos) {
101 pos.clear();
102
103 let mut count: BigUint = 1usize.into();
104 let dim: usize = dim.try_into().unwrap();
105 for (j, x) in (1usize..dim + 1).enumerate() {
106 count *= x;
107 pos.push(j.into());
108 }
109
110 let dim: usize = dim.try_into().unwrap();
111 for i in 0..dim {
112 let block = &count / (dim - i);
113 let ind: BigUint = &index / █
114 let item = pos.remove((&ind).try_into().unwrap());
115 pos.push(item);
116 count /= dim - i;
117 index -= &ind * block;
118 }
119 }
120}
121
122impl<N, T> Space<N> for Permutation<Of<T>>
123 where T: Space<N>,
124 T::Pos: Clone,
125 N: Clone +
126 From<usize> +
127 TryInto<usize> +
128 for<'a> AddAssign<&'a N> +
129 for<'a> MulAssign<&'a N> +
130 Sub<usize, Output = N> +
131 SubAssign +
132 DivAssign<usize> +
133 MulAssign<usize> +
134 PartialOrd,
135 <N as TryInto<usize>>::Error: Debug,
136 for<'a> &'a N: Sub<usize, Output = N> +
137 Mul<&'a N, Output = N> +
138 Div<usize, Output = N> +
139 Div<&'a N, Output = N> +,
140 <N as TryInto<usize>>::Error: Debug,
141{
142 type Dim = T::Dim;
143 type Pos = Vec<T::Pos>;
144 fn count(&self, dim: &Self::Dim) -> N {
145 let of: T = Construct::new();
146 let _1: N = 1usize.into();
147 let mut x = _1.clone();
148 let mut res = _1.clone();
149 let of_count = of.count(dim);
150 loop {
151 if &x > &of_count {break}
152 res *= &x;
153 x += &_1;
154 }
155 res
156 }
157 fn zero(&self, dim: &Self::Dim) -> Self::Pos {
158 let of: T = Construct::new();
159 let count = match of.count(dim).try_into() {
160 Ok(x) => x,
161 Err(_) => panic!("Out of range"),
162 };
163 vec![of.zero(dim); count]
164 }
165 fn to_index(&self, dim: &Self::Dim, pos: &Self::Pos) -> N {
166 let of: T = Construct::new();
167 let mut index: N = 0usize.into();
168 let dim_count = of.count(dim);
169 let mut count: N = 1usize.into();
170 for (i, x) in pos.iter()
171 .map(|x| of.to_index(dim, x))
172 .enumerate().rev() {
173 let lower = pos[..i].iter()
174 .map(|y| of.to_index(dim, y))
175 .filter(|y| y < &x).count();
176 index += &(&count * &(x - lower));
177 count *= &(&dim_count - i);
178 }
179 index
180 }
181 fn to_pos(&self, dim: &Self::Dim, mut index: N, pos: &mut Self::Pos) {
182 let of: T = Construct::new();
183 let of_count: usize = of.count(dim).try_into().unwrap();
184 pos.clear();
185
186 let mut count: N = 1usize.into();
187 for (j, x) in (1..of_count + 1).enumerate() {
188 count *= x;
189 let mut new_pos: T::Pos = of.zero(&dim);
190 of.to_pos(dim, j.into(), &mut new_pos);
191 pos.push(new_pos);
192 }
193
194 for i in 0..of_count {
195 let diff = of_count - i;
196 let block = &count / diff;
197 let ind = &index / █
198 index -= &ind * █
199 let item = pos.remove(ind.try_into().unwrap());
200 pos.push(item);
201 count /= diff;
202 }
203 }
204}
205
206#[cfg(test)]
207mod test {
208 use super::super::*;
209
210 #[test]
211 fn features() {
212 is_complete::<usize, Permutation>();
213 is_complete::<usize, Permutation<Of<Pair>>>();
214 }
215
216 #[test]
217 fn data() {
218 let permutation: Permutation = Construct::new();
219 assert_eq!(permutation.count(&1), 1);
220 assert_eq!(permutation.count(&2), 2);
221 assert_eq!(permutation.count(&3), 6);
222 assert_eq!(permutation.count(&4), 24);
223
224 let mut pos = Vec::new();
225 let ref dim = 4;
226 let count = permutation.count(dim);
227 for i in 0..count {
228 permutation.to_pos(dim, i, &mut pos);
229 let index = permutation.to_index(dim, &pos);
230 assert_eq!(index, i);
231 }
232 }
233
234 #[test]
235 fn data_big() {
236 use std::convert::TryInto;
237
238 let permutation: Permutation = Construct::new();
239 let ins: Vec<BigUint> = vec![
240 1usize.into(),
241 2usize.into(),
242 3usize.into(),
243 4usize.into(),
244 ];
245 let outs: Vec<BigUint> = vec![
246 1usize.into(),
247 2usize.into(),
248 6usize.into(),
249 24usize.into(),
250 ];
251 for i in 0..ins.len() {
252 assert_eq!(permutation.count(&ins[i]), outs[i]);
253 }
254
255 let mut pos: Vec<BigUint> = Vec::new();
256 let ref dim: BigUint = 4usize.into();
257 let count: usize = permutation.count(dim).try_into().unwrap();
258 for i in 0usize..count {
259 permutation.to_pos(dim, i.into(), &mut pos);
260 let index = permutation.to_index(dim, &pos);
261 assert_eq!(index, i.into());
262 }
263 }
264
265 #[test]
266 fn of() {
267 let space: Permutation<Of<Pair>> = Construct::new();
268 let ref dim = 3;
269 let count = space.count(dim);
270 let mut pos = space.zero(dim);
271 for i in 0..count {
272 space.to_pos(dim, i, &mut pos);
273 let index = space.to_index(dim, &pos);
274 assert_eq!(index, i);
275 }
276 }
277
278 #[test]
279 fn of_big() {
280 use std::convert::TryInto;
281
282 let space: Permutation<Of<Pair>> = Construct::new();
283 let ref dim: BigUint = 3usize.into();
284 let count: usize = space.count(dim).try_into().unwrap();
285 let mut pos = space.zero(dim);
286 for i in 0..count {
287 space.to_pos(dim, i.into(), &mut pos);
288 let index = space.to_index(dim, &pos);
289 assert_eq!(index, i.into());
290 }
291 }
292}