tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
19
Task/Permutations-Derangements/0DESCRIPTION
Normal file
19
Task/Permutations-Derangements/0DESCRIPTION
Normal 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]]
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
>
|
||||
57
Task/Permutations-Derangements/C/permutations-derangements.c
Normal file
57
Task/Permutations-Derangements/C/permutations-derangements.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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 ] ]
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)}
|
||||
"""
|
||||
|
|
@ -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
|
||||
|
|
@ -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)]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
derangement=: (A.&i.~ !)~ (*/ .~: # [) i. NB. task item 1
|
||||
subfactorial=: ! * +/@(_1&^ % !)@i.@>: NB. task item 3
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Needs["Combinatorica`"]
|
||||
derangements[n_] := Derangements[Range[n]]
|
||||
derangements[4]
|
||||
Table[{NumberOfDerangements[i], Subfactorial[i]}, {i, 9}] // TableForm
|
||||
Subfactorial[20]
|
||||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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))) ) ) )
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)))
|
||||
|
|
@ -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
|
||||
|
|
@ -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)}"
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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]"
|
||||
Loading…
Add table
Add a link
Reference in a new issue