How to resolve the algorithm Permutations/Rank of a permutation step by step in the jq programming language
How to resolve the algorithm Permutations/Rank of a permutation step by step in the jq programming language
Table of Contents
Problem Statement
A particular ranking of a permutation associates an integer with a particular ordering of all the permutations of a set of distinct items. For our purposes the ranking will assign integers
0.. ( n ! − 1 )
{\displaystyle 0..(n!-1)}
to an ordering of all the permutations of the integers
0.. ( n − 1 )
{\displaystyle 0..(n-1)}
. For example, the permutations of the digits zero to 3 arranged lexicographically have the following rank: Algorithms exist that can generate a rank from a permutation for some particular ordering of permutations, and that can generate the same rank from the given individual permutation (i.e. given a rank of 17 produce (2, 3, 1, 0) in the example above). One use of such algorithms could be in generating a small, random, sample of permutations of
n
{\displaystyle n}
items without duplicates when the total number of permutations is large. Remember that the total number of permutations of
n
{\displaystyle n}
items is given by
n !
{\displaystyle n!}
which grows large very quickly: A 32 bit integer can only hold
12 !
{\displaystyle 12!}
, a 64 bit integer only
20 !
{\displaystyle 20!}
. It becomes difficult to take the straight-forward approach of generating all permutations then taking a random sample of them. A question on the Stack Overflow site asked how to generate one million random and indivudual permutations of 144 items.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Permutations/Rank of a permutation step by step in the jq programming language
Source code in the jq programming language
# Assuming sufficiently-precise integer arithmetic,
# if the input and $j are integers, then the result will be a pair of integers,
# except that if $j is 0, then an error condition is raised.
def divmod($j):
. as $i
| ($i % $j) as $mod
| [($i - $mod) / $j, $mod] ;
# Input may be an object or an array
def swap($i; $j):
.[$i] as $t
| .[$i] = .[$j]
| .[$j] = $t;
def factorial:
. as $n
| reduce range(2; $n) as $i ($n; . * $i);
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
# Myrvold and Ruskey algorithm
# The input should be a permutation of 0 ... $n-1 inclusive
def mrUnrank1($rank; $n):
if $n < 1 then .
else ($rank|divmod($n)) as [$q, $r]
| swap($r; $n - 1)
| mrUnrank1($q; $n - 1)
end ;
# The input should be a permutation of 0 ... $n-1 inclusive
def mrRank1($n; $vec):
if $n < 2 then 0
else
. as $inv
| $vec
| .[$n-1] as $s
| swap($n - 1; $inv[$n-1]) as $vec
| $inv
| swap($s; $n - 1)
| $s + $n * mrRank1($n - 1; $vec)
end;
def getPermutation($rank; $n):
[range(0; $n)]
| mrUnrank1($rank; $n) ;
def getRank($n; $vec):
reduce range(0; $n) as $i ( null;
.[$vec[$i]] = $i )
| mrRank1($n; $vec);
def task($k):
"\($k)!",
(range(0; $k|factorial) as $r
| getPermutation($r; $k)
| [ ($r|lpad(2)), tostring, (getRank($k; .) | lpad(2)) ]
| join(" -> ") );
def task3:
def randoms: 43154690, 150112966, 15732396, 157551691;
"\("#"|lpad(10)) -> \("permutation"|lpad(27)) -> \("rank"|lpad(10))",
(randoms as $r
| getPermutation($r; 12)
| "\($r|lpad(10)) -> \(lpad(27)) -> \(getRank(12;.)|lpad(10))" );
task(3),
"",
task(4),
"",
task3
You may also check:How to resolve the algorithm Character codes step by step in the DWScript programming language
You may also check:How to resolve the algorithm Averages/Arithmetic mean step by step in the EMal programming language
You may also check:How to resolve the algorithm Conditional structures step by step in the langur programming language
You may also check:How to resolve the algorithm String length step by step in the LFE programming language
You may also check:How to resolve the algorithm Hash join step by step in the M2000 Interpreter programming language