I recently learned about CNS and FNS , and since they look so elegant for me, I decided to try and implement methods for generating combinations and permutations using these methods. I finished my method to convert from n select k combinations to CSN rank and vice versa, but I hit my head against the wall trying to do the same with n choice of k (unique) permutations.
Thanks to @Joshua , I got the FNS to perutation method:
function Pr_Unrank($n, $k, $rank) { // rank starts at 1 if ($n >= $k) { if (($rank > 0) && ($rank <= Pr($n, $k))) { $rank--; $result = array(); $factoriadic = array(); for ($i = 1; $i <= ($n - $k); ++$i) { $rank *= $i; } for ($j = 1; $j <= $n; ++$j) { $factoriadic[$n - $j] = ($rank % $j) + 1; $rank /= $j; } for ($i = $n - 1; $i >= 0; --$i) { $result[$i] = $factoriadic[$i]; for ($j = $i + 1; $j < $n; ++$j) { if ($result[$j] >= $result[$i]) { ++$result[$j]; } } } return array_reverse(array_slice($result, 0 - $k)); } } return false; }
This is my current attempt at the ranking method (permutation for FNS):
function Pr_Rank($n, $k, $permutation) { if ($n >= $k) { $result = range(1, $n); $factoriadic = array(); foreach ($permutation as $key => $value) { $factoriadic[$k - $key - 1] = array_search($value, $result); array_splice($result, $factoriadic[$k - $key - 1], 1); } $result = 1; foreach (array_filter($factoriadic) as $key => $value) { $result += F($key) * $value; } return $result; } return false; }
And these are the helper functions that I use:
function F($n) { // Factorial return array_product(range($n, 1)); } function Pr($n, $k) { // Permutations (without Repetitions) return array_product(range($n - $k + 1, $n)); }
The problem is that the Pr_Rank() method returns the correct rank when n = k ( demo ):
var_dump(Pr_Rank(5, 2, Pr_Unrank(5, 2, 10)));
I behaved using the Wikipedia article I linked above and this MSDN article , I know that none of them consider k-size subsets, but I'm completely in the dark, what that logic looks like ...
I also tried Googling and looked for existing questions / answers, but nothing significant came up.