Last active
December 10, 2015 13:49
-
-
Save masak/4443780 to your computer and use it in GitHub Desktop.
What's the expected loop length of a randomly chosen mapping from 1..N to 1..N?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my $MAX_N = 20; | |
my $TRIALS = 10_000; | |
for 1 .. $MAX_N -> $N { | |
my @lengths = loop-length(random-mapping($N)) xx $TRIALS; | |
my $average = ([+] @lengths) / @lengths; | |
my $analytical = analytical($N); | |
my $percent_error = abs($analytical - $average) / $analytical * 100; | |
FIRST say " N average analytical (error)"; | |
FIRST say "=== ========= ============ ========="; | |
my @columns = | |
$N.fmt('%3d'), | |
$average.fmt('%9.4f'), | |
$analytical.fmt('%12.4f'), | |
$percent_error.fmt(' (%2d%%)'), | |
; | |
say join ' ', @columns; | |
} | |
sub random-mapping($size) { | |
# Not just a permutation, but a mapping from all 1..N to any 1..N | |
# In other words, .roll, not .pick | |
return hash map { $_ => (1..$size).roll }, 1..$size; | |
} | |
sub loop-length(%mapping) { | |
my %seen; | |
my $current = 1; | |
my $steps = 0; | |
while !%seen{$current}++ { | |
$current = %mapping{$current}; | |
$steps++; | |
} | |
return $steps; | |
} | |
sub analytical($N) { | |
sub postfix:<!>($n) { [*] 1..$n } | |
return [+] (1..$N).map: -> $k { $N! * $k * $k / $N ** ($k + 1) / ($N - $k)! }; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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%) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment