Instead of rearranging the original string of numbers, rearrange the groups of numbers. I don't know how to best describe it, so I will try a few psuedocode.
For the string "001222" a group of digits - two 0, 1 and 3 seconds.
permute(groups, permutation): if there are no non-empty groups print permutation else for each non-empty group permutation += group.digit --group.count permute(groups, permutation)
By looping groups, not all numbers, he avoids generating duplicates, because each digit can only be selected once for the next position, and not several times. Looking through a random permutation, you get
Permutation Digit Groups 0: 2, 1: 1, 2: 3 // start 0 0: 1, 1: 1, 2: 3 02 0: 1, 1: 1, 2: 2 // * 021 0: 1, 1: 0, 2: 2 // the 1 group is removed from the set 0212 0: 1, 1: 0, 2: 1 02120 0: 0, 1: 0, 2: 1 // the 0 group is removed from the set 021202 0: 0, 1: 0, 2: 0 // the 2 group is removed from the set
Now go to the * page.
02 0: 1, 1: 0, 2: 1
Since you are looping over groups of numbers, and not all (repeating) numbers from the original string, you cannot select 2 again. This means that all permutations starting with β02β will be unique because the prefix β02β is generated only once. The same goes for the algorithm.
Update
Here is a quick PHP implementation that produces 60 permutations for entering "001222":
function permute(&$groups, &$count, $permutation) { $done = true; foreach ($groups as &$group) { if ($group[1] > 0) { --$group[1]; permute($groups, $count, $permutation . $group[0]); ++$group[1]; $done = false; } } if ($done) { echo $permutation . PHP_EOL; ++$count; } } $groups = array( array(0, 2), array(1, 1), array(2, 3), ); $count = 0; permute($groups, $count, ''); echo "\nTotal: $count\n";