Permutations/Rank of a permutation: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 60: Line 60:
{{trans|Nim}}
{{trans|Nim}}


<lang 11l>UInt32 seed = 0
<syntaxhighlight lang="11l">UInt32 seed = 0
F nonrandom()
F nonrandom()
:seed = 1664525 * :seed + 1013904223
:seed = 1664525 * :seed + 1013904223
Line 106: Line 106:
V r = Int(nonrandom() * factorial(12))
V r = Int(nonrandom() * factorial(12))
getPermutation(&tv12, r)
getPermutation(&tv12, r)
print(‘#9 -> #. -> #.’.format(r, tv12, getRank(tv12)))</lang>
print(‘#9 -> #. -> #.’.format(r, tv12, getRank(tv12)))</syntaxhighlight>


{{out}}
{{out}}
Line 151: Line 151:
=== C: Myrvold and Ruskey ===
=== C: Myrvold and Ruskey ===
This is algorithm #1 from the M&R paper.
This is algorithm #1 from the M&R paper.
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>


Line 219: Line 219:
}
}
}
}
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 251: Line 251:
{{trans|C}}
{{trans|C}}
Currently this doesn't use BigInts.
Currently this doesn't use BigInts.
<lang d>import std.stdio, std.algorithm, std.range;
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range;


alias TRank = ulong;
alias TRank = ulong;
Line 313: Line 313:
writefln("%20d: %s = %d", rank, items2, items2.computeRank);
writefln("%20d: %s = %d", rank, items2, items2.computeRank);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre> 0: [1, 2, 3, 0] = 0
<pre> 0: [1, 2, 3, 0] = 0
Line 348: Line 348:
=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
===Up to 20 objects===
===Up to 20 objects===
<lang freebasic>' version 31-03-2017
<syntaxhighlight lang="freebasic">' version 31-03-2017
' compile with: fbc -s console
' compile with: fbc -s console


Line 497: Line 497:
Print : Print "hit any key to end program"
Print : Print "hit any key to end program"
Sleep
Sleep
End</lang>
End</syntaxhighlight>
{{out}}
{{out}}
<pre>Rank: unrank1 rank1
<pre>Rank: unrank1 rank1
Line 532: Line 532:
===Using GMP for the big numbers===
===Using GMP for the big numbers===
{{libheader|GMP}}
{{libheader|GMP}}
<lang freebasic>' version 31-03-2017
<syntaxhighlight lang="freebasic">' version 31-03-2017
' compile with: fbc -s console
' compile with: fbc -s console


Line 648: Line 648:
Print : Print "hit any key to end program"
Print : Print "hit any key to end program"
Sleep
Sleep
End</lang>
End</syntaxhighlight>
{{out}}
{{out}}
<pre>862993243747395020367391904490190117106585269146708404403331561502140758428008657463653366643611155380240799622282374456087743515643868809722278635878978733132591027133490410275442362000562723356064257191755491520940533177124123076535632269113257248
<pre>862993243747395020367391904490190117106585269146708404403331561502140758428008657463653366643611155380240799622282374456087743515643868809722278635878978733132591027133490410275442362000562723356064257191755491520940533177124123076535632269113257248
Line 669: Line 669:


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 750: Line 750:
fmt.Println(r, MRPerm(r, n))
fmt.Println(r, MRPerm(r, n))
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 769: Line 769:
=={{header|Haskell}}==
=={{header|Haskell}}==
Without the random part.
Without the random part.
<lang haskell>fact :: Int -> Int
<syntaxhighlight lang="haskell">fact :: Int -> Int
fact n = product [1 .. n]
fact n = product [1 .. n]


Line 788: Line 788:
f n = print (n, p, permRank p)
f n = print (n, p, permRank p)
where
where
p = rankPerm [0 .. 3] n</lang>
p = rankPerm [0 .. 3] n</syntaxhighlight>
{{out}}
{{out}}
from rank to permutation back to rank:
from rank to permutation back to rank:
Line 821: Line 821:
The J primitive <code>A.</code> provides an effective solution to this task. Generating 4 random permutations of 144 items takes about 6 milliseconds so solving the Stack Overflow question ought to take about 100 minutes on that particular test machine.
The J primitive <code>A.</code> provides an effective solution to this task. Generating 4 random permutations of 144 items takes about 6 milliseconds so solving the Stack Overflow question ought to take about 100 minutes on that particular test machine.


<lang j> A. 2 0 1 NB. return rank of permutation
<syntaxhighlight lang="j"> A. 2 0 1 NB. return rank of permutation
4
4
4 A. i.3 NB. return permutation of rank 4
4 A. i.3 NB. return permutation of rank 4
Line 845: Line 845:
111 65 136 58 92 46 4 83 20 54 21 10 72 110 56 28 13 18 73 133 105 117 63 126 114 43 5 80 45 88 86 108 11 29 0 129 71 141 59 53 113 137 2 102 95 15 35 74 107 61 134 36 32 19 106 100 55 69 76 142 64 49 9 30 47 123 12 97 42...
111 65 136 58 92 46 4 83 20 54 21 10 72 110 56 28 13 18 73 133 105 117 63 126 114 43 5 80 45 88 86 108 11 29 0 129 71 141 59 53 113 137 2 102 95 15 35 74 107 61 134 36 32 19 106 100 55 69 76 142 64 49 9 30 47 123 12 97 42...
64 76 139 122 37 127 57 143 32 108 46 17 126 9 51 59 1 74 23 89 42 124 132 19 93 137 70 86 14 112 83 91 63 39 73 18 90 120 53 103 140 87 43 55 131 40 142 102 107 111 80 65 61 34 66 75 88 92 13 138 50 117 97 20 44 7 56 94 41...
64 76 139 122 37 127 57 143 32 108 46 17 126 9 51 59 1 74 23 89 42 124 132 19 93 137 70 86 14 112 83 91 63 39 73 18 90 120 53 103 140 87 43 55 131 40 142 102 107 111 80 65 61 34 66 75 88 92 13 138 50 117 97 20 44 7 56 94 41...
139 87 98 118 125 65 35 112 10 43 85 66 58 131 36 30 50 11 136 130 71 100 79 142 40 69 101 84 143 33 95 26 18 94 13 68 8 0 47 70 129 48 107 64 93 16 83 39 29 81 6 105 78 92 104 60 15 55 4 14 7 91 86 12 31 46 20 133 53...</lang>
139 87 98 118 125 65 35 112 10 43 85 66 58 131 36 30 50 11 136 130 71 100 79 142 40 69 101 84 143 33 95 26 18 94 13 68 8 0 47 70 129 48 107 64 93 16 83 39 29 81 6 105 78 92 104 60 15 55 4 14 7 91 86 12 31 46 20 133 53...</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
Line 855: Line 855:
'''Code:'''
'''Code:'''


<lang java>import java.math.BigInteger;
<syntaxhighlight lang="java">import java.math.BigInteger;
import java.util.*;
import java.util.*;


Line 926: Line 926:
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 954: Line 954:


'''Preliminaries'''
'''Preliminaries'''
<lang jq># Assuming sufficiently-precise integer arithmetic,
<syntaxhighlight lang="jq"># Assuming sufficiently-precise integer arithmetic,
# if the input and $j are integers, then the result will be a pair of integers,
# 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.
# except that if $j is 0, then an error condition is raised.
Line 972: Line 972:
| reduce range(2; $n) as $i ($n; . * $i);
| reduce range(2; $n) as $i ($n; . * $i);


def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;</lang>
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;</syntaxhighlight>


'''The Tasks'''
'''The Tasks'''
<lang jq># Myrvold and Ruskey algorithm
<syntaxhighlight lang="jq"># Myrvold and Ruskey algorithm
# The input should be a permutation of 0 ... $n-1 inclusive
# The input should be a permutation of 0 ... $n-1 inclusive
def mrUnrank1($rank; $n):
def mrUnrank1($rank; $n):
Line 1,026: Line 1,026:
task(4),
task(4),
"",
"",
task3</lang>
task3</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,078: Line 1,078:


Unfortunately, as of the 0.3 release of Julian, this code can not be used to address the StackOverflow question. Although many of Julia's permutation built-in functions support large permutations, <tt>nthperm(p)</tt> is limited to partitions of no more than 20 objects. <tt>p = randperm(114)</tt> works fine, but <tt>nthperm(p)</tt> throws an <tt>OverflowError</tt>. Arguably, this is a bug, and it may be rectified in future releases.
Unfortunately, as of the 0.3 release of Julian, this code can not be used to address the StackOverflow question. Although many of Julia's permutation built-in functions support large permutations, <tt>nthperm(p)</tt> is limited to partitions of no more than 20 objects. <tt>p = randperm(114)</tt> works fine, but <tt>nthperm(p)</tt> throws an <tt>OverflowError</tt>. Arguably, this is a bug, and it may be rectified in future releases.
<lang Julia>using Printf
<syntaxhighlight lang="julia">using Printf


nobjs = 4
nobjs = 4
Line 1,105: Line 1,105:
println(" ", p, " (", prank, ")")
println(" ", p, " (", prank, ")")
end
end
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,144: Line 1,144:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|C}}
{{trans|C}}
<lang scala>// version 1.1.2
<syntaxhighlight lang="scala">// version 1.1.2


import java.util.Random
import java.util.Random
Line 1,208: Line 1,208:
System.out.printf("%9d -> %s -> %d\n", r, tv.contentToString(), getRank(12, tv))
System.out.printf("%9d -> %s -> %d\n", r, tv.contentToString(), getRank(12, tv))
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,252: Line 1,252:
=={{header|Mathematica}}/{{header|Wolfram Language}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
{{trans|Haskell}}
{{trans|Haskell}}
<lang mathematica>fromrank[list_, 0] := list;
<syntaxhighlight lang="mathematica">fromrank[list_, 0] := list;
fromrank[list_, n_] :=
fromrank[list_, n_] :=
Prepend[fromrank[DeleteCases[list, #],
Prepend[fromrank[DeleteCases[list, #],
Line 1,265: Line 1,265:


Do[Print@fromrank[Range[0, 12 - 1], RandomInteger[12!]], {4}];
Do[Print@fromrank[Range[0, 12 - 1], RandomInteger[12!]], {4}];
Do[Print@fromrank[Range[0, 144 - 1], RandomInteger[144!]], {4}];</lang>
Do[Print@fromrank[Range[0, 144 - 1], RandomInteger[144!]], {4}];</syntaxhighlight>
{{Out}}
{{Out}}
<pre>{0,{0,1,2,3},0}
<pre>{0,{0,1,2,3},0}
Line 1,302: Line 1,302:
=={{header|Nim}}==
=={{header|Nim}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang Nim>func mrUnrank1(vec: var openArray[int]; rank, n: int) =
<syntaxhighlight lang="nim">func mrUnrank1(vec: var openArray[int]; rank, n: int) =
if n < 1: return
if n < 1: return
let q = rank div n
let q = rank div n
Line 1,349: Line 1,349:
for r in newSeqWith(4, rand(fac(12))):
for r in newSeqWith(4, rand(fac(12))):
tv12.getPermutation(r)
tv12.getPermutation(r)
echo &"{r:>9} → {tv12} → {tv12.getRank()}"</lang>
echo &"{r:>9} → {tv12} → {tv12.getRank()}"</syntaxhighlight>


{{out}}
{{out}}
Line 1,391: Line 1,391:
=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
The functions are built into GP already: <code>numtoperm</code> and <code>permtonum</code>
The functions are built into GP already: <code>numtoperm</code> and <code>permtonum</code>
<lang parigp>vector(3!,i,permtonum(numtoperm(3,i-1)))==vector(3!,i,i-1)
<syntaxhighlight lang="parigp">vector(3!,i,permtonum(numtoperm(3,i-1)))==vector(3!,i,i-1)
vector(4,i,numtoperm(12,random(12!)))
vector(4,i,numtoperm(12,random(12!)))
for(i=1,1e6,numtoperm(144,random(144!)))</lang>
for(i=1,1e6,numtoperm(144,random(144!)))</syntaxhighlight>
{{out}}
{{out}}
<pre>%1 = 1
<pre>%1 = 1
Line 1,401: Line 1,401:
The ntheory module gives us <code>numtoperm</code> and <code>permtonum</code> commands similar to Pari/GP, though in the preferred lexicographic order. Values larger than the native int size are handled as well. The <code>randperm</code> function is useful for random permutations, using a Knuth shuffle and a Chacha/20 CSPRNG supplying randomness. A Macbook takes a bit under 4 seconds to generate 1 million random permutations of 144 objects, or 8 seconds if inserting into a set to ensure uniqueness.
The ntheory module gives us <code>numtoperm</code> and <code>permtonum</code> commands similar to Pari/GP, though in the preferred lexicographic order. Values larger than the native int size are handled as well. The <code>randperm</code> function is useful for random permutations, using a Knuth shuffle and a Chacha/20 CSPRNG supplying randomness. A Macbook takes a bit under 4 seconds to generate 1 million random permutations of 144 objects, or 8 seconds if inserting into a set to ensure uniqueness.
{{libheader|ntheory}}
{{libheader|ntheory}}
<lang perl>use ntheory qw/:all/;
<syntaxhighlight lang="perl">use ntheory qw/:all/;


my $n = 3;
my $n = 3;
Line 1,421: Line 1,421:
print " Four 4-object random permutations of 100k objects using randperm\n";
print " Four 4-object random permutations of 100k objects using randperm\n";
print join(" ", randperm(100000,4)),"\n" for 1..4;
print join(" ", randperm(100000,4)),"\n" for 1..4;
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,454: Line 1,454:
=={{header|Phix}}==
=={{header|Phix}}==
{{trans|C}}
{{trans|C}}
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_rank</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">get_rank</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
Line 1,486: Line 1,486:
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">12</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">12</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 1,515: Line 1,515:
Their algorithm is efficient and pythons transparent use of arbitrary precision integers allows the Stack Overflow questions limits to be used. (Chopped at four rather than a million random samples although function get_random_ranks(144, 1e6) doesn't take long).
Their algorithm is efficient and pythons transparent use of arbitrary precision integers allows the Stack Overflow questions limits to be used. (Chopped at four rather than a million random samples although function get_random_ranks(144, 1e6) doesn't take long).


<lang python>from math import factorial as fact
<syntaxhighlight lang="python">from math import factorial as fact
from random import randrange
from random import randrange
from textwrap import wrap
from textwrap import wrap
Line 1,600: Line 1,600:
test1('First ordering:', unranker1, ranker1)
test1('First ordering:', unranker1, ranker1)
test1('Second ordering:', unranker2, ranker2)
test1('Second ordering:', unranker2, ranker2)
test2('First ordering, large number of perms:', unranker1)</lang>
test2('First ordering, large number of perms:', unranker1)</syntaxhighlight>


{{out}}
{{out}}
Line 1,674: Line 1,674:
Permutations with small differences in rank are likely to be "similar" in appearance (if rank difference << perm length).
Permutations with small differences in rank are likely to be "similar" in appearance (if rank difference << perm length).


<lang python>from random import randrange
<syntaxhighlight lang="python">from random import randrange
from typing import List
from typing import List


Line 1,777: Line 1,777:
rank = tj_rank(p)
rank = tj_rank(p)
parity = tj_parity(p)
parity = tj_parity(p)
print(f" Rank: {r:10} to perm: {p}, parity: {parity} to rank: {rank:10}")</lang>
print(f" Rank: {r:10} to perm: {p}, parity: {parity} to rank: {rank:10}")</syntaxhighlight>


{{out}}
{{out}}
Line 1,803: Line 1,803:
Functions ranker1 and ranker2 above, can be changed from the recursive form as used in the paper to iterative versions if they are replaced with the following code that yields the same results:
Functions ranker1 and ranker2 above, can be changed from the recursive form as used in the paper to iterative versions if they are replaced with the following code that yields the same results:


<lang python>def ranker1(n, pi, pi1):
<syntaxhighlight lang="python">def ranker1(n, pi, pi1):
if n == 1:
if n == 1:
return 0
return 0
Line 1,819: Line 1,819:
pi1[s], pi1[i] = pi1[i], pi1[s]
pi1[s], pi1[i] = pi1[i], pi1[s]
result += s * fact(i)
result += s * fact(i)
return result</lang>
return result</syntaxhighlight>


=={{header|Racket}}==
=={{header|Racket}}==
Mimicking the Haskell style.
Mimicking the Haskell style.
<lang racket>
<syntaxhighlight lang="racket">
#lang racket (require math)
#lang racket (require math)
(define-syntax def (make-rename-transformer #'match-define-values))
(define-syntax def (make-rename-transformer #'match-define-values))
Line 1,839: Line 1,839:
(* (for/sum ([x xs] #:when (< x x0)) 1)
(* (for/sum ([x xs] #:when (< x x0)) 1)
(factorial (length xs))))]))
(factorial (length xs))))]))
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,878: Line 1,878:
It is easy generate random inversion vector without BigInt.
It is easy generate random inversion vector without BigInt.


<lang perl6>use v6;
<syntaxhighlight lang="raku" line>use v6;


sub rank2inv ( $rank, $n = * ) {
sub rank2inv ( $rank, $n = * ) {
Line 1,927: Line 1,927:
.say
.say
};
};
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,960: Line 1,960:
Since this REXX program generates permutations without recursive calls,
Since this REXX program generates permutations without recursive calls,
testing for the limit for a &nbsp; ''stack overflow'' &nbsp; wouldn't be necessary using this REXX program.
testing for the limit for a &nbsp; ''stack overflow'' &nbsp; wouldn't be necessary using this REXX program.
<lang rexx>/*REXX program displays permutations of N number of objects (1, 2, 3, ···). */
<syntaxhighlight lang="rexx">/*REXX program displays permutations of N number of objects (1, 2, 3, ···). */
parse arg N y seed . /*obtain optional arguments from the CL*/
parse arg N y seed . /*obtain optional arguments from the CL*/
if N=='' | N=="," then N= 4 /*Not specified? Then use the default.*/
if N=='' | N=="," then N= 4 /*Not specified? Then use the default.*/
Line 1,997: Line 1,997:
end /*p*/
end /*p*/
parse value @.p @.q with @.q @.p
parse value @.p @.q with @.q @.p
return 1</lang>
return 1</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
<pre>
Line 2,029: Line 2,029:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Permutations/Rank of a permutation
# Project : Permutations/Rank of a permutation


Line 2,071: Line 2,071:
last = last - 1
last = last - 1
end
end
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
Line 2,101: Line 2,101:


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>class Permutation
<syntaxhighlight lang="ruby">class Permutation
include Enumerable
include Enumerable
attr_reader :num_elements, :size
attr_reader :num_elements, :size
Line 2,138: Line 2,138:
n.zero? ? 1 : n.downto(1).inject(:*)
n.zero? ? 1 : n.downto(1).inject(:*)
end
end
end</lang>
end</syntaxhighlight>
Demo:
Demo:
<lang ruby>puts "All permutations of 3 items from and back to rank."
<syntaxhighlight lang="ruby">puts "All permutations of 3 items from and back to rank."
perm = Permutation.new(3)
perm = Permutation.new(3)
(0...perm.size).each{|num| puts "#{num} --> #{prm=perm.unrank(num)} --> #{perm.rank(prm)}"}
(0...perm.size).each{|num| puts "#{num} --> #{prm=perm.unrank(num)} --> #{perm.rank(prm)}"}
Line 2,159: Line 2,159:
p prm = perm.unrank(r)
p prm = perm.unrank(r)
p perm.rank(prm) == r
p perm.rank(prm) == r
end</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre style="overflow:auto">
<pre style="overflow:auto">
Line 2,193: Line 2,193:


=={{header|Scala}}==
=={{header|Scala}}==
<lang scala>import scala.math._
<syntaxhighlight lang="scala">import scala.math._


def factorial(n: Int): BigInt = {
def factorial(n: Int): BigInt = {
Line 2,215: Line 2,215:
case Nil => BigInt(0)
case Nil => BigInt(0)
case x :: rest => factorial(rest.size) * rest.count(ord.lt(_, x)) + permutationToIndex(rest)
case x :: rest => factorial(rest.size) * rest.count(ord.lt(_, x)) + permutationToIndex(rest)
}</lang>
}</syntaxhighlight>
<lang scala>def check(n: Int, x: BigInt): Boolean = {
<syntaxhighlight lang="scala">def check(n: Int, x: BigInt): Boolean = {
val perm = indexToPermutation(n, x)
val perm = indexToPermutation(n, x)
val xOut = permutationToIndex(perm)
val xOut = permutationToIndex(perm)
Line 2,227: Line 2,227:
} else {
} else {
println("Failed")
println("Failed")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 2,241: Line 2,241:
=={{header|Tcl}}==
=={{header|Tcl}}==
{{trans|D}}
{{trans|D}}
<lang tcl># A functional swap routine
<syntaxhighlight lang="tcl"># A functional swap routine
proc swap {v idx1 idx2} {
proc swap {v idx1 idx2} {
lset v $idx2 [lindex $v $idx1][lset v $idx1 [lindex $v $idx2];subst ""]
lset v $idx2 [lindex $v $idx1][lset v $idx1 [lindex $v $idx2];subst ""]
Line 2,274: Line 2,274:
}}
}}
return [apply $mrRank1 $mrRank1 [llength $vec] $vec $inv]
return [apply $mrRank1 $mrRank1 [llength $vec] $vec $inv]
}</lang>
}</syntaxhighlight>
Demonstrating:
Demonstrating:
<lang tcl>proc factorial {n} {
<syntaxhighlight lang="tcl">proc factorial {n} {
for {set result 1; set i 2} {$i <= $n} {incr i} {
for {set result 1; set i 2} {$i <= $n} {incr i} {
set result [expr {$result * $i}]
set result [expr {$result * $i}]
Line 2,299: Line 2,299:
puts [format "%20lld: \[%s\] = %lld" \
puts [format "%20lld: \[%s\] = %lld" \
$rank [join $items2 ", "] [computeRank $items2]]
$rank [join $items2 ", "] [computeRank $items2]]
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre style="overflow:auto">
<pre style="overflow:auto">
Line 2,333: Line 2,333:
</pre>
</pre>
The above code is not a particularly good use of a random number generator; the Tcl PRNG does not generate enough bits of true randomness per call to <code>rand()</code> for it to be useful in such a simplistic approach. However, it will do for the purposes of demonstration. A more sophisticated RNG is this one:
The above code is not a particularly good use of a random number generator; the Tcl PRNG does not generate enough bits of true randomness per call to <code>rand()</code> for it to be useful in such a simplistic approach. However, it will do for the purposes of demonstration. A more sophisticated RNG is this one:
<lang tcl>proc uniform {limit} {
<syntaxhighlight lang="tcl">proc uniform {limit} {
set bits [expr {ceil(log($limit)/log(2))+10}]
set bits [expr {ceil(log($limit)/log(2))+10}]
for {set b [set r 0]} {$b < $bits} {incr b 16} {
for {set b [set r 0]} {$b < $bits} {incr b 16} {
Line 2,339: Line 2,339:
}
}
return [expr {$r % $limit}]
return [expr {$r % $limit}]
}</lang>
}</syntaxhighlight>
===Addressing the extra credit===
===Addressing the extra credit===
The technique above can generate any random permutation of a list, but an equally viable approach (and one especially suitable to the SO question where the number of required permutations is small with respect to the number of possible permutations) would be to use a [[Knuth shuffle]] on a list and just use that with a quick check for repetitions, which could be implemented using a simple hashing check. (On the other hand, building a hash table of a million strings of 144 characters would not be too awkward on modern hardware.)
The technique above can generate any random permutation of a list, but an equally viable approach (and one especially suitable to the SO question where the number of required permutations is small with respect to the number of possible permutations) would be to use a [[Knuth shuffle]] on a list and just use that with a quick check for repetitions, which could be implemented using a simple hashing check. (On the other hand, building a hash table of a million strings of 144 characters would not be too awkward on modern hardware.)
Line 2,346: Line 2,346:
{{trans|Kotlin}}
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "random" for Random
<syntaxhighlight lang="ecmascript">import "random" for Random
import "/fmt" for Fmt
import "/fmt" for Fmt


Line 2,408: Line 2,408:
getPermutation.call(r, 12, tv)
getPermutation.call(r, 12, tv)
Fmt.print("$9d -> $n -> $d", r, tv, getRank.call(12, tv))
Fmt.print("$9d -> $n -> $d", r, tv, getRank.call(12, tv))
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 2,452: Line 2,452:
=={{header|zkl}}==
=={{header|zkl}}==
{{trans|D}}
{{trans|D}}
<lang zkl>fcn computePermutation(items,rank){ // in place permutation of items
<syntaxhighlight lang="zkl">fcn computePermutation(items,rank){ // in place permutation of items
foreach n in ([items.len()..1,-1]){
foreach n in ([items.len()..1,-1]){
r:=rank%n;
r:=rank%n;
Line 2,459: Line 2,459:
}
}
items
items
}</lang>
}</syntaxhighlight>
<lang zkl> /// Return the rank of a permutation.
<syntaxhighlight lang="zkl"> /// Return the rank of a permutation.
fcn computeRank(perm){
fcn computeRank(perm){
N,p2,inv := perm.len(), perm.copy(), List.createLong(N,0);
N,p2,inv := perm.len(), perm.copy(), List.createLong(N,0);
Line 2,471: Line 2,471:
s + n*self.fcn(i,p2,inv);
s + n*self.fcn(i,p2,inv);
}(N,p2,inv);
}(N,p2,inv);
}</lang>
}</syntaxhighlight>
<lang zkl> // do some random permutations of 4
<syntaxhighlight lang="zkl"> // do some random permutations of 4
fcn factorial(n){ (1).reduce(n,'*) }
fcn factorial(n){ (1).reduce(n,'*) }
items,max:=(4).toList(),factorial(items.len()); // (0,1,2,3), read only
items,max:=(4).toList(),factorial(items.len()); // (0,1,2,3), read only
Line 2,486: Line 2,486:
p:=computePermutation(items.copy(),rank);
p:=computePermutation(items.copy(),rank);
println("%12d: %s = %d".fmt(rank,p,computeRank(p)));
println("%12d: %s = %d".fmt(rank,p,computeRank(p)));
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 2,503: Line 2,503:
computePermutation works fine with BigInts but there is no current way to generate a random number in range to 250!
computePermutation works fine with BigInts but there is no current way to generate a random number in range to 250!
If a 63 bit range was OK, then (but don't hold your breath, this takes a while):
If a 63 bit range was OK, then (but don't hold your breath, this takes a while):
<lang zkl>var [const] BN=Import("zklBigNum"); // libGMP
<syntaxhighlight lang="zkl">var [const] BN=Import("zklBigNum"); // libGMP
one44Bang:=BN(144).factorial(); // 250 digits
one44Bang:=BN(144).factorial(); // 250 digits
// Needed: random number [0,one44Bang)
// Needed: random number [0,one44Bang)
do(0d1_000_000){
do(0d1_000_000){
p:=computePermutation((144).toList().copy(),(0).random((0).MAX));
p:=computePermutation((144).toList().copy(),(0).random((0).MAX));
}</lang>
}</syntaxhighlight>
and the TCL idea of shuffles (List.shuffle()) makes more sense.
and the TCL idea of shuffles (List.shuffle()) makes more sense.