I too think this isn't a great interface as far as the example goes. But anyway, we can abstract the question to be "what's a good API for constructing a permutation of a fixed size?" The metrics you've described are "infallible construction from the inputs" and "no factorially growing enums as inputs".

## Thinking aloud...

Every permutation can be decomposed into a sequence of swaps, so one way would be to take an iterator of valid swaps (`(i, j)`

where `i < j`

). That's `n * (n - 1) / 2`

possibilities for size `n`

; going from size `k`

to `k+1`

introduces `k`

new possibilities. You could nest these, but the code would be gnarly. So probably you'd just make an `enum`

per size, and that's quadratic for a single size, but cubed if you need all smaller sizes.

Another possibility would be to take a Lehmer code in some form, like a tuple of `(TwoOrLess, OneOrLess, Zero)`

(or reversed; `Zero`

optional). Going from `k`

to `k+1`

again introduces `k`

new variants, but since they're used separately, you'd just introduce a new enum with `n-1`

variants. You always need all smaller sizes, but it is quadratic in total. In a sense you get the benefits of nesting the other suggestion for free. (If you nested this version, it would be linear, but again gnarly.)

Assuming you want a `[uint; N]`

permutation to come out, we might consider conversion cost. The number of transpositions needed or supplied may vary, but an optimal encoding will involve a linear number of swaps. The direct encoding/decoding of Lehmer codes is quadratic, but you could instead use a modified definition:

- Start with the identity permutation
- Largest radix digit is the index of the first element: swap first element with that index
- Second largest radix digit is the index of the second element out of the remaining elements
- Etc

In this modified form, the encoding can be seen as an alternative way to supply a sequence of transpositions.

So one way would be to have

```
#[derive(Copy, Clone)] #[repr(u8)] pub enum D1 { Zero, One, }
#[derive(Copy, Clone)] #[repr(u8)] pub enum D2 { Zero, One, Two, }
#[derive(Copy, Clone)] #[repr(u8)] pub enum D3 { Zero, One, Two, Three, }
```

And then to construct a permutation `[u8; 4]`

from a `tuple = (D1, D2, D3)`

you could start with the identity `permutation = [0, 1, 2, 3]`

and then

```
let indices = [tuple.2 as usize, tuple.1 as usize, tuple.0 as usize];
for (offset, idx) in indices.into_iter().enumerate() {
permutation.swap(offset, offset + idx);
}
```

Linear growth of variants for a quadratic total, bijection between inputs and outputs, linear construction.