tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View file

@ -0,0 +1,19 @@
A [http://mathworld.wolfram.com/Derangement.html derangement] is a permutation of the order of distinct items in which ''no item appears in its original place''.
For example, the only two derangements of the three items (0, 1, 2) are (1, 2, 0), and (2, 0, 1).
The number of derangements of ''n'' distinct items is known as the subfactorial of ''n'', sometimes written as !''n''. There are various ways to [[wp:Derangement#Counting_derangements|calculate]] !''n''.
;Task
The task is to:
# Create a named function/method/subroutine/... to generate derangements of the integers ''0..n-1'', (or ''1..n'' if you prefer).
# Generate ''and show'' all the derangements of 4 integers using the above routine.
# Create a function that calculates the subfactorial of ''n'', !''n''.
# Print and show a table of the ''counted'' number of derangements of ''n'' vs. the calculated !''n'' for n from 0..9 inclusive.
As an optional stretch goal:
:* Calculate !''20''.
;Cf.
* [[Anagrams/Deranged anagrams]]
* [[Best shuffle]]

View file

@ -0,0 +1,54 @@
with Ada.Text_IO; use Ada.Text_IO;
procedure DePermute is
type U64 is mod 2**64;
type Num is range 0 .. 20;
type NumList is array (Natural range <>) of Num;
type PtNumList is access all NumList;
package IO is new Ada.Text_IO.Integer_IO (Num);
package UIO is new Ada.Text_IO.Modular_IO (U64);
function deranged (depth : Natural; list : PtNumList;
show : Boolean) return U64 is
tmp : Num; count : U64 := 0;
begin
if depth = list'Length then
if show then
for i in list'Range loop IO.Put (list (i), 2); end loop;
New_Line;
end if; return 1;
end if;
for i in reverse depth .. list'Last loop
if Num (i + 1) /= list (depth) then
tmp := list (i); list (i) := list (depth); list (depth) := tmp;
count := count + deranged (depth + 1, list, show);
tmp := list (i); list (i) := list (depth); list (depth) := tmp;
end if;
end loop;
return count;
end deranged;
function gen_n (len : Natural; show : Boolean) return U64 is
list : PtNumList;
begin
list := new NumList (0 .. len - 1);
for i in list'Range loop list (i) := Num (i + 1); end loop;
return deranged (0, list, show);
end gen_n;
function sub_fact (n : Natural) return U64 is begin
if n < 2 then return U64 (1 - n);
else return (sub_fact (n - 1) + sub_fact (n - 2)) * U64 (n - 1);
end if;
end sub_fact;
count : U64;
begin
Put_Line ("Deranged 4:");
count := gen_n (4, True);
Put_Line ("List vs. calc:");
for i in Natural range 0 .. 9 loop
IO.Put (Num (i), 1); UIO.Put (gen_n (i, False), 7);
UIO.Put (sub_fact (i), 7); New_Line;
end loop;
Put_Line ("!20 = " & U64'Image (sub_fact (20)));
end DePermute;

View file

@ -0,0 +1,96 @@
#NoEnv
SetBatchLines -1
Process, Priority,, high
output := "Derangements for 1, 2, 3, 4:`n"
obj := [1, 2, 3, 4], objS := obj.Clone()
Loop ; permute 4
{
obj := perm_NextObj(Obj)
If !obj
break
For k, v in obj
if ( objS[k] = v )
continue 2
output .= ObjDisp(obj) "`n"
}
output .= "`nTable of n, counted, calculated derangements:`n"
Loop 10 ; Count !n
{
obj := []
count := 0
output .= A_Tab . (i := A_Index-1) . A_Tab
Loop % i
obj[A_Index] := A_Index
objS := obj.Clone()
Loop
{
obj := perm_NextObj(Obj)
If !obj
break
For k, v in obj
if ( objS[k] = v )
continue 2
count++
}
output .= count . A_Tab . cd(i) . "`n"
}
output .= "`nApproximation of !20: " . cd(20)
MsgBox % Clipboard := output
perm_NextObj(obj){ ; next lexicographic permutation
p := 0, objM := ObjMaxIndex(obj)
Loop % objM
{
If A_Index=1
continue
t := obj[objM+1-A_Index]
n := obj[objM+2-A_Index]
If ( t < n )
{
p := objM+1-A_Index, pC := obj[p]
break
}
}
If !p
return false
Loop
{
t := obj[objM+1-A_Index]
If ( t > pC )
{
n := objM+1-A_Index, nC := obj[n]
break
}
}
obj[n] := pC, obj[p] := nC
return ObjReverse(obj, objM-p)
}
ObjReverse(Obj, tail){
o := ObjClone(Obj), ObjM := ObjMaxIndex(O)
Loop % tail
o[ObjM-A_Index+1] := Obj[ObjM+A_Index-tail]
return o
}
ObjDisp(obj){
For k, v in obj
s .= v ", "
return SubStr(s, 1, strLen(s)-2)
}
cd(n){ ; Count Derangements
static e := 2.71828182845904523536028747135
return n ? floor(ft(n)/e + 1/2) : 1
}
ft(n){ ; FacTorial
a := 1
Loop % n
a *= A_Index
return a
}

View file

@ -0,0 +1,75 @@
PRINT"Derangements for the numbers 0,1,2,3 are:"
Count% = FN_Derangement_Generate(4,TRUE)
PRINT'"Table of n, counted derangements, calculated derangements :"
FOR I% = 0 TO 9
PRINT I%, FN_Derangement_Generate(I%,FALSE), FN_SubFactorial(I%)
NEXT
PRINT'"There is no long int in BBC BASIC!"
PRINT"!20 = ";FN_SubFactorial(20)
END
DEF FN_Derangement_Generate(N%, fPrintOut)
LOCAL A%(), O%(), C%, D%, I%, J%
IF N% = 0 THEN = 1
DIM A%(N%-1), O%(N%-1)
FOR I% = 0 TO N%-1 : A%(I%) = I% : NEXT
O%() = A%()
FOR I% = 0 TO FN_Factorial(DIM(A%(),1)+1)-1
PROC_NextPermutation(A%())
D% = TRUE
FOR J%=0 TO N%-1
IF A%(J%) = O%(J%) THEN D% = FALSE
NEXT
IF D% THEN
C% += 1
IF fPrintOut THEN
FOR K% = 0 TO N%-1
PRINT ;A%(K%);" ";
NEXT
PRINT
ENDIF
ENDIF
NEXT
= C%
DEF PROC_NextPermutation(A%())
LOCAL first, last, elementcount, pos
elementcount = DIM(A%(),1)
IF elementcount < 1 THEN ENDPROC
pos = elementcount-1
WHILE A%(pos) >= A%(pos+1)
pos -= 1
IF pos < 0 THEN
PROC_Permutation_Reverse(A%(), 0, elementcount)
ENDPROC
ENDIF
ENDWHILE
last = elementcount
WHILE A%(last) <= A%(pos)
last -= 1
ENDWHILE
SWAP A%(pos), A%(last)
PROC_Permutation_Reverse(A%(), pos+1, elementcount)
ENDPROC
DEF PROC_Permutation_Reverse(A%(), firstindex, lastindex)
LOCAL first, last
first = firstindex
last = lastindex
WHILE first < last
SWAP A%(first), A%(last)
first += 1
last -= 1
ENDWHILE
ENDPROC
DEF FN_Factorial(N) : IF (N = 1) OR (N = 0) THEN =1 ELSE = N * FN_Factorial(N-1)
DEF FN_SubFactorial(N) : IF N=0 THEN =1 ELSE =N*FN_SubFactorial(N-1)+-1^N
REM Or you could use:
REM DEF FN_SubFactorial(N) : IF N<1 THEN =1 ELSE =(N-1)*(FN_SubFactorial(N-1)+FN_SubFactorial(N-2))

View file

@ -0,0 +1,26 @@
Derangements for the numbers 0,1,2,3 are:
1 0 3 2
1 2 3 0
1 3 0 2
2 0 3 1
2 3 0 1
2 3 1 0
3 0 1 2
3 2 0 1
3 2 1 0
Table of n, counted derangements, calculated derangements :
0 1 1
1 0 0
2 1 1
3 2 2
4 9 9
5 44 44
6 265 265
7 1854 1854
8 14833 14833
9 133496 133496
There is no long int in BBC BASIC!
!20 = 8.95014632E17
>

View file

@ -0,0 +1,57 @@
#include <stdio.h>
typedef unsigned long long LONG;
LONG deranged(int depth, int len, int *d, int show)
{
int i;
char tmp;
LONG count = 0;
if (depth == len) {
if (show) {
for (i = 0; i < len; i++) putchar(d[i] + 'a');
putchar('\n');
}
return 1;
}
for (i = len - 1; i >= depth; i--) {
if (i == d[depth]) continue;
tmp = d[i]; d[i] = d[depth]; d[depth] = tmp;
count += deranged(depth + 1, len, d, show);
tmp = d[i]; d[i] = d[depth]; d[depth] = tmp;
}
return count;
}
LONG gen_n(int n, int show)
{
LONG i;
int a[1024]; /* 1024 ought to be big enough for anybody */
for (i = 0; i < n; i++) a[i] = i;
return deranged(0, n, a, show);
}
LONG sub_fact(int n)
{
return n < 2 ? 1 - n : (sub_fact(n - 1) + sub_fact(n - 2)) * (n - 1);
}
int main()
{
int i;
printf("Deranged Four:\n");
gen_n(4, 1);
printf("\nCompare list vs calc:\n");
for (i = 0; i < 10; i++)
printf("%d:\t%llu\t%llu\n", i, gen_n(i, 0), sub_fact(i));
printf("\nfurther calc:\n");
for (i = 10; i <= 20; i++)
printf("%d: %llu\n", i, sub_fact(i));
return 0;
}

View file

@ -0,0 +1,65 @@
import std.stdio, std.algorithm, std.typecons, std.array,
std.conv, std.range, std.traits;
auto derangements(in size_t n, in bool countOnly=false)
/*pure nothrow*/ {
size_t[] seq = iota(n).array();
auto ori = seq.idup;
size_t[][] all;
size_t cnt = n == 0;
foreach (tot; 0 .. fact(n)-1) {
size_t j = n - 2;
while (seq[j] > seq[j + 1])
j--;
size_t k = n - 1;
while (seq[j] > seq[k])
k--;
swap(seq[k], seq[j]);
size_t r = n - 1;
size_t s = j + 1;
while (r > s) {
swap(seq[s], seq[r]);
r--;
s++;
}
j = 0;
while (j < n && seq[j] != ori[j])
j++;
if (j == n) {
if (countOnly)
cnt++;
else
all ~= seq.dup;
}
}
return tuple(all, cnt);
}
T fact(T)(in T n) pure nothrow {
Unqual!T result = 1;
for (Unqual!T i = 2; i <= n; i++)
result *= i;
return result;
}
T subfact(T)(in T n) pure nothrow {
if (0 <= n && n <= 2)
return n != 1;
return (n - 1) * (subfact(n - 1) + subfact(n - 2));
}
void main() {
writeln("derangements for n = 4\n");
foreach (d; derangements(4)[0])
writeln(d);
writeln("\ntable of n vs counted vs calculated derangements\n");
foreach (i; 0 .. 10)
writefln("%s %-7s%-7s", i, derangements(i, 1)[1], subfact(i));
writefln("\n!20 = %s", subfact(20L));
}

View file

@ -0,0 +1,47 @@
import std.stdio, std.algorithm, std.typecons, std.array,
std.conv, std.range, std.traits;
auto derangementsR(in size_t n, in bool countOnly=false) {
auto seq = iota(n).array();
immutable ori = seq.idup;
const(size_t[])[] res;
size_t cnt;
void perms(in size_t[] s, in size_t[] pre=null) nothrow {
if (s.length) {
foreach (i, c; s)
perms(s[0 .. i] ~ s[i + 1 .. $], pre ~ c);
} else if (mismatch!q{a != b}(pre, ori)[0].length == 0) {
if (countOnly) cnt++;
else res ~= pre;
}
}
perms(seq);
return tuple(res, cnt);
}
T fact(T)(in T n) pure nothrow {
Unqual!T result = 1;
for (Unqual!T i = 2; i <= n; i++)
result *= i;
return result;
}
T subfact(T)(in T n) pure nothrow {
if (0 <= n && n <= 2)
return n != 1;
return (n - 1) * (subfact(n - 1) + subfact(n - 2));
}
void main() {
writeln("derangements for n = 4\n");
foreach (const d; derangementsR(4)[0])
writeln(d);
writeln("\ntable of n vs counted vs calculated derangements\n");
foreach (i; 0 .. 10)
writefln("%s %-7s%-7s", i, derangementsR(i,1)[1], subfact(i));
writefln("\n!20 = %s", subfact(20L));
}

View file

@ -0,0 +1,35 @@
# All of this is built-in
Derangements([1 .. 4]);
# [ [ 2, 1, 4, 3 ], [ 2, 3, 4, 1 ], [ 2, 4, 1, 3 ], [ 3, 1, 4, 2 ], [ 3, 4, 1, 2 ], [ 3, 4, 2, 1 ],
# [ 4, 1, 2, 3 ], [ 4, 3, 1, 2 ], [ 4, 3, 2, 1 ] ]
Size(last);
# 9
NrDerangements([1 .. 4]);
# 9
# An implementation using formula D(n + 1) = n*(D(n) + D(n - 1))
NrDerangementsAlt_memo := [1, 0];
NrDerangementsAlt := function(n)
if not IsBound(NrDerangementsAlt_memo[n + 1]) then
NrDerangementsAlt_memo[n + 1] := (n - 1)*(NrDerangementsAlt(n - 1) + NrDerangementsAlt(n - 2));
fi;
return NrDerangementsAlt_memo[n + 1];
end;
L := List([0 .. 9]);
PrintArray(TransposedMat([L,
List(L, n -> Size(Derangements([1 .. n]))),
List(L, n -> NrDerangements([1 .. n])),
List(L, NrDerangementsAlt)]));
# [ [ 0, 1, 1, 1 ],
# [ 1, 0, 0, 0 ],
# [ 2, 1, 1, 1 ],
# [ 3, 2, 2, 2 ],
# [ 4, 9, 9, 9 ],
# [ 5, 44, 44, 44 ],
# [ 6, 265, 265, 265 ],
# [ 7, 1854, 1854, 1854 ],
# [ 8, 14833, 14833, 14833 ],
# [ 9, 133496, 133496, 133496 ] ]

View file

@ -0,0 +1,71 @@
package main
import (
"fmt"
"math/big"
)
// task 1: function returns list of derangements of n integers
func dList(n int) (r [][]int) {
a := make([]int, n)
for i := range a {
a[i] = i
}
// recursive closure permutes a
var recurse func(last int)
recurse = func(last int) {
if last == 0 {
// bottom of recursion. you get here once for each permutation.
// test if permutation is deranged.
for j, v := range a {
if j == v {
return // no, ignore it
}
}
// yes, save a copy
r = append(r, append([]int{}, a...))
return
}
for i := last; i >= 0; i-- {
a[i], a[last] = a[last], a[i]
recurse(last - 1)
a[i], a[last] = a[last], a[i]
}
}
recurse(n - 1)
return
}
// task 3: function computes subfactorial of n
func subFact(n int) *big.Int {
if n == 0 {
return big.NewInt(1)
} else if n == 1 {
return big.NewInt(0)
}
d0 := big.NewInt(1)
d1 := big.NewInt(0)
f := new(big.Int)
for i, n64 := int64(1), int64(n); i < n64; i++ {
d0, d1 = d1, d0.Mul(f.SetInt64(i), d0.Add(d0, d1))
}
return d1
}
func main() {
// task 2:
fmt.Println("Derangements of 4 integers")
for _, d := range dList(4) {
fmt.Println(d)
}
// task 4:
fmt.Println("\nNumber of derangements")
fmt.Println("N Counted Calculated")
for n := 0; n <= 9; n++ {
fmt.Printf("%d %8d %11s\n", n, len(dList(n)), subFact(n).String())
}
// stretch (sic)
fmt.Println("\n!20 =", subFact(20))
}

View file

@ -0,0 +1,9 @@
def fact = { n -> [1,(1..<(n+1)).inject(1) { prod, i -> prod * i }].max() }
def subfact
subfact = { BigInteger n -> (n == 0) ? 1 : (n == 1) ? 0 : ((n-1) * (subfact(n-1) + subfact(n-2))) }
def derangement = { List l ->
def d = []
l.eachPermutation { p -> if ([p,l].transpose().every{ it[0] != it[1] }) d << p }
d
}

View file

@ -0,0 +1,16 @@
def d = derangement([1,2,3,4])
assert d.size() == subfact(4)
d.each { println it }
println """
n # derangements subfactorial
= ============== ============"""
(0..9). each { n ->
def dr = derangement((1..<(n+1)) as List)
def sf = subfact(n)
printf('%1d %14d %12d\n', n, dr.size(), sf)
}
println """
!20 == ${subfact(20)}
"""

View file

@ -0,0 +1,25 @@
import Control.Monad
import Data.List
-- Compute all derangements of a list
derangements xs = filter (and . zipWith (/=) xs) $ permutations xs
-- Compute the number of derangements of n elements
subfactorial 0 = 0
subfactorial 1 = 0
subfactorial 2 = 1
subfactorial n = (n-1) * (subfactorial (n-1) + subfactorial (n-2))
main = do
-- Generate and show all the derangements of four integers
print $ derangements [1..4]
putStrLn ""
-- Print the count of derangements vs subfactorial
forM_ [1..9] $ \i ->
putStrLn $ show (length (derangements [1..i])) ++ " " ++
show (subfactorial i)
putStrLn ""
-- Print the number of derangements in a list of 20 items
print $ subfactorial 20

View file

@ -0,0 +1,3 @@
derangements xs = loop xs xs
where loop [] [] = [[]]
loop (h:hs) xs = [x:ys | x <- xs, x /= h, ys <- loop hs (delete x xs)]

View file

@ -0,0 +1,2 @@
derangement=: (A.&i.~ !)~ (*/ .~: # [) i. NB. task item 1
subfactorial=: ! * +/@(_1&^ % !)@i.@>: NB. task item 3

View file

@ -0,0 +1,25 @@
derangement 4 NB. task item 2
1 0 3 2
1 2 3 0
1 3 0 2
2 0 3 1
2 3 0 1
2 3 1 0
3 0 1 2
3 2 0 1
3 2 1 0
(,subfactorial,#@derangement)"0 i.10 NB. task item 4
0 1 1
1 0 0
2 1 1
3 2 2
4 9 9
5 44 44
6 265 265
7 1854 1854
8 14833 14833
9 133496 133496
subfactorial 20 NB. stretch task
8.95015e17
subfactorial 20x NB. using extended precision
895014631192902121

View file

@ -0,0 +1,95 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Derangement {
public static void main(String[] args) {
System.out.println("derangements for n = 4\n");
for (Object d : (ArrayList)(derangements(4, false)[0])) {
System.out.println(Arrays.toString((int[])d));
}
System.out.println("\ntable of n vs counted vs calculated derangements\n");
for (int i = 0; i < 10; i++) {
int d = ((Integer)derangements(i, true)[1]).intValue();
System.out.printf("%d %-7d %-7d\n", i, d, subfact(i));
}
System.out.printf ("\n!20 = %20d\n", subfact(20L));
}
static Object[] derangements(int n, boolean countOnly) {
int[] seq = iota(n);
int[] ori = Arrays.copyOf(seq, n);
long tot = fact(n);
List<int[]> all = new ArrayList<int[]>();
int cnt = n == 0 ? 1 : 0;
while (--tot > 0) {
int j = n - 2;
while (seq[j] > seq[j + 1]) {
j--;
}
int k = n - 1;
while (seq[j] > seq[k]) {
k--;
}
swap(seq, k, j);
int r = n - 1;
int s = j + 1;
while (r > s) {
swap(seq, s, r);
r--;
s++;
}
j = 0;
while (j < n && seq[j] != ori[j]) {
j++;
}
if (j == n) {
if (countOnly) {
cnt++;
} else {
all.add(Arrays.copyOf(seq, n));
}
}
}
return new Object[]{all, cnt};
}
static long fact(long n) {
long result = 1;
for (long i = 2; i <= n; i++) {
result *= i;
}
return result;
}
static long subfact(long n) {
if (0 <= n && n <= 2) {
return n != 1 ? 1 : 0;
}
return (n - 1) * (subfact(n - 1) + subfact(n - 2));
}
static void swap(int[] arr, int lhs, int rhs) {
int tmp = arr[lhs];
arr[lhs] = arr[rhs];
arr[rhs] = tmp;
}
static int[] iota(int n) {
if (n < 0) {
throw new IllegalArgumentException("iota cannot accept < 0");
}
int[] r = new int[n];
for (int i = 0; i < n; i++) {
r[i] = i;
}
return r;
}
}

View file

@ -0,0 +1,5 @@
Needs["Combinatorica`"]
derangements[n_] := Derangements[Range[n]]
derangements[4]
Table[{NumberOfDerangements[i], Subfactorial[i]}, {i, 9}] // TableForm
Subfactorial[20]

View file

@ -0,0 +1,19 @@
derangements(n)=if(n,round(n!/exp(1)),1);
derange(n)={
my(v=[[]],tmp);
for(level=1,n,
tmp=List();
for(i=1,#v,
for(k=1,n,
if(k==level, next);
for(j=1,level-1,if(v[i][j]==k, next(2)));
listput(tmp, concat(v[i],k))
)
);
v=Vec(tmp)
);
v
};
derange(4)
for(n=0,9,print("!"n" = "#derange(n)" = "derangements(n)))
derangements(20)

View file

@ -0,0 +1,32 @@
sub derange (@result, @avail) {
if not @avail { @result.item }
else {
map {
derange([ @result, @avail[$_] ],
@avail[0 .. $_-1, $_+1 ..^ @avail ])
}, grep { @avail[$_] != @result }, 0 .. @avail-1;
}
}
constant factorial = 1, [\*] 1...*;
# choose k among n, i.e. n! / k! (n-k)!
sub choose ($n, $k) { factorial[$n] div factorial[$k] div factorial[$n - $k] }
sub sub-factorial ($n) {
(state @)[$n] //=
factorial[$n] - [+] gather for 1 .. $n -> $k {
take choose($n, $k) * sub-factorial($n - $k);
}
}
say "Derangements for 4 elements:";
for derange([], 0 .. 3).kv -> $i, @d {
say $i+1, ': ', @d;
}
say "\nCompare list length and calculated table";
say "$_\t{+derange([], ^$_)}\t{sub-factorial($_)}" for 0 .. 9;
say "\nNumber of derangements:";
say "$_:\t{sub-factorial($_)}" for 1 .. 20;

View file

@ -0,0 +1,66 @@
sub d {
# compare this with the deranged() sub to see how to turn procedural
# code into functional one ('functional' as not in 'understandable')
$#_ ? map d([ @{$_[0]}, $_[$_] ], @_[1 .. $_-1, $_+1 .. $#_ ]),
grep { $_[$_] != @{$_[0]} } 1 .. $#_
: $_[0]
}
sub deranged { # same as sub d above, just a readable version to explain method
my ($result, @avail) = @_;
return $result if !@avail; # no more elements to pick from, done
my @list; # list of permutations to return
for my $i (0 .. $#avail) { # try to add each element to result in turn
next if $avail[$i] == @$result; # element n at n-th position, no-no
my $e = splice @avail, $i, 1; # move the n-th element from available to result
push @list, deranged([ @$result, $e ], @avail);
# and recurse down, keep what's returned
splice @avail, $i, 0, $e; # put that element back, try next
}
return @list;
}
sub choose { # choose k among n, i.e. n! / k! (n-k)!
my ($n, $k) = @_;
factorial($n) / factorial($k) / factorial($n - $k)
}
my @fact = (1);
sub factorial {
# //= : standard caching technique. If cached value available,
# return it; else compute, cache and return.
# For this specific task not really necessary.
$fact[ $_[0] ] //= $_[0] * factorial($_[0] - 1)
}
my @subfact;
sub sub_factorial {
my $n = shift;
$subfact[$n] //= do # same caching stuff, try comment out this line
{
# computes deranged without formula, using recursion
my $total = factorial($n); # total permutations
for my $k (1 .. $n) {
# minus the permutations where k items are fixed
# to original location, and the rest deranged
$total -= choose($n, $k) * sub_factorial($n - $k)
}
$total
}
}
print "Derangements for 4 elements:\n";
my @deranged = d([], 0 .. 3);
for (1 .. @deranged) {
print "$_: @{$deranged[$_-1]}\n"
}
print "\nCompare list length and calculated table\n";
for (0 .. 9) {
my @x = d([], 0 .. $_-1);
print $_, "\t", scalar(@x), "\t", sub_factorial($_), "\n"
}
print "\nNumber of derangements:\n";
print "$_:\t", sub_factorial($_), "\n" for 1 .. 20;

View file

@ -0,0 +1,13 @@
(load "@lib/simul.l") # For 'permute'
(de derangements (Lst)
(filter
'((L) (not (find = L Lst)))
(permute Lst) ) )
(de subfact (N)
(if (>= 2 N)
(if (= 1 N) 0 1)
(*
(dec N)
(+ (subfact (dec N)) (subfact (- N 2))) ) ) )

View file

@ -0,0 +1,123 @@
Procedure.q perm(n)
if n=0:ProcedureReturn 1:endif
if n=1:ProcedureReturn 0:endif
ProcedureReturn (perm(n-1)+perm(n-2))*(n-1)
EndProcedure
factFile.s="factorials.txt"
tempFile.s="temp.txt"
drngFile.s="derangements.txt"
DeleteFile(factFile.s)
DeleteFile(tempFile.s)
DeleteFile(drngFile.s)
n=4
; create our storage file
f.s=factFile.s
If CreateFile(2113,f.s)
WriteStringN(2113,"1.2")
WriteStringN(2113,"2.1")
CloseFile(2113)
Else
Debug "not createfile :"+f.s
EndIf
showfactorial=#FALSE
if showfactorial
; cw("nfactorial n ="+str(n))
Debug "nfactorial n ="+str(n)
endif
; build up the factorial combinations
for l=1 to n-2
gosub nfactorial
next
; extract the derangements
; cw("derangements["+str(perm(n))+"] for n="+str(n))
Debug "derangements["+str(perm(n))+"] for n="+str(n)
gosub derangements
; cw("")
Debug ""
; show the first 20 derangements
for i=0 to 20
; cw("derangements["+str(perm(i))+"] for n="+str(i))
Debug "derangements["+str(perm(i))+"] for n="+str(i)
next
end
derangements:
x=0
If ReadFile(2112,factFile.s) and CreateFile(2113,drngFile.s)
repeat
r.s = ReadString(2112)
cs=CountString(r.s,".")
if cs
hit=0
t.s=""
; scan for numbers at their index
for i=1 to cs+1
s.s=StringField(r.s,i,".")
t.s+s.s+"."
if val(s.s)=i:hit+1:endif
next
t.s=rtrim(t.s,".")
; show only those which are valid
if not hit
x+1
; cw(t.s+" "+str(x))
Debug t.s+" "+str(x)
WriteStringN(2113,t.s+" "+str(x))
endif
endif
until eof(2112)
CloseFile(2112)
CloseFile(2113)
Else
Debug "not readfile :"+factFile.s
Debug "not createfile :"+drngFile.s
EndIf
; cw("")
Debug ""
return
nfactorial:
x=0
If ReadFile(2112,factFile.s) and CreateFile(2113,tempFile.s)
repeat
r.s = ReadString(2112)
cs=CountString(r.s,".")
if cs
for j=1 to cs+2
t.s=""
for i=1 to cs+1
s.s=StringField(r.s,i,".")
if i=j
t.s+"."+str(cs+2)+"."+s.s
else
t.s+"."+s.s
endif
next
if j=cs+2:t.s+"."+str(cs+2):endif
t.s=trim(t.s,".")
x+1
if cs+2=n and showfactorial
; cw(t.s+" "+str(x))
Debug t.s+" "+str(x)
endif
WriteStringN(2113,t.s)
next
endif
until eof(2112)
CloseFile(2112)
CloseFile(2113)
Else
Debug "not readfile :"+factFile.s
Debug "not createfile :"+tempFile.s
EndIf
CopyFile(tempFile.s,factFile.s)
DeleteFile(tempFile.s)
return

View file

@ -0,0 +1,57 @@
Procedure.i deranged(depth,lenn,array d(1),show)
Protected count.l,tmp,i
if (depth = lenn)
if (show)
; for i = 0 to lenn-1:so(chr(d(i) + 'a')):next
for i = 0 to lenn-1:Debug chr(d(i) + 'a'):next
; cw("")
Debug ""
endif
ProcedureReturn 1
endif
for i = lenn - 1 to depth step -1
if i = d(depth) :continue:endif
tmp = d(i): d(i) = d(depth): d(depth) = tmp
count + deranged(depth + 1, lenn, d(), show)
tmp = d(i): d(i) = d(depth): d(depth) = tmp
next
ProcedureReturn count
EndProcedure
Procedure.q sub_fact(n)
if n=0:ProcedureReturn 1:endif
if n=1:ProcedureReturn 0:endif
ProcedureReturn (sub_fact(n-1)+sub_fact(n-2))*(n-1)
EndProcedure
Procedure.i gen_n(n,show)
Protected r.i
global dim a(1024)
for i=0 to n-1:a(i)=i:next
ProcedureReturn deranged(0, n, a(), show)
EndProcedure
; cw("Deranged Four:")
Debug "Deranged Four:"
gen_n(4, 1)
; cw("")
Debug ""
; cw("Compare list vs calc:")
Debug "Compare list vs calc:"
for i = 0 to 9
; cw(str(i)+" "+str(gen_n(i, 0))+" "+str(sub_fact(i)))
Debug str(i)+" "+str(gen_n(i, 0))+" "+str(sub_fact(i))
next
; cw("")
Debug ""
; cw("further calc:")
Debug "further calc:"
for i = 10 to 20
; cw(str(i)+" "+str(sub_fact(i)))
Debug str(i)+" "+str(sub_fact(i))
next

View file

@ -0,0 +1,41 @@
from itertools import permutations
import math
def derangements(n):
'All deranged permutations of the integers 0..n-1 inclusive'
return ( perm for perm in permutations(range(n))
if all(indx != p for indx, p in enumerate(perm)) )
def subfact(n):
if n == 2 or n == 0:
return 1
elif n == 1:
return 0
elif 1 <= n <=18:
return round(math.factorial(n) / math.e)
elif n.imag == 0 and n.real == int(n.real) and n > 0:
return (n-1) * ( subfact(n - 1) + subfact(n - 2) )
else:
raise ValueError()
def _iterlen(iter):
'length of an iterator without taking much memory'
l = 0
for x in iter:
l += 1
return l
if __name__ == '__main__':
n = 4
print("Derangements of %s" % (tuple(range(n)),))
for d in derangements(n):
print(" %s" % (d,))
print("\nTable of n vs counted vs calculated derangements")
for n in range(10):
print("%2i %-5i %-5i" %
(n, _iterlen(derangements(n)), subfact(n)))
n = 20
print("\n!%i = %i" % (n, subfact(n)))

View file

@ -0,0 +1,43 @@
/*REXX pgm generates all permutations of N derangements & subfactorial #*/
numeric digits 1000 /*be able to handle big subfacts.*/
parse arg N .; if N=='' then N=4 /*Not specified? Assume default*/
d=derangementsSet(N) /*go & build the derangements set*/
say d 'derangements for' N "items are:"
say
do i=1 for d /*show derangements for N items.*/
say right('derangement',22) right(i,length(d)) '' $.i
end /*i*/
say /* [↓] count and calculate !L. */
do L=0 to 9; d=derangementsSet(L)
say L 'items: derangement count='right(d,6)", !"L'='right(!s(L),6)
end /*L*/
say
say right('!20=' , 40) !s( 20)
say right('!100=', 40) !s(100)
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────!S subroutine───────────────────────*/
!s: _=1; do j=1 for arg(1);if j//2 then _=-1+j*_;else _=1+j*_;end;return _
/*──────────────────────────────────DERANGEMENTSSET subroutine──────────*/
derangementsSet: procedure expose $.; parse arg x; $.=; #=0; p=x-1
if x==0 then return 1; if x==1 then return 0
/*populate the first derangement.*/
@.1=2; @.2=1; do i=3 to x; @.i=i; end
parse value @.p @.x with @.x @.p; call .buildD x /*swap & build.*/
/*build others.*/
do while .nextD(x,0); call .buildD x; end
return #
/*──────────────────────────────────.BUILDD subroutine──────────────────*/
.buildD: do j=1 for arg(1); if @.j==j then return; end
#=#+1; do j=1 for arg(1); $.#=$.# @.j; end; return
/*──────────────────────────────────.NEXTD subroutine───────────────────*/
.nextD: procedure expose @.; parse arg n,i; nm=n-1
do k=nm by -1 for nm; kp=k+1; if @.k<@.kp then do; i=k; leave; end
end /*k*/
do j=i+1 while j<n; parse value @.j @.n with @.n @.j; n=n-1; end
if i==0 then return 0
do j=i+1 while @.j<@.i; end
parse value @.j @.i with @.i @.j
return 1

View file

@ -0,0 +1,25 @@
def derangements(n)
ary = (1 .. n).to_a
ary.permutation.select do |perm|
ary.zip(perm).all? {|a,b| a != b}
end
end
def subfact(n)
case n
when 0 then 1
when 1 then 0
else (n-1)*(subfact(n-1) + subfact(n-2))
end
end
(0..9).each do |n|
s = subfact(n)
if n <= 4
d = derangements(n)
puts "n=%d, subfact=%d, num_derangements=%d, %s" % [n, s, d.length, d]
else
puts "n=%d, subfact=%d" % [n, s]
end
end
puts "n=20, subfact=#{subfact(20)}"

View file

@ -0,0 +1,37 @@
package require Tcl 8.5; # for arbitrary-precision integers
package require struct::list; # for permutation enumerator
proc derangements lst {
# Special case
if {![llength $lst]} {return {{}}}
set result {}
for {set perm [struct::list firstperm $lst]} {[llength $perm]} \
{set perm [struct::list nextperm $perm]} {
set skip 0
foreach a $lst b $perm {
if {[set skip [string equal $a $b]]} break
}
if {!$skip} {lappend result $perm}
}
return $result
}
proc deranged1to n {
for {set i 1;set r {}} {$i <= $n} {incr i} {lappend r $i}
return [derangements $r]
}
proc countDeranged1to n {
llength [deranged1to $n]
}
proc subfact n {
if {$n == 0} {return 1}
if {$n == 1} {return 0}
set o 1
set s 0
for {set i 1} {$i < $n} {incr i} {
set s [expr {$i * ($o + [set o $s])}]
}
return $s
}

View file

@ -0,0 +1,11 @@
foreach d [deranged1to 4] {
puts "derangement of 1..4: $d"
}
puts "\n\tcounted\tcalculated"
for {set i 0} {$i <= 9} {incr i} {
puts "!$i\t[countDeranged1to $i]\t[subfact $i]"
}
# Stretch goal
puts "\n!20 = [subfact 20]"