Here is an example of shuffling.
With a zero-based permutation named p whose size is 15, the statement p.shuffle (false, 4, 9) means that the element in position 0 is moved to position 4, and the element in position 1 is moved to position 9. The step is then defined as 9 − 4 = 5. It is not a problem if the step is zero or negative.
Each successive element from the source is placed, into the destination, 5 (the step size) positions beyond the one previously placed, with the count wrapping around the end modularly. If the desired position is already in use, the next higher-numbered vacant space is selected instead. This "next higher-numbered" placement collision policy is what makes this shuffle an out_shuffle; it is specified by the boolean parameter of false.
The permutation size need not be a multiple of the step; if these two numbers happen to be relatively prime, the out_shuffle will give the same result as the in_shuffle.
table 1 — out_shuffle | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
position: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
arbitrary permutation: | 8 | 11 | 7 | 12 | 13 | 9 | 1 | 4 | 6 | 0 | 14 | 5 | 2 | 10 | 3 |
shuffle (false, 4, 9): | 9 | 6 | 5 | 3 | 8 | 12 | 1 | 0 | 2 | 11 | 13 | 4 | 14 | 10 | 7 |
unshuffle (false, 4, 9): | 8 | 11 | 7 | 12 | 13 | 9 | 1 | 4 | 6 | 0 | 14 | 5 | 2 | 10 | 3 |
Of course, p.unshuffle (false, 4, 9) precisely undoes p.shuffle (false, 4, 9).
Here is an elaboration of how p.shuffle (false, 4, 9) is figured:
table 2 — shuffle (false, 4, 9) | |||
---|---|---|---|
element | old position | new position | comment |
8 | 0 | 4 | by parameter |
11 | 1 | 9 | by parameter |
7 | 2 | 14 | 9 + 5 = 14 |
12 | 3 | 5 | 14 + 5 = 19 → 4, in use; add 1 |
13 | 4 | 10 | 5 + 5 = 10 |
9 | 5 | 0 | 10 + 5 = 15 → 0 |
1 | 6 | 6 | 0 + 5 = 5, in use; add 1 |
4 | 7 | 11 | 6 + 5 = 11 |
6 | 8 | 1 | 11 + 5 = 16 → 1 |
0 | 9 | 7 | 1 + 5 = 6, in use; add 1 |
14 | 10 | 12 | 7 + 5 = 12 |
5 | 11 | 2 | 12 + 5 = 17 → 2 |
2 | 12 | 8 | 2 + 5 = 7, in use; add 1 |
10 | 13 | 13 | 8 + 5 = 13 |
3 | 14 | 3 | 13 + 5 = 18 → 3 |
For an in_shuffle, the boolean parameter is true rather than false, and the placement collision policy becomes "next lower-numbered". Example:
table 3 — in_shuffle | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
position: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
arbitrary permutation: | 8 | 11 | 7 | 12 | 13 | 9 | 1 | 4 | 6 | 0 | 14 | 5 | 2 | 10 | 3 |
shuffle (true, 4, 9): | 2 | 0 | 1 | 12 | 8 | 10 | 14 | 4 | 13 | 11 | 3 | 5 | 6 | 9 | 7 |
unshuffle (true, 4, 9): | 8 | 11 | 7 | 12 | 13 | 9 | 1 | 4 | 6 | 0 | 14 | 5 | 2 | 10 | 3 |
table 4 — shuffle (true, 4, 9) | |||
---|---|---|---|
element | old position | new position | comment |
8 | 0 | 4 | by parameter |
11 | 1 | 9 | by parameter |
7 | 2 | 14 | 9 + 5 = 14 |
12 | 3 | 3 | 14 + 5 = 19 → 4, in use, subtract 1 |
13 | 4 | 8 | 3 + 5 = 8 |
9 | 5 | 13 | 8 + 5 = 13 |
1 | 6 | 2 | 13 + 5 = 18 → 3, in use, subtract 1 |
4 | 7 | 7 | 2 + 5 = 7 |
6 | 8 | 12 | 7 + 5 = 12 |
0 | 9 | 1 | 12 + 5 = 17 → 2, in use, subtract 1 |
14 | 10 | 6 | 1 + 5 = 6 |
5 | 11 | 11 | 6 + 5 = 11 |
2 | 12 | 0 | 11 + 5 = 16 → 1, in use, subtract 1 |
10 | 13 | 5 | 0 + 5 = 5 |
3 | 14 | 10 | 5 + 5 = 10 |
Table 5 is the one-based equivalent to zero-based table 1. Every number, including the function parameters, has been increased by 1.
table 5 — out_shuffle | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
position: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
arbitrary permutation: | 9 | 12 | 8 | 13 | 14 | 10 | 2 | 5 | 7 | 1 | 15 | 6 | 3 | 11 | 4 |
shuffle (false, 5, 10): | 10 | 7 | 6 | 4 | 9 | 13 | 2 | 1 | 3 | 12 | 14 | 5 | 15 | 11 | 8 |
unshuffle (false, 5, 10): | 9 | 12 | 8 | 13 | 14 | 10 | 2 | 5 | 7 | 1 | 15 | 6 | 3 | 11 | 4 |
To achieve the canonical shuffles associated with a pack of playing cards, use a permutation whose size is an even number, and specify the following parameters:
table 6 — canonical shuffles | |
---|---|
out_shuffle, zero-based: | shuffle (false, 0, 2) |
in_shuffle, zero-based: | shuffle (true, 1, 3) |
out_shuffle, one-based: | shuffle (false, 1, 3) |
in_shuffle, one-based: | shuffle (true, 2, 4) |
These functions will still give a sensible result if the size of the permutation is an odd number.
The shuffle and unshuffle operations are by position (compare reverse_position) and not by value (contrast reverse_value). A shuffle_value could be written if needed.