How to resolve the algorithm Permutations/Rank of a permutation step by step in the Tcl programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Permutations/Rank of a permutation step by step in the Tcl 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 Tcl programming language

Source code in the tcl programming language

# A functional swap routine
proc swap {v idx1 idx2} {
    lset v $idx2 [lindex $v $idx1][lset v $idx1 [lindex $v $idx2];subst ""]
}

# Fill the integer array <vec> with the permutation at rank <rank>
proc computePermutation {vecName rank} {
    upvar 1 $vecName vec
    if {![info exist vec] || ![llength $vec]} return
    set N [llength $vec]
    for {set n 0} {$n < $N} {incr n} {lset vec $n $n}
    for {set n $N} {$n>=1} {incr n -1} {
	set r [expr {$rank % $n}]
	set rank [expr {$rank / $n}]
	set vec [swap $vec $r [expr {$n-1}]]
    }
}

# Return the rank of the current permutation.
proc computeRank {vec} {
    if {![llength $vec]} return
    set inv [lrepeat [llength $vec] 0]
    set i -1
    foreach v $vec {lset inv $v [incr i]}
    # First argument is lambda term
    set mrRank1 {{f n vec inv} {
	if {$n < 2} {return 0}
	set s [lindex $vec [set n1 [expr {$n - 1}]]]
	set vec [swap $vec $n1 [lindex $inv $n1]]
	set inv [swap $inv $s $n1]
	return [expr {$s + $n * [apply $f $f $n1 $vec $inv]}]
    }}
    return [apply $mrRank1 $mrRank1 [llength $vec] $vec $inv]
}


proc factorial {n} {
    for {set result 1; set i 2} {$i <= $n} {incr i} {
	set result [expr {$result * $i}]
    }
    return $result
}

set items1 [lrepeat 4 ""]
set rMax1 [factorial [llength $items1]]
for {set rank 0} {$rank < $rMax1} {incr rank} {
    computePermutation items1 $rank
    puts [format "%3d: \[%s\] = %d" \
	    $rank [join $items1 ", "] [computeRank $items1]]
}
puts ""
set items2 [lrepeat 21 ""]
set rMax2 [factorial [llength $items2]]
foreach _ {1 2 3 4} {
    # Note that we're casting to (potential) bignum, so entier() not int()
    set rank [expr {entier(rand() * $rMax2)}]
    computePermutation items2 $rank
    puts [format "%20lld: \[%s\] = %lld" \
	    $rank [join $items2 ", "] [computeRank $items2]]
}


proc uniform {limit} {
    set bits [expr {ceil(log($limit)/log(2))+10}]
    for {set b [set r 0]} {$b < $bits} {incr b 16} {
	incr r [expr {2**$b * int(rand() * 2**16)}]
    }
    return [expr {$r % $limit}]
}


  

You may also check:How to resolve the algorithm Regular expressions step by step in the Perl programming language
You may also check:How to resolve the algorithm Substring/Top and tail step by step in the PowerShell programming language
You may also check:How to resolve the algorithm XML/DOM serialization step by step in the PHP programming language
You may also check:How to resolve the algorithm Special variables step by step in the J programming language
You may also check:How to resolve the algorithm Price fraction step by step in the Common Lisp programming language