Add all the A tasks
This commit is contained in:
parent
2dd7375f96
commit
051504d65b
1608 changed files with 18584 additions and 0 deletions
32
Task/Average-loop-length/0DESCRIPTION
Normal file
32
Task/Average-loop-length/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Let <code>f</code> be a uniformly-randomly chosen mapping from the numbers 1..N to the numbers 1..N (note: not necessarily a permutation of 1..N; the mapping could produce a number in more than one way or not at all). At some point, the sequence <code>1, f(1), f(f(1))...</code> will contain a <em>repetition</em>, a number that occurring for the second time in the sequence.
|
||||
|
||||
Write a program or a script that estimates, for each <code>N</code>, the average length until the first such repetition.
|
||||
|
||||
Also calculate this expected length using an analytical formula, and optionally compare the simulated result with the theoretical one.
|
||||
|
||||
This problem comes from the end of Donald Knuth's [http://www.youtube.com/watch?v=cI6tt9QfRdo Christmas tree lecture 2011].
|
||||
|
||||
Example of expected output:
|
||||
|
||||
<pre> N average analytical (error)
|
||||
=== ========= ============ =========
|
||||
1 1.0000 1.0000 ( 0.00%)
|
||||
2 1.4992 1.5000 ( 0.05%)
|
||||
3 1.8784 1.8889 ( 0.56%)
|
||||
4 2.2316 2.2188 ( 0.58%)
|
||||
5 2.4982 2.5104 ( 0.49%)
|
||||
6 2.7897 2.7747 ( 0.54%)
|
||||
7 3.0153 3.0181 ( 0.09%)
|
||||
8 3.2429 3.2450 ( 0.07%)
|
||||
9 3.4536 3.4583 ( 0.14%)
|
||||
10 3.6649 3.6602 ( 0.13%)
|
||||
11 3.8091 3.8524 ( 1.12%)
|
||||
12 3.9986 4.0361 ( 0.93%)
|
||||
13 4.2074 4.2123 ( 0.12%)
|
||||
14 4.3711 4.3820 ( 0.25%)
|
||||
15 4.5275 4.5458 ( 0.40%)
|
||||
16 4.6755 4.7043 ( 0.61%)
|
||||
17 4.8877 4.8579 ( 0.61%)
|
||||
18 4.9951 5.0071 ( 0.24%)
|
||||
19 5.1312 5.1522 ( 0.41%)
|
||||
20 5.2699 5.2936 ( 0.45%)</pre>
|
||||
53
Task/Average-loop-length/Ada/average-loop-length.ada
Normal file
53
Task/Average-loop-length/Ada/average-loop-length.ada
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with Ada.Numerics.Generic_Elementary_Functions;
|
||||
with Ada.Numerics.Discrete_Random;
|
||||
procedure Avglen is
|
||||
package IIO is new Ada.Text_IO.Integer_IO (Positive); use IIO;
|
||||
package LFIO is new Ada.Text_IO.Float_IO (Long_Float); use LFIO;
|
||||
subtype FactN is Natural range 0..20;
|
||||
TESTS : constant Natural := 1_000_000;
|
||||
|
||||
function Factorial (N : FactN) return Long_Float is
|
||||
Result : Long_Float := 1.0;
|
||||
begin
|
||||
for I in 2..N loop Result := Result * Long_Float(I); end loop;
|
||||
return Result;
|
||||
end Factorial;
|
||||
|
||||
function Analytical (N : FactN) return Long_Float is
|
||||
Sum : Long_Float := 0.0;
|
||||
begin
|
||||
for I in 1..N loop
|
||||
Sum := Sum + Factorial(N) / Factorial(N - I) / Long_Float(N)**I;
|
||||
end loop;
|
||||
return Sum;
|
||||
end Analytical;
|
||||
|
||||
function Experimental (N : FactN) return Long_Float is
|
||||
subtype RandInt is Natural range 1..N;
|
||||
package Random is new Ada.Numerics.Discrete_Random(RandInt);
|
||||
seed : Random.Generator;
|
||||
Num : RandInt;
|
||||
count : Natural := 0;
|
||||
bits : array(RandInt'Range) of Boolean;
|
||||
begin
|
||||
Random.Reset(seed);
|
||||
for run in 1..TESTS loop
|
||||
bits := (others => false);
|
||||
for I in RandInt'Range loop
|
||||
Num := Random.Random(seed); exit when bits(Num);
|
||||
bits(Num) := True; count := count + 1;
|
||||
end loop;
|
||||
end loop;
|
||||
return Long_Float(count)/Long_Float(TESTS);
|
||||
end Experimental;
|
||||
|
||||
A, E, err : Long_Float;
|
||||
begin
|
||||
Put_Line(" N avg calc %diff");
|
||||
for I in 1..20 loop
|
||||
A := Analytical(I); E := Experimental(I); err := abs(E-A)/A*100.0;
|
||||
Put(I, Width=>2); Put(E ,Aft=>4, exp=>0); Put(A, Aft=>4, exp=>0);
|
||||
Put(err, Fore=>3, Aft=>3, exp=>0); New_line;
|
||||
end loop;
|
||||
end Avglen;
|
||||
56
Task/Average-loop-length/C/average-loop-length.c
Normal file
56
Task/Average-loop-length/C/average-loop-length.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MAX_N 20
|
||||
#define TIMES 1000000
|
||||
|
||||
double factorial(int n) {
|
||||
double f = 1;
|
||||
int i;
|
||||
for (i = 1; i <= n; i++) f *= i;
|
||||
return f;
|
||||
}
|
||||
|
||||
double expected(int n) {
|
||||
double sum = 0;
|
||||
int i;
|
||||
for (i = 1; i <= n; i++)
|
||||
sum += factorial(n) / pow(n, i) / factorial(n - i);
|
||||
return sum;
|
||||
}
|
||||
|
||||
int randint(int n) {
|
||||
int r, rmax = RAND_MAX / n * n;
|
||||
while ((r = rand()) >= rmax);
|
||||
return r / (RAND_MAX / n);
|
||||
}
|
||||
|
||||
int test(int n, int times) {
|
||||
int i, count = 0;
|
||||
for (i = 0; i < times; i++) {
|
||||
int x = 1, bits = 0;
|
||||
while (!(bits & x)) {
|
||||
count++;
|
||||
bits |= x;
|
||||
x = 1 << randint(n);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
srand(time(0));
|
||||
puts(" n\tavg\texp.\tdiff\n-------------------------------");
|
||||
|
||||
int n;
|
||||
for (n = 1; n <= MAX_N; n++) {
|
||||
int cnt = test(n, TIMES);
|
||||
double avg = (double)cnt / TIMES;
|
||||
double theory = expected(n);
|
||||
double diff = (avg / theory - 1) * 100;
|
||||
printf("%2d %8.4f %8.4f %6.3f%%\n", n, avg, theory, diff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
27
Task/Average-loop-length/Python/average-loop-length.py
Normal file
27
Task/Average-loop-length/Python/average-loop-length.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
from __future__ import division # Only necessary for Python 2.X
|
||||
from math import factorial
|
||||
from random import randrange
|
||||
|
||||
MAX_N = 20
|
||||
TIMES = 1000000
|
||||
|
||||
def analytical(n):
|
||||
return sum(factorial(n) / pow(n, i) / factorial(n -i) for i in range(1, n+1))
|
||||
|
||||
def test(n, times):
|
||||
count = 0
|
||||
for i in range(times):
|
||||
x, bits = 1, 0
|
||||
while not (bits & x):
|
||||
count += 1
|
||||
bits |= x
|
||||
x = 1 << randrange(n)
|
||||
return count / times
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(" n\tavg\texp.\tdiff\n-------------------------------")
|
||||
for n in range(1, MAX_N+1):
|
||||
avg = test(n, TIMES)
|
||||
theory = analytical(n)
|
||||
diff = (avg / theory - 1) * 100
|
||||
print("%2d %8.4f %8.4f %6.3f%%" % (n, avg, theory, diff))
|
||||
36
Task/Average-loop-length/REXX/average-loop-length.rexx
Normal file
36
Task/Average-loop-length/REXX/average-loop-length.rexx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*REXX program to read a config file and assign VARs as found within. */
|
||||
numeric digits 10000 /*be able to calculate !(runs). */
|
||||
parse arg runs tests seed .
|
||||
if runs ==',' | runs =='' then runs = 40 /*num of runs. */
|
||||
if tests ==',' | tests =='' then tests = 1000000 /*num of trials.*/
|
||||
if seed\==',' & seed\=='' then call random ,,seed /*repeatability?*/
|
||||
numeric digits max(9,length(!(runs))) /*set NUMERIC digits for !(runs).*/
|
||||
say right( runs, 24) 'runs' /*display # of runs we're using*/
|
||||
say right( tests, 24) 'tests' /* " " " tests " " */
|
||||
say right( digits(), 24) 'digits' /* " " " digits " " */
|
||||
say
|
||||
say ' N average exact % error' /*headers & pad.*/
|
||||
h= ' ─── ───────── ───────── ─────────'; say h; pad=left('',3)
|
||||
|
||||
do #=1 for runs; ##=right(#,9) /*## is used for indenting output*/
|
||||
a= format(exact(#) ,,4) /*use 4 digits past decimal point*/
|
||||
e= format(exper(#) ,,4) /* " " " " " " */
|
||||
err= format(abs(e-a)*100/a ,,4) /* " " " " " " */
|
||||
if err=0 then err=err/1 /*present a clean & concise zero.*/
|
||||
say ## pad e pad a pad err /*display a line of statistics. */
|
||||
end /*#*/
|
||||
say h /*display the final header bar. */
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────! subroutine────────────────────────*/
|
||||
!: procedure; !=1; do j=2 to arg(1); !=!*j; end; return !
|
||||
/*──────────────────────────────────EXACT subroutine────────────────────*/
|
||||
exact: parse arg x; s=0; do j=1 for x; s=s+!(x)/!(x-j)/x**j; end; return s
|
||||
/*──────────────────────────────────EXPER subroutine────────────────────*/
|
||||
exper: parse arg n
|
||||
k=0; do tests; !.=0 /*repeat TESTS times, reset found*/
|
||||
!.=0 /*stemmed array: expected results*/
|
||||
do n; r=random(1,n); if !.r then leave
|
||||
!.r=1; k=k+1 /*bump the ctr. */
|
||||
end /*n*/
|
||||
end /*tests*/
|
||||
return k/tests
|
||||
40
Task/Average-loop-length/Tcl/average-loop-length.tcl
Normal file
40
Task/Average-loop-length/Tcl/average-loop-length.tcl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Generate a list of the numbers increasing from $a to $b
|
||||
proc range {a b} {
|
||||
for {set result {}} {$a <= $b} {incr a} {lappend result $a}
|
||||
return $result
|
||||
}
|
||||
|
||||
# Computing the expected value analytically
|
||||
proc tcl::mathfunc::factorial n {
|
||||
::tcl::mathop::* {*}[range 2 $n]
|
||||
}
|
||||
proc Analytical {n} {
|
||||
set sum 0.0
|
||||
foreach x [range 1 $n] {
|
||||
set sum [expr {$sum + factorial($n) / factorial($n-$x) / double($n)**$x}]
|
||||
}
|
||||
return $sum
|
||||
}
|
||||
|
||||
# Determining an approximation to the value experimentally
|
||||
proc Experimental {n numTests} {
|
||||
set count 0
|
||||
set u0 [lrepeat $n 1]
|
||||
foreach run [range 1 $numTests] {
|
||||
set unseen $u0
|
||||
for {set i 0} {[lindex $unseen $i]} {incr count} {
|
||||
lset unseen $i 0
|
||||
set i [expr {int(rand()*$n)}]
|
||||
}
|
||||
}
|
||||
return [expr {$count / double($numTests)}]
|
||||
}
|
||||
|
||||
# Tabulate the results in exactly the original format
|
||||
puts " N average analytical (error)"
|
||||
puts "=== ========= ============ ========="
|
||||
foreach n [range 1 20] {
|
||||
set a [Analytical $n]
|
||||
set e [Experimental $n 100000]
|
||||
puts [format "%3d %9.4f %12.4f (%6.2f%%)" $n $e $a [expr {abs($e-$a)/$a*100.0}]]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue