September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -14,8 +14,10 @@ Note: The SteinhausJohnsonTrotter algorithm generates successive permutati
* [[wp:SteinhausJohnsonTrotter algorithm|SteinhausJohnsonTrotter algorithm]]
* [http://www.cut-the-knot.org/Curriculum/Combinatorics/JohnsonTrotter.shtml Johnson-Trotter Algorithm Listing All Permutations]
* [http://stackoverflow.com/a/29044942/10562 Correction to] Heap's algorithm as presented in Wikipedia and widely distributed.
* [http://www.gutenberg.org/files/18567/18567-h/18567-h.htm#ch7] Tintinnalogia
;Related task:
*   [[Matrix arithmetic]]
*   [[Gray code]]
<br><br>

View file

@ -0,0 +1,59 @@
(defstruct (directed-number (:conc-name dn-))
(number nil :type integer)
(direction nil :type (member :left :right)))
(defmethod print-object ((dn directed-number) stream)
(ecase (dn-direction dn)
(:left (format stream "<~D" (dn-number dn)))
(:right (format stream "~D>" (dn-number dn)))))
(defun dn> (dn1 dn2)
(declare (directed-number dn1 dn2))
(> (dn-number dn1) (dn-number dn2)))
(defun dn-reverse-direction (dn)
(declare (directed-number dn))
(setf (dn-direction dn) (ecase (dn-direction dn)
(:left :right)
(:right :left))))
(defun make-directed-numbers-upto (upto)
(let ((numbers (make-array upto :element-type 'integer)))
(dotimes (n upto numbers)
(setf (aref numbers n) (make-directed-number :number (1+ n) :direction :left)))))
(defun max-mobile-pos (numbers)
(declare ((vector directed-number) numbers))
(loop with pos-limit = (1- (length numbers))
with max-value and max-pos
for num across numbers
for pos from 0
do (ecase (dn-direction num)
(:left (when (and (plusp pos) (dn> num (aref numbers (1- pos)))
(or (null max-value) (dn> num max-value)))
(setf max-value num
max-pos pos)))
(:right (when (and (< pos pos-limit) (dn> num (aref numbers (1+ pos)))
(or (null max-value) (dn> num max-value)))
(setf max-value num
max-pos pos))))
finally (return max-pos)))
(defun permutations (upto)
(loop with numbers = (make-directed-numbers-upto upto)
for max-mobile-pos = (max-mobile-pos numbers)
for sign = 1 then (- sign)
do (format t "~A sign: ~:[~;+~]~D~%" numbers (plusp sign) sign)
while max-mobile-pos
do (let ((max-mobile-number (aref numbers max-mobile-pos)))
(ecase (dn-direction max-mobile-number)
(:left (rotatef (aref numbers (1- max-mobile-pos))
(aref numbers max-mobile-pos)))
(:right (rotatef (aref numbers max-mobile-pos)
(aref numbers (1+ max-mobile-pos)))))
(loop for n across numbers
when (dn> n max-mobile-number)
do (dn-reverse-direction n)))))
(permutations 3)
(permutations 4)

View file

@ -0,0 +1,67 @@
S" fsl-util.fs" REQUIRED
S" fsl/dynmem.seq" REQUIRED
cell darray p{
: sgn
DUP 0 > IF
DROP 1
ELSE 0 < IF
-1
ELSE
0
THEN THEN ;
: arr-swap {: addr1 addr2 | tmp -- :}
addr1 @ TO tmp
addr2 @ addr1 !
tmp addr2 ! ;
: perms {: n xt | my-i k s -- :}
& p{ n 1+ }malloc malloc-fail? ABORT" perms :: out of memory"
0 p{ 0 } !
n 1+ 1 DO
I NEGATE p{ I } !
LOOP
1 TO s
BEGIN
1 n 1+ DO
p{ I } @ ABS
-1 +LOOP
n 1+ s xt EXECUTE
0 TO k
n 1+ 2 DO
p{ I } @ 0 < ( flag )
p{ I } @ ABS p{ I 1- } @ ABS > ( flag flag )
p{ I } @ ABS p{ k } @ ABS > ( flag flag flag )
AND AND IF
I TO k
THEN
LOOP
n 1 DO
p{ I } @ 0 > ( flag )
p{ I } @ ABS p{ I 1+ } @ ABS > ( flag flag )
p{ I } @ ABS p{ k } @ ABS > ( flag flag flag )
AND AND IF
I TO k
THEN
LOOP
k IF
n 1+ 1 DO
p{ I } @ ABS p{ k } @ ABS > IF
p{ I } @ NEGATE p{ I } !
THEN
LOOP
p{ k } @ sgn k + TO my-i
p{ k } p{ my-i } arr-swap
s NEGATE TO s
THEN
k 0 = UNTIL ;
: .perm ( p0 p1 p2 ... pn n s )
>R
." Perm: [ "
1 DO
. SPACE
LOOP
R> ." ] Sign: " . CR ;
3 ' .perm perms CR
4 ' .perm perms

View file

@ -0,0 +1,59 @@
' version 31-03-2017
' compile with: fbc -s console
Sub perms(n As ULong)
Dim As Long p(n), i, k, s = 1
For i = 1 To n
p(i) = -i
Next
Do
Print "Perm: [ ";
For i = 1 To n
Print Abs(p(i)); " ";
Next
Print "] Sign: "; s
k = 0
For i = 2 To n
If p(i) < 0 Then
If Abs(p(i)) > Abs(p(i -1)) Then
If Abs(p(i)) > Abs(p(k)) Then k = i
End If
End If
Next
For i = 1 To n -1
If p(i) > 0 Then
If Abs(p(i)) > Abs(p(i +1)) Then
If Abs(p(i)) > Abs(p(k)) Then k = i
End If
End If
Next
If k Then
For i = 1 To n
If Abs(p(i)) > Abs(p(k)) Then p(i) = -p(i)
Next
i = k + Sgn(p(k))
Swap p(k), p(i)
s = -s
End If
Loop Until k = 0
End Sub
' ------=< MAIN >=------
perms(3)
print
perms(4)
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -1,14 +1,15 @@
s_permutations :: [a] -> [([a], Int)]
s_permutations = flip zip (cycle [1, -1]) . (foldl aux [[]])
where aux items x = do
(f,item) <- zip (cycle [reverse,id]) items
f (insertEv x item)
insertEv x [] = [[x]]
insertEv x l@(y:ys) = (x:l) : map (y:) (insertEv x ys)
sPermutations :: [a] -> [([a], Int)]
sPermutations = flip zip (cycle [-1, 1]) . foldr aux [[]]
where
aux x items = do
(f, item) <- zip (repeat id) items
f (insertEv x item)
insertEv x [] = [[x]]
insertEv x l@(y:ys) = (x : l) : ((y :) <$> insertEv x ys)
main :: IO ()
main = do
putStrLn "3 items:"
mapM_ print $ s_permutations [0..2]
putStrLn "4 items:"
mapM_ print $ s_permutations [0..3]
mapM_ print $ sPermutations [1 .. 3]
putStrLn "\n4 items:"
mapM_ print $ sPermutations [1 .. 4]

View file

@ -0,0 +1,68 @@
package org.rosettacode.java;
import java.util.Arrays;
import java.util.stream.IntStream;
public class HeapsAlgorithm {
public static void main(String[] args) {
Object[] array = IntStream.range(0, 4)
.boxed()
.toArray();
HeapsAlgorithm algorithm = new HeapsAlgorithm();
algorithm.recursive(array);
System.out.println();
algorithm.loop(array);
}
void recursive(Object[] array) {
recursive(array, array.length, true);
}
void recursive(Object[] array, int n, boolean plus) {
if (n == 1) {
output(array, plus);
} else {
for (int i = 0; i < n; i++) {
recursive(array, n - 1, i == 0);
swap(array, n % 2 == 0 ? i : 0, n - 1);
}
}
}
void output(Object[] array, boolean plus) {
System.out.println(Arrays.toString(array) + (plus ? " +1" : " -1"));
}
void swap(Object[] array, int a, int b) {
Object o = array[a];
array[a] = array[b];
array[b] = o;
}
void loop(Object[] array) {
loop(array, array.length);
}
void loop(Object[] array, int n) {
int[] c = new int[n];
output(array, true);
boolean plus = false;
for (int i = 0; i < n; ) {
if (c[i] < i) {
if (i % 2 == 0) {
swap(array, 0, i);
} else {
swap(array, c[i], i);
}
output(array, plus);
plus = !plus;
c[i]++;
i = 0;
} else {
c[i] = 0;
i++;
}
}
}
}

View file

@ -0,0 +1,46 @@
// version 1.1.2
fun johnsonTrotter(n: Int): Pair<List<IntArray>, List<Int>> {
val p = IntArray(n) { it } // permutation
val q = IntArray(n) { it } // inverse permutation
val d = IntArray(n) { -1 } // direction = 1 or -1
var sign = 1
val perms = mutableListOf<IntArray>()
val signs = mutableListOf<Int>()
fun permute(k: Int) {
if (k >= n) {
perms.add(p.copyOf())
signs.add(sign)
sign *= -1
return
}
permute(k + 1)
for (i in 0 until k) {
val z = p[q[k] + d[k]]
p[q[k]] = z
p[q[k] + d[k]] = k
q[z] = q[k]
q[k] += d[k]
permute(k + 1)
}
d[k] *= -1
}
permute(0)
return perms to signs
}
fun printPermsAndSigns(perms: List<IntArray>, signs: List<Int>) {
for ((i, perm) in perms.withIndex()) {
println("${perm.contentToString()} -> sign = ${signs[i]}")
}
}
fun main(args: Array<String>) {
val (perms, signs) = johnsonTrotter(3)
printPermsAndSigns(perms, signs)
println()
val (perms2, signs2) = johnsonTrotter(4)
printPermsAndSigns(perms2, signs2)
}

View file

@ -0,0 +1,23 @@
function spermutations(integer p, integer i)
-- generate the i'th permutation of [1..p]:
-- first obtain the appropriate permutation of [1..p-1],
-- then insert p/move it down k(=0..p-1) places from the end.
integer k = mod(i-1,2*p)
if k>=p then k=2*p-1-k end if
sequence res
integer parity
if p>1 then
{res,parity} = spermutations(p-1,floor((i-1)/p)+1)
res = res[1..length(res)-k]&p&res[length(res)-k+1..$]
else
res = {1}
end if
return {res,iff(and_bits(i,1)?1:-1)}
end function
for p=1 to 4 do
printf(1,"==%d==\n",p)
for i=1 to factorial(p) do
?{i,spermutations(p,i)}
end for
end for

View file

@ -1,20 +1,20 @@
func perms(n) {
var perms = [[+1]]
n.times { |x|
var sign = -1;
for x in (1..n) {
var sign = -1
perms = gather {
for s,*p in perms {
var r = (0 .. p.len);
var r = (0 .. p.len)
take((s < 0 ? r : r.flip).map {|i|
[sign *= -1, p[0..i-1], x, p[i..p.end]]
[sign *= -1, p[^i], x, p[i..p.end]]
}...)
}
}
}
perms;
perms
}
var n = 4;
var n = 4
for p in perms(n) {
var s = p.shift
s > 0 && (s = '+1')

View file

@ -0,0 +1,13 @@
fcn permute(seq)
{
insertEverywhere := fcn(x,list){ //(x,(a,b))-->((x,a,b),(a,x,b),(a,b,x))
(0).pump(list.len()+1,List,'wrap(n){list[0,n].extend(x,list[n,*]) })};
insertEverywhereB := fcn(x,t){ //--> insertEverywhere().reverse()
[t.len()..-1,-1].pump(t.len()+1,List,'wrap(n){t[0,n].extend(x,t[n,*])})};
seq.reduce('wrap(items,x){
f := Utils.Helpers.cycle(insertEverywhereB,insertEverywhere);
items.pump(List,'wrap(item){f.next()(x,item)},
T.fp(Void.Write,Void.Write));
},T(T));
}

View file

@ -0,0 +1,6 @@
p := permute(T(1,2,3));
p.println();
p := permute([1..4]);
p.len().println();
p.toString(*).println()

View file

@ -0,0 +1,21 @@
fcn [private] _permuteW(seq){ // lazy version
N:=seq.len(); NM1:=N-1;
ds:=(0).pump(N,List,T(Void,-1)).copy(); ds[0]=0; // direction to move e: -1,0,1
es:=(0).pump(N,List).copy(); // enumerate seq
while(1) {
vm.yield(es.pump(List,seq.__sGet));
// find biggest e with d!=0
reg i=Void, c=-1;
foreach n in (N){ if(ds[n] and es[n]>c) { c=es[n]; i=n; } }
if(Void==i) return();
d:=ds[i]; j:=i+d;
es.swap(i,j); ds.swap(i,j); // d tracks e
if(j==NM1 or j==0 or es[j+d]>c) ds[j]=0;
foreach e in (N){ if(es[e]>c) ds[e]=(i-e).sign }
}
}
fcn permuteW(seq) { Utils.Generator(_permuteW,seq) }

View file

@ -0,0 +1 @@
foreach p in (permuteW(T("a","b","c"))){ println(p) }