I know this topic is much discussed but I can’t seem to find any implementation that fits my needs.
I have the following set of characters:
a b c d e f g h
I want to get all possible permutations or combinations (non repeating), but on a limited (variable) set of characters, meaning if I input the characters and the number 2, the results should look like
ab ba ac ca ad da ae ea af fa ag ga ah ha
bc cb bd db be eb bf fb bg gb bh hb
cd dc ce ec cf fc cg gc ch hc
de ed df fd dg gd dh hd
ef fe eg ge eh he
fg gf fh hf
gh hg
I hope you understand where I’m going with this. I currently have an implementation that gives me the permutations of all characters, but I can’t wrap my head around how to implement a limited space for those permutations:
public function getPermutations($letters) {
if (strlen($letters) < 2) {
return array($letters);
}
$permutations = array();
$tail = substr($letters, 1);
foreach ($this->getPermutations($tail) as $permutation) {
$length = strlen($permutation);
for ($i = 0; $i <= $length; $i++) {
$permutations[] = substr($permutation, 0, $i) . $letters[0] . substr($permutation, $i);
}
}
return $permutations;
}
If you only need one element at a time, you can save on memory by generating each element individually.
If we wanted to generate a random string in your set of expected outputs, we could use this algorithm:
where
|S|is the current number of elements in S.We can actually encode this sequence of choices into an integer. One way to do that is to change the algorithm as such:
After running this algorithm, the value
Iwill uniquely encode this particular sequence of choices. It basically encodes this as a mixed-radix number; one digit uses base N, the next uses N-1, and so on until the last digit which is base N-K+1 (N being the number of letters in the input).Naturally, we can also decode this again, and in PHP, that would be something like this:
(Note that for simplicity, this particular decoding algorithm does not correspond exactly to the encoding algorithm I previously described, but maintains the desirable property of a given
$indexmapping to a unique result.)To use this code, you would do something like this: