Initial data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 72d218235f
commit f23f22d71c
199087 changed files with 3378941 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/Average_loop_length

View file

@ -0,0 +1,37 @@
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.
;Task:
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>
<br>

View file

@ -0,0 +1,28 @@
F ffactorial(n)
V result = 1.0
L(i) 2..n
result *= i
R result
V MAX_N = 20
V TIMES = 1000000
F analytical(n)
R sum((1..n).map(i -> ffactorial(@n) / pow(Float(@n), Float(i)) / ffactorial(@n - i)))
F test(n, times)
V count = 0
L(i) 0 .< times
V (x, bits) = (1, 0)
L (bits [&] x) == 0
count++
bits [|]= x
x = 1 << random:(n)
R Float(count) / times
print(" n avg exp. diff\n-------------------------------")
L(n) 1 .. MAX_N
V avg = test(n, TIMES)
V theory = analytical(n)
V diff = (avg / theory - 1) * 100
print(#2 #3.4 #3.4 #2.3%.format(n, avg, theory, diff))

View 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;

View file

@ -0,0 +1,33 @@
@% = &2040A
MAX_N = 20
TIMES = 1000000
FOR n = 1 TO MAX_N
avg = FNtest(n, TIMES)
theory = FNanalytical(n)
diff = (avg / theory - 1) * 100
PRINT STR$(n), avg, theory, diff "%"
NEXT
END
DEF FNanalytical(n)
LOCAL i, s
FOR i = 1 TO n
s += FNfactorial(n) / n^i / FNfactorial(n-i)
NEXT
= s
DEF FNtest(n, times)
LOCAL i, b, c, x
FOR i = 1 TO times
x = 1 : b = 0
WHILE (b AND x) = 0
c += 1
b OR= x
x = 1 << (RND(n) - 1)
ENDWHILE
NEXT
= c / times
DEF FNfactorial(n)
IF n=1 OR n=0 THEN =1 ELSE = n * FNfactorial(n-1)

View file

@ -0,0 +1,63 @@
#include <random>
#include <random>
#include <vector>
#include <iostream>
#define MAX_N 20
#define TIMES 1000000
/**
* Used to generate a uniform random distribution
*/
static std::random_device rd; //Will be used to obtain a seed for the random number engine
static std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
static std::uniform_int_distribution<> dis;
int randint(int n) {
int r, rmax = RAND_MAX / n * n;
dis=std::uniform_int_distribution<int>(0,rmax) ;
r = dis(gen);
return r / (RAND_MAX / n);
}
unsigned long long factorial(size_t n) {
//Factorial using dynamic programming to memoize the values.
static std::vector<unsigned long long>factorials{1,1,2};
for (;factorials.size() <= n;)
factorials.push_back(((unsigned long long) factorials.back())*factorials.size());
return factorials[n];
}
long double expected(size_t n) {
long double sum = 0;
for (size_t i = 1; i <= n; i++)
sum += factorial(n) / pow(n, i) / factorial(n - i);
return sum;
}
int test(int n, int times) {
int i, count = 0;
for (i = 0; i < times; i++) {
unsigned int x = 1, bits = 0;
while (!(bits & x)) {
count++;
bits |= x;
x = static_cast<unsigned int>(1 << randint(n));
}
}
return count;
}
int main() {
puts(" n\tavg\texp.\tdiff\n-------------------------------");
int n;
for (n = 1; n <= MAX_N; n++) {
int cnt = test(n, TIMES);
long double avg = (double)cnt / TIMES;
long double theory = expected(static_cast<size_t>(n));
long double diff = (avg / theory - 1) * 100;
printf("%2d %8.4f %8.4f %6.3f%%\n", n, static_cast<double>(avg), static_cast<double>(theory), static_cast<double>(diff));
}
return 0;
}

View file

@ -0,0 +1,50 @@
public class AverageLoopLength {
private static int N = 100000;
private static double analytical(int n) {
double[] factorial = new double[n + 1];
double[] powers = new double[n + 1];
powers[0] = 1.0;
factorial[0] = 1.0;
for (int i = 1; i <= n; i++) {
factorial[i] = factorial[i - 1] * i;
powers[i] = powers[i - 1] * n;
}
double sum = 0;
for (int i = 1; i <= n; i++) {
sum += factorial[n] / factorial[n - i] / powers[i];
}
return sum;
}
private static double average(int n) {
Random rnd = new Random();
double sum = 0.0;
for (int a = 0; a < N; a++) {
int[] random = new int[n];
for (int i = 0; i < n; i++) {
random[i] = rnd.Next(n);
}
var seen = new HashSet<double>(n);
int current = 0;
int length = 0;
while (seen.Add(current)) {
length++;
current = random[current];
}
sum += length;
}
return sum / N;
}
public static void Main(string[] args) {
Console.WriteLine(" N average analytical (error)");
Console.WriteLine("=== ========= ============ =========");
for (int i = 1; i <= 20; i++) {
var average = AverageLoopLength.average(i);
var analytical = AverageLoopLength.analytical(i);
Console.WriteLine("{0,3} {1,10:N4} {2,13:N4} {3,8:N2}%", i, average, analytical, (analytical - average) / analytical * 100);
}
}
}

View 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;
}

View file

@ -0,0 +1,44 @@
(ns cyclelengths
(:gen-class))
(defn factorial [n]
" n! "
(apply *' (range 1 (inc n)))) ; Use *' (vs. *) to allow arbitrary length arithmetic
(defn pow [n i]
" n^i"
(apply *' (repeat i n)))
(defn analytical [n]
" Analytical Computation "
(->>(range 1 (inc n))
(map #(/ (factorial n) (pow n %) (factorial (- n %)))) ;calc n %))
(reduce + 0)))
;; Number of random times to test each n
(def TIMES 1000000)
(defn single-test-cycle-length [n]
" Single random test of cycle length "
(loop [count 0
bits 0
x 1]
(if (zero? (bit-and x bits))
(recur (inc count) (bit-or bits x) (bit-shift-left 1 (rand-int n)))
count)))
(defn avg-cycle-length [n times]
" Average results of single tests of cycle lengths "
(/
(reduce +
(for [i (range times)]
(single-test-cycle-length n)))
times))
;; Show Results
(println "\tAvg\t\tExp\t\tDiff")
(doseq [q (range 1 21)
:let [anal (double (analytical q))
avg (double (avg-cycle-length q TIMES))
diff (Math/abs (* 100 (- 1 (/ avg anal))))]]
(println (format "%3d\t%.4f\t%.4f\t%.2f%%" q avg anal diff)))

View file

@ -0,0 +1,41 @@
import std.stdio, std.random, std.math, std.algorithm, std.range, std.format;
real analytical(in int n) pure nothrow @safe /*@nogc*/ {
enum aux = (int k) => reduce!q{a * b}(1.0L, iota(n - k + 1, n + 1));
return iota(1, n + 1)
.map!(k => (aux(k) * k ^^ 2) / (real(n) ^^ (k + 1)))
.sum;
}
size_t loopLength(size_t maxN)(in int size, ref Xorshift rng) {
__gshared static bool[maxN + 1] seen;
seen[0 .. size + 1] = false;
int current = 1;
size_t steps = 0;
while (!seen[current]) {
seen[current] = true;
current = uniform(1, size + 1, rng);
steps++;
}
return steps;
}
void main() {
enum maxN = 40;
enum nTrials = 300_000;
auto rng = Xorshift(unpredictableSeed);
writeln(" n average analytical (error)");
writeln("=== ========= ============ ==========");
foreach (immutable n; 1 .. maxN + 1) {
long total = 0;
foreach (immutable _; 0 .. nTrials)
total += loopLength!maxN(n, rng);
immutable average = total / real(nTrials);
immutable an = n.analytical;
immutable percentError = abs(an - average) / an * 100;
immutable errorS = format("%2.4f", percentError);
writefln("%3d %9.5f %12.5f (%7s%%)",
n, average, an, errorS);
}
}

View file

@ -0,0 +1,65 @@
program Average_loop_length;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Math;
const
MAX_N = 20;
TIMES = 1000000;
function Factorial(const n: Double): Double;
begin
Result := 1;
if n > 1 then
Result := n * Factorial(n - 1);
end;
function Expected(const n: Integer): Double;
var
i: Integer;
begin
Result := 0;
for i := 1 to n do
Result := Result + (factorial(n) / Power(n, i) / factorial(n - i));
end;
function Test(const n, times: Integer): integer;
var
i, x, bits: Integer;
begin
Result := 0;
for i := 0 to times - 1 do
begin
x := 1;
bits := 0;
while ((bits and x) = 0) do
begin
inc(Result);
bits := bits or x;
x := 1 shl random(n);
end;
end;
end;
var
n, cnt: Integer;
avg, theory, diff: Double;
begin
Randomize;
Writeln(#10' tavg'^I'exp.'^I'diff'#10'-------------------------------');
for n := 1 to MAX_N do
begin
cnt := test(n, times);
avg := cnt / times;
theory := expected(n);
diff := (avg / theory - 1) * 100;
writeln(format('%2d %8.4f %8.4f %6.3f%%', [n, avg, theory, diff]));
end;
readln;
end.

View file

@ -0,0 +1,29 @@
(lib 'math) ;; Σ aka (sigma f(n) nfrom nto)
(define (f-count N (times 100000))
(define count 0)
(for ((i times))
;; new random f mapping from 0..N-1 to 0..N-1
;; (f n) is NOT (random N)
;; because each call (f n) must return the same value
(define f (build-vector N (lambda(i) (random N))))
(define hits (make-vector N))
(define n 0)
(while (zero? [hits n])
(++ count)
(vector+= hits n 1)
(set! n [f n])))
(// count times))
(define (f-anal N)
(Σ (lambda(i) (// (! N) (! (- N i)) (^ N i))) 1 N))
(decimals 5)
(define (f-print (maxN 21))
(for ((N (in-range 1 maxN)))
(define fc (f-count N))
(define fa (f-anal N))
(printf "%3d %10d %10d %10.2d %%" N fc fa (// (abs (- fa fc)) fc 0.01))))

View file

@ -0,0 +1,26 @@
defmodule RC do
def factorial(0), do: 1
def factorial(n), do: Enum.reduce(1..n, 1, &(&1 * &2))
def loop_length(n), do: loop_length(n, MapSet.new)
defp loop_length(n, set) do
r = :rand.uniform(n)
if r in set, do: MapSet.size(set), else: loop_length(n, MapSet.put(set, r))
end
def task(runs) do
IO.puts " N average analytical (error) "
IO.puts "=== ========= ========== ========="
Enum.each(1..20, fn n ->
avg = Enum.reduce(1..runs, 0, fn _,sum -> sum + loop_length(n) end) / runs
analytical = Enum.reduce(1..n, 0, fn i,sum ->
sum + (factorial(n) / :math.pow(n, i) / factorial(n-i))
end)
:io.format "~3w ~9.4f ~9.4f (~6.2f%)~n", [n, avg, analytical, abs(avg/analytical - 1)*100]
end)
end
end
runs = 1_000_000
RC.task(runs)

View file

@ -0,0 +1,49 @@
open System
let gamma z =
let lanczosCoefficients = [76.18009172947146;-86.50532032941677;24.01409824083091;-1.231739572450155;0.1208650973866179e-2;-0.5395239384953e-5]
let rec sumCoefficients acc i coefficients =
match coefficients with
| [] -> acc
| h::t -> sumCoefficients (acc + (h/i)) (i+1.0) t
let gamma = 5.0
let x = z - 1.0
Math.Pow(x + gamma + 0.5, x + 0.5) * Math.Exp( -(x + gamma + 0.5) ) * Math.Sqrt( 2.0 * Math.PI ) * sumCoefficients 1.000000000190015 (x + 1.0) lanczosCoefficients
let factorial n = gamma ((float n) + 1.)
let expected n =
seq {for i in 1 .. n do yield (factorial n) / System.Math.Pow((float n), (float i)) / (factorial (n - i)) }
|> Seq.sum
let r = System.Random()
let trial n =
let count = ref 0
let x = ref 1
let bits = ref 0
while (!bits &&& !x) = 0 do
count := !count + 1
bits := !bits ||| !x
x := 1 <<< r.Next(n)
!count
let tested n times = (float (Seq.sum (seq { for i in 1 .. times do yield (trial n) }))) / (float times)
let results = seq {
for n in 1 .. 20 do
let avg = tested n 1000000
let theory = expected n
yield n, avg, theory
}
[<EntryPoint>]
let main argv =
printfn " N average analytical (error)"
printfn "------------------------------------"
results
|> Seq.iter (fun (n, avg, theory) ->
printfn "%2i %2.6f %2.6f %+2.3f%%" n avg theory ((avg / theory - 1.) * 100.))
0

View file

@ -0,0 +1,25 @@
USING: formatting fry io kernel locals math math.factorials
math.functions math.ranges random sequences ;
: (analytical) ( m n -- x )
[ drop factorial ] [ ^ /f ] [ - factorial / ] 2tri ;
: analytical ( n -- x )
dup [1,b] [ (analytical) ] with map-sum ;
: loop-length ( n -- x )
[ 0 0 1 [ 2dup bitand zero? ] ] dip
'[ [ 1 + ] 2dip bitor 1 _ random shift ] while 2drop ;
:: average-loop-length ( n #tests -- x )
0 #tests [ n loop-length + ] times #tests / ;
: stats ( n -- avg exp )
[ 1,000,000 average-loop-length ] [ analytical ] bi ;
: .line ( n -- )
dup stats 2dup / 1 - 100 *
"%2d %8.4f %8.4f %6.3f%%\n" printf ;
" n\tavg\texp.\tdiff\n-------------------------------" print
20 [1,b] [ .line ] each

View file

@ -0,0 +1,43 @@
Const max_N = 20, max_ciclos = 1000000
Function Factorial(Byval N As Integer) As Double
Dim As Double d: d = 1
If N = 0 Then Factorial = 1: Exit Function
While (N > 1)
d *= N
N -= 1
Wend
Factorial = d
End Function
Function Analytical(N As Integer) As Double
Dim As Double i, sum = 0
For i = 1 To N
sum += Factorial(N) / N^i / Factorial(N-i)
Next i
Return sum
End Function
Function Average(N As Integer, ciclos As Double) As Double
Dim As Integer i, x, bits, sum = 0
For i = 0 To ciclos - 1
x = 1 : bits = 0
While (bits And x) = 0
sum += 1
bits Or= x
x = 1 Shl (Rnd * (N - 1))
Wend
Next i
Return sum / ciclos
End Function
Randomize Timer
Print " N promedio analitico (error)"
Print "--- ---------- ----------- ----------"
For N As Integer = 1 To max_N
Dim As Double avg = Average(N, max_ciclos)
Dim As Double ana = Analytical(N)
Dim As Double diff = abs(avg-ana) / ana * 100
Print Using " ## #####.###0 #####.###0 ###.#0%"; N; avg; ana; diff
Next N
Sleep

View file

@ -0,0 +1,49 @@
_nmax = 20
_times = 1000000
local fn Average( n as long, times as long ) as double
long i, x
double b, c = 0
for i = 0 to times
x = 1 : b = 0
while ( b and x ) == 0
c++
b = b || x
x = 1 << ( rnd(n) - 1 )
wend
next
end fn = c / times
local fn Analyltic( n as long ) as double
double nn = (double)n
double term = 1.0
double sum = 1.0
long i
for i = nn - 1 to i >= 1 step -1
term = term * i / nn
sum = sum + term
next
end fn = sum
local fn DoIt
long n
double average, theory, difference
window 1
printf @"\nSamples tested: %ld\n", _times
print " N Average Analytical (error)"
print "=== ========= ============ ========="
for n = 1 to _nmax
average = fn Average( n, _times )
theory = fn Analyltic( n )
difference = ( average / theory - 1) * 100
printf @"%3d %9.4f %9.4f %10.4f%%", n, average, theory, difference
next
end fn
randomize
fn DoIt
HandleEvents

View file

@ -0,0 +1,44 @@
package main
import (
"fmt"
"math"
"math/rand"
)
const nmax = 20
func main() {
fmt.Println(" N average analytical (error)")
fmt.Println("=== ========= ============ =========")
for n := 1; n <= nmax; n++ {
a := avg(n)
b := ana(n)
fmt.Printf("%3d %9.4f %12.4f (%6.2f%%)\n",
n, a, b, math.Abs(a-b)/b*100)
}
}
func avg(n int) float64 {
const tests = 1e4
sum := 0
for t := 0; t < tests; t++ {
var v [nmax]bool
for x := 0; !v[x]; x = rand.Intn(n) {
v[x] = true
sum++
}
}
return float64(sum) / tests
}
func ana(n int) float64 {
nn := float64(n)
term := 1.
sum := 1.
for i := nn - 1; i >= 1; i-- {
term *= i / nn
sum += term
}
return sum
}

View file

@ -0,0 +1,54 @@
import System.Random
import qualified Data.Set as S
import Text.Printf
findRep :: (Random a, Integral a, RandomGen b) => a -> b -> (a, b)
findRep n gen = findRep' (S.singleton 1) 1 gen
where
findRep' seen len gen'
| S.member fx seen = (len, gen'')
| otherwise = findRep' (S.insert fx seen) (len + 1) gen''
where
(fx, gen'') = randomR (1, n) gen'
statistical :: (Integral a, Random b, Integral b, RandomGen c, Fractional d) =>
a -> b -> c -> (d, c)
statistical samples size gen =
let (total, gen') = sar samples gen 0
in ((fromIntegral total) / (fromIntegral samples), gen')
where
sar 0 gen' acc = (acc, gen')
sar samples' gen' acc =
let (len, gen'') = findRep size gen'
in sar (samples' - 1) gen'' (acc + len)
factorial :: (Integral a) => a -> a
factorial n = foldl (*) 1 [1..n]
analytical :: (Integral a, Fractional b) => a -> b
analytical n = sum [fromIntegral num /
fromIntegral (factorial (n - i)) /
fromIntegral (n ^ i) |
i <- [1..n]]
where num = factorial n
test :: (Integral a, Random b, Integral b, PrintfArg b, RandomGen c) =>
a -> [b] -> c -> IO c
test _ [] gen = return gen
test samples (x:xs) gen = do
let (st, gen') = statistical samples x gen
an = analytical x
err = abs (st - an) / st * 100.0
str = printf "%3d %9.4f %12.4f (%6.2f%%)\n"
x (st :: Float) (an :: Float) (err :: Float)
putStr str
test samples xs gen'
main :: IO ()
main = do
putStrLn " N average analytical (error)"
putStrLn "=== ========= ============ ========="
let samples = 10000 :: Integer
range = [1..20] :: [Integer]
_ <- test samples range $ mkStdGen 0
return ()

View file

@ -0,0 +1,4 @@
(~.@, {&0 0@{:)^:_] 0
0
(~.@, {&0 0@{:)^:_] 1
1 0

View file

@ -0,0 +1,2 @@
0 0 ([: # (] ~.@, {:@] { [)^:_) 1
2

View file

@ -0,0 +1,5 @@
(#.inv i.@^~)2
0 0
0 1
1 0
1 1

View file

@ -0,0 +1,12 @@
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)1
1
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)2
1.5
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)3
1.88889
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)4
2.21875
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)5
2.5104
(+/ % #)@,@((#.inv i.@^~) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)6
2.77469

View file

@ -0,0 +1,3 @@
ana=: +/@(!@[ % !@- * ^) 1+i.
ana"0]1 2 3 4 5 6
1 1.5 1.88889 2.21875 2.5104 2.77469

View file

@ -0,0 +1,3 @@
sim=: (+/ % #)@,@((]?@$~1e4,]) ([: # (] ~.@, {:@] { [)^:_)"1 0/ i.)
sim"0]1 2 3 4 5 6
1 1.5034 1.8825 2.22447 2.51298 2.76898

View file

@ -0,0 +1,25 @@
(;:'N average analytic error'),:,.each(;ana"0 ([;];-|@%[) sim"0)1+i.20
+--+-------+--------+-----------+
|N |average|analytic|error |
+--+-------+--------+-----------+
| 1| 1| 1 | 0|
| 2| 1.5|1.49955 | 0.0003|
| 3|1.88889| 1.8928 | 0.00207059|
| 4|2.21875|2.23082 | 0.00544225|
| 5| 2.5104|2.52146 | 0.00440567|
| 6|2.77469|2.78147 | 0.00244182|
| 7|3.01814| 3.0101 | 0.00266346|
| 8|3.24502|3.25931 | 0.00440506|
| 9|3.45832|3.45314 | 0.00149532|
|10|3.66022| 3.6708 | 0.00289172|
|11|3.85237|3.84139 | 0.00285049|
|12|4.03607|4.03252 |0.000881304|
|13|4.21235|4.18358 | 0.00682833|
|14|4.38203|4.38791 | 0.00134132|
|15|4.54581|4.54443 |0.000302246|
|16|4.70426|4.71351 | 0.00196721|
|17|4.85787|4.85838 |0.000104089|
|18|5.00706|5.00889 |0.000365752|
|19| 5.1522|5.14785 |0.000843052|
|20|5.29358|5.28587 | 0.00145829|
+--+-------+--------+-----------+

View file

@ -0,0 +1,56 @@
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class AverageLoopLength {
private static final int N = 100000;
//analytical(n) = sum_(i=1)^n (n!/(n-i)!/n**i)
private static double analytical(int n) {
double[] factorial = new double[n + 1];
double[] powers = new double[n + 1];
powers[0] = 1.0;
factorial[0] = 1.0;
for (int i = 1; i <= n; i++) {
factorial[i] = factorial[i - 1] * i;
powers[i] = powers[i - 1] * n;
}
double sum = 0;
//memoized factorial and powers
for (int i = 1; i <= n; i++) {
sum += factorial[n] / factorial[n - i] / powers[i];
}
return sum;
}
private static double average(int n) {
Random rnd = new Random();
double sum = 0.0;
for (int a = 0; a < N; a++) {
int[] random = new int[n];
for (int i = 0; i < n; i++) {
random[i] = rnd.nextInt(n);
}
Set<Integer> seen = new HashSet<>(n);
int current = 0;
int length = 0;
while (seen.add(current)) {
length++;
current = random[current];
}
sum += length;
}
return sum / N;
}
public static void main(String[] args) {
System.out.println(" N average analytical (error)");
System.out.println("=== ========= ============ =========");
for (int i = 1; i <= 20; i++) {
double avg = average(i);
double ana = analytical(i);
System.out.println(String.format("%3d %9.4f %12.4f (%6.2f%%)", i, avg, ana, ((ana - avg) / ana * 100)));
}
}
}

View file

@ -0,0 +1,28 @@
using Printf
analytical(n::Integer) = sum(factorial(n) / big(n) ^ i / factorial(n - i) for i = 1:n)
function test(n::Integer, times::Integer = 1000000)
c = 0
for i = range(0, times)
x, bits = 1, 0
while (bits & x) == 0
c += 1
bits |= x
x = 1 << rand(0:(n - 1))
end
end
return c / times
end
function main(n::Integer)
println(" n\tavg\texp.\tdiff\n-------------------------------")
for n in 1:n
avg = test(n)
theory = analytical(n)
diff = (avg / theory - 1) * 100
@printf(STDOUT, "%2d %8.4f %8.4f %6.3f%%\n", n, avg, theory, diff)
end
end
main(20)

View file

@ -0,0 +1,38 @@
const val NMAX = 20
const val TESTS = 1000000
val rand = java.util.Random()
fun avg(n: Int): Double {
var sum = 0
for (t in 0 until TESTS) {
val v = BooleanArray(NMAX)
var x = 0
while (!v[x]) {
v[x] = true
sum++
x = rand.nextInt(n)
}
}
return sum.toDouble() / TESTS
}
fun ana(n: Int): Double {
val nn = n.toDouble()
var term = 1.0
var sum = 1.0
for (i in n - 1 downTo 1) {
term *= i / nn
sum += term
}
return sum
}
fun main(args: Array<String>) {
println(" N average analytical (error)")
println("=== ========= ============ =========")
for (n in 1..NMAX) {
val a = avg(n)
val b = ana(n)
println(String.format("%3d %6.4f %10.4f (%4.2f%%)", n, a, b, Math.abs(a - b) / b * 100.0))
}
}

View file

@ -0,0 +1,36 @@
MAXN = 20
TIMES = 10000'00
't0=time$("ms")
FOR n = 1 TO MAXN
avg = FNtest(n, TIMES)
theory = FNanalytical(n)
diff = (avg / theory - 1) * 100
PRINT n, avg, theory, using("##.####",diff); "%"
NEXT
't1=time$("ms")
'print t1-t0; " ms"
END
function FNanalytical(n)
FOR i = 1 TO n
s = s+ FNfactorial(n) / n^i / FNfactorial(n-i)
NEXT
FNanalytical = s
end function
function FNtest(n, times)
FOR i = 1 TO times
x = 1 : b = 0
WHILE (b AND x) = 0
c = c + 1
b = b OR x
x = 2^int(n*RND(1))
WEND
NEXT
FNtest = c / times
end function
function FNfactorial(n)
IF n=1 OR n=0 THEN FNfactorial=1 ELSE FNfactorial= n * FNfactorial(n-1)
end function

View file

@ -0,0 +1,26 @@
function average(n, reps)
local count = 0
for r = 1, reps do
local f = {}
for i = 1, n do f[i] = math.random(n) end
local seen, x = {}, 1
while not seen[x] do
seen[x], x, count = true, f[x], count+1
end
end
return count / reps
end
function analytical(n)
local s, t = 1, 1
for i = n-1, 1, -1 do t=t*i/n s=s+t end
return s
end
print(" N average analytical (error)")
print("=== ========= ============ =========")
for n = 1, 20 do
local avg, ana = average(n, 1e6), analytical(n)
local err = (avg-ana) / ana * 100
print(string.format("%3d %9.4f %12.4f (%6.3f%%)", n, avg, ana, err))
end

View file

@ -0,0 +1,9 @@
Grid@Prepend[
Table[{n, #[[1]], #[[2]],
Row[{Round[10000 Abs[#[[1]] - #[[2]]]/#[[2]]]/100., "%"}]} &@
N[{Mean[Array[
Length@NestWhileList[#, 1, UnsameQ[##] &, All] - 1 &[# /.
MapIndexed[#2[[1]] -> #1 &,
RandomInteger[{1, n}, n]] &] &, 10000]],
Sum[n! n^(n - k - 1)/(n - k)!, {k, n}]/n^(n - 1)}, 5], {n, 1,
20}], {"N", "average", "analytical", "error"}]

View file

@ -0,0 +1,34 @@
import random, math, strformat
randomize()
const
maxN = 20
times = 1_000_000
proc factorial(n: int): float =
result = 1
for i in 1 .. n:
result *= i.float
proc expected(n: int): float =
for i in 1 .. n:
result += factorial(n) / pow(n.float, i.float) / factorial(n - i)
proc test(n, times: int): int =
for i in 1 .. times:
var
x = 1
bits = 0
while (bits and x) == 0:
inc result
bits = bits or x
x = 1 shl rand(n - 1)
echo " n\tavg\texp.\tdiff"
echo "-------------------------------"
for n in 1 .. maxN:
let cnt = test(n, times)
let avg = cnt.float / times
let theory = expected(n)
let diff = (avg / theory - 1) * 100
echo fmt"{n:2} {avg:8.4f} {theory:8.4f} {diff:6.3f}%"

View file

@ -0,0 +1,71 @@
MODULE AvgLoopLen;
(* Oxford Oberon-2 *)
IMPORT Random, Out;
PROCEDURE Fac(n: INTEGER; f: REAL): REAL;
BEGIN
IF n = 0 THEN
RETURN f
ELSE
RETURN Fac(n - 1,n*f)
END
END Fac;
PROCEDURE Power(n,i: INTEGER): REAL;
VAR
p: REAL;
BEGIN
p := 1.0;
WHILE i > 0 DO p := p * n; DEC(i) END;
RETURN p
END Power;
PROCEDURE Abs(x: REAL): REAL;
BEGIN
IF x < 0 THEN RETURN -x ELSE RETURN x END
END Abs;
PROCEDURE Analytical(n: INTEGER): REAL;
VAR
i: INTEGER;
res: REAL;
BEGIN
res := 0.0;
FOR i := 1 TO n DO
res := res + (Fac(n,1.0) / Power(n,i) / Fac(n - i,1.0));
END;
RETURN res
END Analytical;
PROCEDURE Averages(n: INTEGER): REAL;
CONST
times = 100000;
VAR
rnds: SET;
r,count,i: INTEGER;
BEGIN
count := 0; i := 0;
WHILE i < times DO
rnds := {};
LOOP
r := Random.Roll(n);
IF r IN rnds THEN EXIT ELSE INCL(rnds,r); INC(count) END
END;
INC(i)
END;
RETURN count / times
END Averages;
VAR
i: INTEGER;
av,an,df: REAL;
BEGIN
Random.Randomize;
Out.String(" Averages Analytical Diff% ");Out.Ln;
FOR i := 1 TO 20 DO
Out.Int(i,3); Out.String(": ");
av := Averages(i);an := Analytical(i);df := Abs(av - an) / an * 100.0;
Out.Fixed(av,10,4);Out.Fixed(an,11,4);Out.Fixed(df,10,4);Out.Ln
END
END AvgLoopLen.

View file

@ -0,0 +1,14 @@
expected(n)=sum(i=1,n,n!/(n-i)!/n^i,0.);
test(n, times)={
my(ct);
for(i=1,times,
my(x=1,bits);
while(!bitand(bits,x),ct++; bits=bitor(bits,x); x = 1<<random(n))
);
ct
};
TIMES=1000000;
{for(n=1,20,
my(cnt=test(n, TIMES),avg=cnt/TIMES,ex=expected(n),diff=(avg/ex-1)*100.);
print(n"\t"avg*1."\t"ex*1."\t"diff);
)}

View file

@ -0,0 +1,21 @@
use List::Util qw(sum reduce);
sub find_loop {
my($n) = @_;
my($r,@seen);
while () { $seen[$r] = $seen[($r = int(1+rand $n))] ? return sum @seen : 1 }
}
print " N empiric theoric (error)\n";
print "=== ========= ============ =========\n";
my $MAX = 20;
my $TRIALS = 1000;
for my $n (1 .. $MAX) {
my $empiric = ( sum map { find_loop($n) } 1..$TRIALS ) / $TRIALS;
my $theoric = sum map { (reduce { $a*$b } $_**2, ($n-$_+1)..$n ) / $n ** ($_+1) } 1..$n;
printf "%3d %9.4f %12.4f (%5.2f%%)\n",
$n, $empiric, $theoric, 100 * ($empiric - $theoric) / $theoric;
}

View file

@ -0,0 +1,35 @@
(phixonline)-->
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">ITER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1000000</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #7060A8;">sum</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">sum</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">/</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sum</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bits</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">ITER</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">bits</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">bits</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">or_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ITER</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">av</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ex</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" n avg. exp. (error%)\n"</span><span style="color: #0000FF;">);</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"== ====== ====== ========\n"</span><span style="color: #0000FF;">);</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">MAX</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">av</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ex</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2d %8.4f %8.4f (%5.3f%%)\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">av</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ex</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">av</span><span style="color: #0000FF;">/</span><span style="color: #000000;">ex</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">100</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--

View file

@ -0,0 +1,42 @@
include ..\Utilitys.pmt
20 var MAX
100000 var ITER
def factorial 1 swap for * endfor enddef
def expected /# n -- n #/
>ps
0
tps for var i
tps factorial tps i power / tps i - factorial / +
endfor
ps> drop
enddef
def condition over over bitand not enddef
def test /# n -- n #/
0 >ps
ITER for var i
0 1
condition while
ps> 1 + >ps
bitor
over rand * 1 + int 1 - 2 swap power
condition endwhile
drop drop
endfor
drop ps> ITER /
enddef
def printAll len for get print 9 tochar print endfor enddef
( "n" "avg." "exp." "(error%)" ) printAll drop nl
( "==" "======" "======" "========" ) printAll drop nl
MAX for var n
n test
n expected
n rot rot over over / 1 swap - abs 100 * 4 tolist printAll drop nl
endfor

View file

@ -0,0 +1,42 @@
(scl 4)
(seed (in "/dev/urandom" (rd 8)))
(de fact (N)
(if (=0 N) 1 (apply * (range 1 N))) )
(de analytical (N)
(sum
'((I)
(/
(* (fact N) 1.0)
(** N I)
(fact (- N I)) ) )
(range 1 N) ) )
(de testing (N)
(let (C 0 N (dec N) X 0 B 0 I 1000000)
(do I
(zero B)
(one X)
(while (=0 (& B X))
(inc 'C)
(setq
B (| B X)
X (** 2 (rand 0 N)) ) ) )
(*/ C 1.0 I) ) )
(let F (2 8 8 6)
(tab F "N" "Avg" "Exp" "Diff")
(for I 20
(let (A (testing I) B (analytical I))
(tab F
I
(round A 4)
(round B 4)
(round
(*
(abs (- (*/ A 1.0 B) 1.0))
100 )
2 ) ) ) ) )
(bye)

View file

@ -0,0 +1,59 @@
function Get-AnalyticalLoopAverage ( [int]$N )
{
# Expected loop average = sum from i = 1 to N of N! / (N-i)! / N^(N-i+1)
# Equivalently, Expected loop average = sum from i = 1 to N of F(i)
# where F(N) = 1, and F(i) = F(i+1)*i/N
$LoopAverage = $Fi = 1
If ( $N -eq 1 ) { return $LoopAverage }
ForEach ( $i in ($N-1)..1 )
{
$Fi *= $i / $N
$LoopAverage += $Fi
}
return $LoopAverage
}
function Get-ExperimentalLoopAverage ( [int]$N, [int]$Tests = 100000 )
{
If ( $N -eq 1 ) { return 1 }
# Using 0 through N-1 instead of 1 through N for speed and simplicity
$NMO = $N - 1
# Create array to hold mapping function
$F = New-Object int[] ( $N )
$Count = 0
$Random = New-Object System.Random
ForEach ( $Test in 1..$Tests )
{
# Map each number to a random number
ForEach ( $i in 0..$NMO )
{
$F[$i] = $Random.Next( $N )
}
# For each number...
ForEach ( $i in 0..$NMO )
{
# Add the number to the list
$List = @()
$Count++
$List += $X = $i
# If loop does not yet exist in list...
While ( $F[$X] -notin $List )
{
# Go to the next mapped number and add it to the list
$Count++
$List += $X = $F[$X]
}
}
}
$LoopAvereage = $Count / $N / $Tests
return $LoopAvereage
}

View file

@ -0,0 +1,12 @@
# Display results for N = 1 through 20
ForEach ( $N in 1..20 )
{
$AnalyticalAverage = Get-AnalyticalLoopAverage $N
$ExperimentalAverage = Get-ExperimentalLoopAverage $N
[pscustomobject] @{
N = $N.ToString().PadLeft( 2, ' ' )
Analytical = $AnalyticalAverage.ToString( '0.00000000' )
Experimental = $ExperimentalAverage.ToString( '0.00000000' )
'Error (%)' = ( [math]::Abs( $AnalyticalAverage - $ExperimentalAverage ) / $AnalyticalAverage * 100 ).ToString( '0.00000000' )
}
}

View 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))

View file

@ -0,0 +1,45 @@
[ $ "bigrat.qky" loadfile ] now!
[ tuck space swap of
join
swap split drop echo$ ] is lecho$ ( $ n --> )
[ 1 swap times [ i 1+ * ] ] is ! ( n --> n )
[ 0 n->v rot
dup temp put
times
[ temp share ! n->v
temp share i 1+ - ! n->v
v/
temp share i 1+ ** n->v
v/ v+ ]
temp release ] is expected ( n --> n/d )
[ -1 temp put
0
[ 1 temp tally
over random bit
2dup & not while
| again ]
2drop drop
temp take ] is trial ( n --> n )
[ tuck 0 swap
times
[ over trial + ]
nip swap reduce ] is trials ( n n --> n/d )
[ say " n average expected difference"
cr
say "-- ------- -------- ----------"
cr
20 times
[ i^ 1+ dup 10 < if sp echo
2 times sp
i^ 1+ 1000000 trials
2dup 7 point$ 10 lecho$
i^ 1+ expected
2dup 7 point$ 11 lecho$
v/ 1 n->v v- 100 1 v* vabs
7 point$ echo$ say "%" cr ] ] is task ( --> )

View file

@ -0,0 +1,34 @@
expected <- function(size) {
result <- 0
for (i in 1:size) {
result <- result + factorial(size) / size^i / factorial(size -i)
}
result
}
knuth <- function(size) {
v <- sample(1:size, size, replace = TRUE)
visit <- vector('logical',size)
place <- 1
visit[[1]] <- TRUE
steps <- 0
repeat {
place <- v[[place]]
steps <- steps + 1
if (visit[[place]]) break
visit[[place]] <- TRUE
}
steps
}
cat(" N average analytical (error)\n")
cat("=== ========= ============ ==========\n")
for (num in 1:20) {
average <- mean(replicate(1e6, knuth(num)))
analytical <- expected(num)
error <- abs(average/analytical-1)*100
cat(sprintf("%3d%11.4f%14.4f ( %4.4f%%)\n", num, round(average,4), round(analytical,4), round(error,2)))
}

View file

@ -0,0 +1,36 @@
/*REXX program computes the average loop length mapping a random field 1···N ───► 1···N */
parse arg runs tests seed . /*obtain optional arguments from the CL*/
if runs =='' | runs =="," then runs = 40 /*Not specified? Then use the default.*/
if tests =='' | tests =="," then tests= 1000000 /* " " " " " " */
if datatype(seed, 'W') then call random ,, seed /*Is integer? For RAND repeatability.*/
!.=0; !.0=1 /*used for factorial (!) memoization.*/
numeric digits 100000 /*be able to calculate 25k! if need be.*/
numeric digits max(9, length( !(runs) ) ) /*set the NUMERIC DIGITS for !(runs). */
say right( runs, 24) 'runs' /*display number of runs we're using.*/
say right( tests, 24) 'tests' /* " " " tests " " */
say right( digits(), 24) 'digits' /* " " " digits " " */
say
say " N average exact % error " /* ◄─── title, header ►────────┐ */
hdr=" ═══ ═════════ ═════════ ═════════"; pad=left('',3) /* ◄────────┘ */
say hdr
do #=1 for runs; av=fmtD( exact(#) ) /*use four digits past decimal point. */
xa=fmtD( exper(#) ) /* " " " " " " */
say right(#,9) pad xa pad av pad fmtD( abs(xa-av) * 100 / av) /*show values.*/
end /*#*/
say hdr /*display the final header (some bars).*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
!: procedure expose !.; parse arg z; if !.z\==0 then return !.z
!=1; do j=2 for z -1; !=!*j; !.j=!; end; /*compute factorial*/ return !
/*──────────────────────────────────────────────────────────────────────────────────────*/
exact: parse arg x; s=0; do j=1 for x; s=s + !(x) / !(x-j) / x**j; end; return s
/*──────────────────────────────────────────────────────────────────────────────────────*/
exper: parse arg n; k=0; do tests; $.=0 /*do it TESTS times.*/
do n; r=random(1, n); if $.r then leave
$.r=1; k=k + 1 /*bump the counter. */
end /*n*/
end /*tests*/
return k/tests
/*──────────────────────────────────────────────────────────────────────────────────────*/
fmtD: parse arg y,d; d=word(d 4, 1); y=format(y, , d); parse var y w '.' f
if f=0 then return w || left('', d +1); return y

View file

@ -0,0 +1,27 @@
#lang racket
(require (only-in math factorial))
(define (analytical n)
(for/sum ([i (in-range 1 (add1 n))])
(/ (factorial n) (expt n i) (factorial (- n i)))))
(define (test n times)
(define (count-times seen times)
(define x (random n))
(if (memq x seen) times (count-times (cons x seen) (add1 times))))
(/ (for/fold ([count 0]) ([i times]) (count-times '() count))
times))
(define (test-table max-n times)
(displayln " n avg theory error\n------------------------")
(for ([i (in-range 1 (add1 max-n))])
(define average (test i times))
(define theory (analytical i))
(define difference (* (abs (sub1 (/ average theory))) 100))
(displayln (~a (~a i #:width 2 #:align 'right)
" " (real->decimal-string average 4)
" " (real->decimal-string theory 4)
" " (real->decimal-string difference 4)
"%"))))
(test-table 20 10000)

View file

@ -0,0 +1,17 @@
constant MAX_N = 20;
constant TRIALS = 100;
for 1 .. MAX_N -> $N {
my $empiric = TRIALS R/ [+] find-loop(random-mapping $N).elems xx TRIALS;
my $theoric = [+]
map -> $k { $N ** ($k + 1) R/ [×] flat $k**2, $N - $k + 1 .. $N }, 1 .. $N;
FIRST say " N empiric theoric (error)";
FIRST say "=== ========= ============ =========";
printf "%3d %9.4f %12.4f (%4.2f%%)\n",
$N, $empiric, $theoric, 100 × abs($theoric - $empiric) / $theoric;
}
sub random-mapping { hash .list Z=> .roll($_) given ^$^size }
sub find-loop { 0, | %^mapping{*} ...^ { (%){$_}++ } }

View file

@ -0,0 +1,25 @@
class Integer
def factorial
self == 0 ? 1 : (1..self).inject(:*)
end
end
def rand_until_rep(n)
rands = {}
loop do
r = rand(1..n)
return rands.size if rands[r]
rands[r] = true
end
end
runs = 1_000_000
puts " N average exp. diff ",
"=== ======== ======== ==========="
(1..20).each do |n|
sum_of_runs = runs.times.inject(0){|sum, _| sum += rand_until_rep(n)}
avg = sum_of_runs / runs.to_f
analytical = (1..n).inject(0){|sum, i| sum += (n.factorial / (n**i).to_f / (n-i).factorial)}
puts "%3d %8.4f %8.4f (%8.4f%%)" % [n, avg, analytical, (avg/analytical - 1)*100]
end

View file

@ -0,0 +1,74 @@
extern crate rand;
use rand::{ThreadRng, thread_rng};
use rand::distributions::{IndependentSample, Range};
use std::collections::HashSet;
use std::env;
use std::process;
fn help() {
println!("usage: average_loop_length <max_N> <trials>");
}
fn main() {
let args: Vec<String> = env::args().collect();
let mut max_n: u32 = 20;
let mut trials: u32 = 1000;
match args.len() {
1 => {}
3 => {
max_n = args[1].parse::<u32>().unwrap();
trials = args[2].parse::<u32>().unwrap();
}
_ => {
help();
process::exit(0);
}
}
let mut rng = thread_rng();
println!(" N average analytical (error)");
println!("=== ========= ============ =========");
for n in 1..(max_n + 1) {
let the_analytical = analytical(n);
let the_empirical = empirical(n, trials, &mut rng);
println!(" {:>2} {:3.4} {:3.4} ( {:>+1.2}%)",
n,
the_empirical,
the_analytical,
100f64 * (the_empirical / the_analytical - 1f64));
}
}
fn factorial(n: u32) -> f64 {
(1..n + 1).fold(1f64, |p, n| p * n as f64)
}
fn analytical(n: u32) -> f64 {
let sum: f64 = (1..(n + 1))
.map(|i| factorial(n) / (n as f64).powi(i as i32) / factorial(n - i))
.fold(0f64, |a, v| a + v);
sum
}
fn empirical(n: u32, trials: u32, rng: &mut ThreadRng) -> f64 {
let sum: f64 = (0..trials)
.map(|_t| {
let mut item = 1u32;
let mut seen = HashSet::new();
let range = Range::new(1u32, n + 1);
for step in 0..n {
if seen.contains(&item) {
return step as f64;
}
seen.insert(item);
item = range.ind_sample(rng);
}
n as f64
})
.fold(0f64, |a, v| a + v);
sum / trials as f64
}

View file

@ -0,0 +1,36 @@
import scala.util.Random
object AverageLoopLength extends App {
val factorial: LazyList[Double] = 1 #:: factorial.zip(LazyList.from(1)).map(n => n._2 * factorial(n._2 - 1))
val results = for (n <- 1 to 20;
avg = tested(n, 1000000);
theory = expected(n)
) yield (n, avg, theory, (avg / theory - 1) * 100)
def expected(n: Int): Double = (for (i <- 1 to n) yield factorial(n) / Math.pow(n, i) / factorial(n - i)).sum
def tested(n: Int, times: Int): Double = (for (i <- 1 to times) yield trial(n)).sum / times
def trial(n: Int): Double = {
var count = 0
var x = 1
var bits = 0
while ((bits & x) == 0) {
count = count + 1
bits = bits | x
x = 1 << Random.nextInt(n)
}
count
}
println("n avg exp diff")
println("------------------------------------")
results foreach { n => {
println(f"${n._1}%2d ${n._2}%2.6f ${n._3}%2.6f ${n._4}%2.3f%%")
}
}
}

View file

@ -0,0 +1,56 @@
(import (scheme base)
(scheme write)
(srfi 1 lists)
(only (srfi 13 strings) string-pad-right)
(srfi 27 random-bits))
(define (analytical-function n)
(define (factorial n)
(fold * 1 (iota n 1)))
;
(fold (lambda (i sum)
(+ sum
(/ (factorial n) (expt n i) (factorial (- n i)))))
0
(iota n 1)))
(define (simulation n runs)
(define (single-simulation)
(random-source-randomize! default-random-source)
(let ((vec (make-vector n #f)))
(let loop ((count 0)
(num (random-integer n)))
(if (vector-ref vec num)
count
(begin (vector-set! vec num #t)
(loop (+ 1 count)
(random-integer n)))))))
;;
(let loop ((total 0)
(run runs))
(if (zero? run)
(/ total runs)
(loop (+ total (single-simulation))
(- run 1)))))
(display " N average formula (error) \n")
(display "=== ========= ========= =========\n")
(for-each
(lambda (n)
(let ((simulation (inexact (simulation n 10000)))
(formula (inexact (analytical-function n))))
(display
(string-append
" "
(string-pad-right (number->string n) 3)
" "
(string-pad-right (number->string simulation) 6)
" "
(string-pad-right (number->string formula) 6)
" ("
(string-pad-right
(number->string (* 100 (/ (- simulation formula) formula)))
5)
"%)"))
(newline)))
(iota 20 1))

View file

@ -0,0 +1,64 @@
$ include "seed7_05.s7i";
include "float.s7i";
const integer: TESTS is 1000000;
const func float: factorial (in integer: number) is func
result
var float: factorial is 1.0;
local
var integer: i is 0;
begin
for i range 2 to number do
factorial *:= flt(i);
end for;
end func;
const func float: analytical (in integer: number) is func
result
var float: sum is 0.0;
local
var integer: i is 0;
begin
for i range 1 to number do
sum +:= factorial(number) / factorial(number - i) / flt(number)**i;
end for;
end func;
const func float: experimental (in integer: number) is func
result
var float: experimental is 0.0;
local
var integer: run is 0;
var set of integer: seen is EMPTY_SET;
var integer: current is 1;
var integer: count is 0;
begin
for run range 1 to TESTS do
current := 1;
seen := EMPTY_SET;
while current not in seen do
incr(count);
incl(seen, current);
current := rand(1, number);
end while;
end for;
experimental := flt(count) / flt(TESTS);
end func;
const proc: main is func
local
var integer: number is 0;
var float: analytical is 0.0;
var float: experimental is 0.0;
var float: err is 0.0;
begin
writeln(" N avg calc %diff");
for number range 1 to 20 do
analytical := analytical(number);
experimental := experimental(number);
err := abs(experimental - analytical) / analytical * 100.0;
writeln(number lpad 2 <& experimental digits 4 lpad 7 <&
analytical digits 4 lpad 7 <& err digits 3 lpad 7);
end for;
end func;

View file

@ -0,0 +1,22 @@
func find_loop(n) {
var seen = Hash()
loop {
with (irand(1, n)) { |r|
seen.has(r) ? (return seen.len) : (seen{r} = true)
}
}
}
print " N empiric theoric (error)\n";
print "=== ========= ============ =========\n";
define MAX = 20
define TRIALS = 1000
for n in (1..MAX) {
var empiric = (1..TRIALS -> sum { find_loop(n) } / TRIALS)
var theoric = (1..n -> sum {|k| prod(n - k + 1 .. n) * k**2 / n**(k+1) })
printf("%3d %9.4f %12.4f (%5.2f%%)\n",
n, empiric, theoric, 100*(empiric-theoric)/theoric)
}

View file

@ -0,0 +1,65 @@
BEGIN
REAL PROCEDURE FACTORIAL(N); INTEGER N;
BEGIN
REAL RESULT;
INTEGER I;
RESULT := 1.0;
FOR I := 2 STEP 1 UNTIL N DO
RESULT := RESULT * I;
FACTORIAL := RESULT;
END FACTORIAL;
REAL PROCEDURE ANALYTICAL (N); INTEGER N;
BEGIN
REAL SUM, RN;
INTEGER I;
RN := N;
FOR I := 1 STEP 1 UNTIL N DO
BEGIN
SUM := SUM + FACTORIAL(N) / FACTORIAL(N - I) / RN ** I;
END;
ANALYTICAL := SUM;
END ANALYTICAL;
REAL PROCEDURE EXPERIMENTAL(N); INTEGER N;
BEGIN
INTEGER NUM;
INTEGER COUNT;
INTEGER RUN;
FOR RUN := 1 STEP 1 UNTIL TESTS DO
BEGIN
BOOLEAN ARRAY BITS(1:N);
INTEGER I;
FOR I := 1 STEP 1 UNTIL N DO
BEGIN
NUM := RANDINT(1,N,SEED);
IF BITS(NUM) THEN GOTO L;
BITS(NUM) := TRUE;
COUNT := COUNT + 1;
END FOR I;
L:
END FOR RUN;
EXPERIMENTAL := COUNT / TESTS;
END EXPERIMENTAL;
INTEGER SEED, TESTS;
SEED := ININT;
TESTS := 1000000;
BEGIN
REAL A, E, ERR;
INTEGER I;
OUTTEXT(" N AVG CALC %DIFF"); OUTIMAGE;
FOR I := 1 STEP 1 UNTIL 20 DO
BEGIN
A := ANALYTICAL(I);
E := EXPERIMENTAL(I);
ERR := (ABS(E-A)/A)*100.0;
OUTINT(I, 2);
OUTFIX(E, 4, 7);
OUTFIX(A, 4, 10);
OUTFIX(ERR, 4, 10);
OUTIMAGE;
END FOR I;
END;
END

View 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}]]
}

View file

@ -0,0 +1,39 @@
link printf, factors
$define MAX_N 20
$define TIMES 1000000
$define RAND_MAX 2147483647
procedure expected(n)
local sum := 0
every i := 1 to n do
sum +:= factorial(n) / (n ^ i) / factorial(n - i)
return sum
end
procedure test(n, times)
local i, count := 0, x, bits
every i := 0 to times-1 do {
x := 1
bits := 0
while iand(bits, x)=0 do {
count +:= 1
bits := ior(bits, x)
x := ishift(1 , ?n-1)
}
}
return count
end
procedure main(void)
local n, cnt, avg, theory, diff
write(" n\tavg\texp.\tdiff\n", repl("-",29))
every n := 1 to MAX_N do {
cnt := test(n, TIMES)
avg := real(cnt) / TIMES
theory := expected(n)
diff := (avg / theory - 1) * 100
printf("%2d %8.4r %8.4r %6.3r%%\n", n, avg, theory, diff)
}
return 0
end

View file

@ -0,0 +1,39 @@
import rand
import math
const nmax = 20
fn main() {
println(" N average analytical (error)")
println("=== ========= ============ =========")
for n := 1; n <= nmax; n++ {
a := avg(n)
b := ana(n)
println("${n:3} ${a:9.4f} ${b:12.4f} (${math.abs(a-b)/b*100:6.2f}%)" )
}
}
fn avg(n int) f64 {
tests := int(1e4)
mut sum := 0
for _ in 0..tests {
mut v := [nmax]bool{}
for x := 0; !v[x]; {
v[x] = true
sum++
x = rand.intn(n) or {0}
}
}
return f64(sum) / tests
}
fn ana(n int) f64 {
nn := f64(n)
mut term := 1.0
mut sum := 1.0
for i := nn - 1; i >= 1; i-- {
term *= i / nn
sum += term
}
return sum
}

View file

@ -0,0 +1,37 @@
Const MAX = 20
Const ITER = 1000000
Function expected(n As Long) As Double
Dim sum As Double
For i = 1 To n
sum = sum + WorksheetFunction.Fact(n) / n ^ i / WorksheetFunction.Fact(n - i)
Next i
expected = sum
End Function
Function test(n As Long) As Double
Dim count As Long
Dim x As Long, bits As Long
For i = 1 To ITER
x = 1
bits = 0
Do While Not bits And x
count = count + 1
bits = bits Or x
x = 2 ^ (Int(n * Rnd()))
Loop
Next i
test = count / ITER
End Function
Public Sub main()
Dim n As Long
Debug.Print " n avg. exp. (error%)"
Debug.Print "== ====== ====== ========"
For n = 1 To MAX
av = test(n)
ex = expected(n)
Debug.Print Format(n, "@@"); " "; Format(av, "0.0000"); " ";
Debug.Print Format(ex, "0.0000"); " ("; Format(Abs(1 - av / ex), "0.000%"); ")"
Next n
End Sub

View file

@ -0,0 +1,48 @@
Const MAX = 20
Const ITER = 100000
Function expected(n)
Dim sum
ni=n
For i = 1 To n
sum = sum + fact(n) / ni / fact(n-i)
ni=ni*n
Next
expected = sum
End Function
Function test(n )
Dim coun,x,bits
For i = 1 To ITER
x = 1
bits = 0
Do While Not bits And x
count = count + 1
bits = bits Or x
x =shift(Int(n * Rnd()))
Loop
Next
test = count / ITER
End Function
'VBScript formats numbers but does'nt align them!
function rf(v,n,s) rf=right(string(n,s)& v,n):end function
'some precalculations to speed things up...
dim fact(20),shift(20)
fact(0)=1:shift(0)=1
for i=1 to 20
fact(i)=i*fact(i-1)
shift(i)=2*shift(i-1)
next
Dim n
Wscript.echo "For " & ITER &" iterations"
Wscript.Echo " n avg. exp. (error%)"
Wscript.Echo "== ====== ====== =========="
For n = 1 To MAX
av = test(n)
ex = expected(n)
Wscript.Echo rf(n,2," ")& " "& rf(formatnumber(av, 4),7," ") & " "& _
rf(formatnumber(ex,4),6," ")& " ("& rf(Formatpercent(1 - av / ex,4),8," ") & ")"
Next

View file

@ -0,0 +1,44 @@
import "random" for Random
import "/fmt" for Fmt
var nmax = 20
var rand = Random.new()
var avg = Fn.new { |n|
var tests = 1e4
var sum = 0
for (t in 0...tests) {
var v = List.filled(nmax, false)
var x = 0
while (!v[x]) {
v[x] = true
sum = sum + 1
x = rand.int(n)
}
}
return sum/tests
}
var ana = Fn.new { |n|
if (n < 2) return 1
var term = 1
var sum = 1
for (i in n-1..1) {
term = term * i / n
sum = sum + term
}
return sum
}
System.print(" N average analytical (error)")
System.print("=== ========= ============ =========")
for (n in 1..nmax) {
var a = avg.call(n)
var b = ana.call(n)
var ns = Fmt.d(3, n)
var as = Fmt.f(9, a, 4)
var bs = Fmt.f(12, b, 4)
var e = (a - b).abs/ b * 100
var es = Fmt.f(6, e, 2)
System.print("%(ns) %(as) %(bs) (%(es)\%)")
}

View file

@ -0,0 +1,33 @@
const N=20;
(" N average analytical (error)").println();
("=== ========= ============ =========").println();
foreach n in ([1..N]){
a := avg(n);
b := ana(n);
"%3d %9.4f %12.4f (%6.2f%%)".fmt(
n, a, b, ((a-b)/b*100)).println();
}
fcn f(n){ (0).random(n) }
fcn avg(n){
tests := 0d10_000;
sum := 0;
do(tests){
v:=(0).pump(n,List,T(Void,False)).copy();
while(1){
z := f(n);
if(v[z]) break;
v[z] = True;
sum += 1;
}
}
return(sum.toFloat() / tests);
}
fcn fact(n) { (1).reduce(n,fcn(N,n){N*n},1.0) } //-->Float
fcn ana(n){
n=n.toFloat();
(1).reduce(n,'wrap(sum,i){ sum+fact(n)/n.pow(i)/fact(n-i) },0.0);
}