number_encoding/factoradics.rs
1// Copyright 2019-2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Factorial number system
16//!
17//! See [wikipedia] for more information.
18//!
19//! [wikipedia]: https://en.wikipedia.org/wiki/Factorial_number_system
20
21#[cfg(feature = "alloc")]
22use alloc::vec::Vec;
23
24/// Applies the permutation of the value `p` to the slice `xs`.
25///
26/// The applied permutation can be encoded with [`encode`] to get back `p`.
27///
28/// ```rust
29/// # use number_encoding::factoradics::{decode_mut, encode};
30/// # let mut xs = [0, 1, 2, 3];
31/// # let p = 15;
32/// decode_mut(&mut xs, p);
33/// assert_eq!(encode(&xs), p);
34/// ```
35///
36/// See [`decode`] for a version that allocates a vector for the permutation.
37///
38/// # Panics
39///
40/// Panics in debug mode if `xs` is not increasing or `p` is out of range.
41pub fn decode_mut<T: Ord>(xs: &mut [T], mut p: usize) {
42 let n = xs.len();
43 let mut m = crate::factorial(n);
44 debug_assert!(crate::is_ordered_set(xs), "Failed precondition");
45 debug_assert!(p < m, "Failed precondition");
46 for i in 0 .. n {
47 m /= n - i;
48 let j = i + p / m;
49 p %= m;
50 xs[i ..= j].rotate_right(1);
51 }
52 debug_assert_eq!(m, 1);
53 debug_assert_eq!(p, 0);
54}
55
56/// Returns the permutation of the value `p` to the slice `xs`.
57///
58/// The returned permutation can be encoded with [`encode`] to get back `p`.
59///
60/// ```rust
61/// # use number_encoding::factoradics::{decode, encode};
62/// # let xs = [0, 1, 2, 3];
63/// # let p = 15;
64/// let xs = decode(&xs, p);
65/// assert_eq!(encode(&xs), p);
66/// ```
67///
68/// See [`decode_mut`] for a version that applies the permutation to the slice.
69///
70/// # Panics
71///
72/// Panics in debug mode if `xs` is not increasing or `p` is out of range.
73///
74/// # Examples
75///
76/// ```rust
77/// # use number_encoding::factoradics::decode;
78/// assert_eq!(decode(&[0, 1, 2], 0), &[0, 1, 2]);
79/// assert_eq!(decode(&[0, 1, 2], 1), &[0, 2, 1]);
80/// assert_eq!(decode(&[0, 1, 2], 2), &[1, 0, 2]);
81/// ```
82#[cfg(feature = "alloc")]
83pub fn decode<T: Clone + Ord>(xs: &[T], p: usize) -> Vec<T> {
84 let mut xs = xs.to_vec();
85 decode_mut(&mut xs[..], p);
86 xs
87}
88
89#[test]
90fn decode_ok() {
91 fn test(d: usize, p: usize, e: &[usize]) {
92 let mut r: Vec<_> = (0 .. d).collect();
93 decode_mut(&mut r, p);
94 assert_eq!(r, e, "p={p}");
95 }
96 test(0, 0, &[]);
97 test(1, 0, &[0]);
98 test(2, 0, &[0, 1]);
99 test(2, 1, &[1, 0]);
100 test(3, 0, &[0, 1, 2]);
101 test(3, 1, &[0, 2, 1]);
102 test(3, 2, &[1, 0, 2]);
103 test(3, 3, &[1, 2, 0]);
104 test(3, 4, &[2, 0, 1]);
105 test(3, 5, &[2, 1, 0]);
106}
107
108/// Returns the value of a permutation.
109///
110/// The returned value can be decoded with [`decode`] to get back `xs`.
111///
112/// ```rust
113/// # use number_encoding::factoradics::{decode, encode};
114/// # let xs = &[2, 0, 1];
115/// let mut ys = xs.to_vec();
116/// ys.sort();
117/// let p = encode(xs);
118/// assert_eq!(decode(&ys, p), xs);
119/// ```
120///
121/// # Panics
122///
123/// Panics in debug mode if `xs` does not contain distinct elements.
124///
125/// # Examples
126///
127/// ```rust
128/// # use number_encoding::factoradics::encode;
129/// assert_eq!(encode(&[0, 1, 2]), 0);
130/// assert_eq!(encode(&[0, 2, 1]), 1);
131/// assert_eq!(encode(&[1, 0, 2]), 2);
132/// ```
133pub fn encode<T: Ord>(xs: &[T]) -> usize {
134 debug_assert!(crate::is_unordered_set(xs), "Failed precondition");
135 let n = xs.len();
136 let mut m = crate::factorial(n);
137 let mut r = 0;
138 for i in 0 .. n {
139 m /= n - i;
140 r += m * xs[i + 1 ..].iter().filter(|&x| x < &xs[i]).count();
141 }
142 debug_assert_eq!(m, 1);
143 r
144}
145
146#[test]
147fn encode_ok() {
148 fn test(xs: &[usize], p: usize) {
149 assert_eq!(encode(xs), p, "xs={xs:?}");
150 }
151 test(&[], 0);
152 test(&[0], 0);
153 test(&[0, 1], 0);
154 test(&[1, 0], 1);
155 test(&[0, 1, 2], 0);
156 test(&[0, 2, 1], 1);
157 test(&[1, 0, 2], 2);
158 test(&[1, 2, 0], 3);
159 test(&[2, 0, 1], 4);
160 test(&[2, 1, 0], 5);
161}
162
163/// Iterates over all permutations of a slice.
164///
165/// The permutations are iterated in value order:
166///
167/// ```rust
168/// # use number_encoding::factoradics::{Iter, encode};
169/// # let mut xs = [0, 1, 2, 3];
170/// let mut iter = Iter::new(&mut xs);
171/// let mut i = 0;
172/// while let Some(xs) = iter.next() {
173/// assert_eq!(encode(xs), i);
174/// i += 1;
175/// }
176/// ```
177///
178/// If the iteration goes to the end (i.e. [`next`](Iter::next) returns `None`), then the slice is
179/// restored to its initial value (i.e. increasing):
180///
181/// ```rust
182/// # use number_encoding::factoradics::Iter;
183/// # let mut xs = [0, 1, 2, 3];
184/// let saved_xs = xs.clone();
185/// let mut iter = Iter::new(&mut xs);
186/// while iter.next().is_some() {}
187/// assert_eq!(xs, saved_xs);
188/// ```
189///
190/// # Examples
191///
192/// ```rust
193/// # use number_encoding::factoradics::Iter;
194/// # fn process(xs: &[usize]) {}
195/// # let mut xs = [0, 1, 2, 3];
196/// let mut iter = Iter::new(&mut xs);
197/// while let Some(xs) = iter.next() {
198/// process(xs);
199/// }
200/// ```
201pub struct Iter<'a, T> {
202 data: &'a mut [T],
203 state: IterState,
204}
205
206enum IterState {
207 New,
208 Running,
209 Done,
210}
211
212impl<'a, T: Ord> Iter<'a, T> {
213 /// Constructs an iterator with an increasing slice.
214 ///
215 /// # Panics
216 ///
217 /// Panics in debug mode if `xs` is not increasing.
218 pub fn new(xs: &mut [T]) -> Iter<T> {
219 debug_assert!(crate::is_ordered_set(xs));
220 Iter { data: xs, state: IterState::New }
221 }
222
223 /// Returns the next permutation.
224 ///
225 /// If iteration is over, returns `None`.
226 #[allow(clippy::should_implement_trait)]
227 pub fn next(&mut self) -> Option<&[T]> {
228 match self.state {
229 IterState::New => self.state = IterState::Running,
230 IterState::Running => {
231 if self.advance() {
232 self.state = IterState::Done;
233 }
234 }
235 IterState::Done => (),
236 }
237 match self.state {
238 IterState::New => unreachable!(),
239 IterState::Running => Some(self.data),
240 IterState::Done => None,
241 }
242 }
243
244 fn advance(&mut self) -> bool {
245 let k = self.data.len();
246 if k == 0 {
247 return true;
248 }
249 let mut i = k - 1;
250 while i > 0 && self.data[i - 1] > self.data[i] {
251 i -= 1;
252 }
253 if i == 0 {
254 self.data.reverse();
255 return true;
256 }
257 self.data[i ..].reverse();
258 let j = self.data[i ..].iter().position(|x| x > &self.data[i - 1]).unwrap();
259 self.data.swap(i - 1, i + j);
260 false
261 }
262}
263
264#[test]
265fn iter_ok() {
266 fn test(r: &[&[usize]]) {
267 let mut xs = r[0].to_vec();
268 let mut iter = Iter::new(&mut xs);
269 let mut i = 0;
270 while let Some(xs) = iter.next() {
271 assert_eq!(xs, r[i]);
272 assert_eq!(encode(xs), i);
273 i += 1;
274 }
275 assert_eq!(r.len(), i);
276 assert_eq!(xs, r[0]);
277 }
278 test(&[&[]]);
279 test(&[&[0]]);
280 test(&[&[0, 1], &[1, 0]]);
281 test(&[&[0, 1, 2], &[0, 2, 1], &[1, 0, 2], &[1, 2, 0], &[2, 0, 1], &[2, 1, 0]]);
282 test(&[
283 &[0, 1, 2, 3],
284 &[0, 1, 3, 2],
285 &[0, 2, 1, 3],
286 &[0, 2, 3, 1],
287 &[0, 3, 1, 2],
288 &[0, 3, 2, 1],
289 &[1, 0, 2, 3],
290 &[1, 0, 3, 2],
291 &[1, 2, 0, 3],
292 &[1, 2, 3, 0],
293 &[1, 3, 0, 2],
294 &[1, 3, 2, 0],
295 &[2, 0, 1, 3],
296 &[2, 0, 3, 1],
297 &[2, 1, 0, 3],
298 &[2, 1, 3, 0],
299 &[2, 3, 0, 1],
300 &[2, 3, 1, 0],
301 &[3, 0, 1, 2],
302 &[3, 0, 2, 1],
303 &[3, 1, 0, 2],
304 &[3, 1, 2, 0],
305 &[3, 2, 0, 1],
306 &[3, 2, 1, 0],
307 ]);
308}