My young son has me playing the Chutes and Ladders board game with him. While fun for him, this simple game of chance provides little stimulation (for an adult) after the first few spins of the dial. So, being a geek, I coded up some Perl to dump out how many spins it takes to win a game, how often a player climbs a specific ladder, etc. You know -- absolute crucial knowledge for parents.
Now, I'll be able to impress with nuggets such as: "You'll most likely win in 22 moves! But, don't bet on it because that only happens 2.5% of the time".
| Metric | Number of spins |
|---|---|
| Mean | 39.6 |
| Median | 33 |
| Mode | 22 |
| Minimum | 7 |
| Maximum | Infinite? |
| 10% | 15 |
| 90% | 73 |
"10%" means that only about 10% of games will end in 15 moves or less. Similarly, "90%" means that 90% of games will end in 73 moves or less.
The maximum number of moves seems to be infinite. In a sample of 1 million games, the maximum number of moves was 399; after 2 million, it was 437. Maybe there's an asymptote, I don't know. In any case, I think it is practically impossible to be that unlucky. Update: Refer to esper's reply below for more details.
This program merely dumps out raw data. Statistical analysis software sold separately. Batteries not included.
=head1 NAME B<chutes_n_ladders> - Stats for "Chutes and Ladders" game =head1 SYNOPSIS chutes_n_ladders [options] Options: -help verbose help -moves verbose display of all moves -games int number of games =head1 DESCRIPTION Generate statistics for the "Chutes and Ladders" game by running a user-specified number of games. All metrics are for the winning playe +r on a standard 10x10 square game board. All moves are for a single pla +yer. =head1 OPTIONS =over 4 =item moves Use the C<-moves> option to display all individual moves for each game +. chutes_n_ladders -moves =item games By default, one game is played. To run more games, use the C<-games> +option. chutes_n_ladders -games 500 =item help Show verbose usage information. =back =head1 EXAMPLES Run 1000 games and dump the stats to an output file for further proces +sing: chutes_n_ladders -g 1000 > out.txt =cut use strict; use warnings FATAL => 'all'; #use diagnostics; use Data::Dumper; use Getopt::Long; use Pod::Usage; my $games; my $verbose = 0; my %special = ( # Ladders # Start 1 => {end => 38, action => 'up ladder'}, 4 => {end => 14, action => 'up ladder'}, 9 => {end => 31, action => 'up ladder'}, 21 => {end => 42, action => 'up ladder'}, 28 => {end => 84, action => 'up ladder'}, 36 => {end => 44, action => 'up ladder'}, 51 => {end => 67, action => 'up ladder'}, 71 => {end => 91, action => 'up ladder'}, 80 => {end => 100, action => 'up ladder'}, # Chutes # Start 16 => {end => 6, action => 'down chute'}, 48 => {end => 26, action => 'down chute'}, 49 => {end => 11, action => 'down chute'}, 56 => {end => 53, action => 'down chute'}, 62 => {end => 19, action => 'down chute'}, 64 => {end => 60, action => 'down chute'}, 87 => {end => 24, action => 'down chute'}, 93 => {end => 73, action => 'down chute'}, 95 => {end => 75, action => 'down chute'}, 98 => {end => 78, action => 'down chute'} ); parse_args(); for my $i (1 .. $games) { game($i); } sub game { my $game = shift; my %counts; my $mvcnt = 0; my $pos = 0; while ($pos != 100) { $mvcnt++; my $spin = int(rand(6)) + 1; # random spin (1-6) my $tmp = $pos + $spin; my $msg = sprintf 'mvcnt=%4d, spin=%1d, start=%2d, ', $mvcnt, +$spin, $pos; $counts{spin}{$spin}++; $counts{move} = $mvcnt; my $action; if ($tmp > 100) { $action = 'stay'; $counts{stay}++ } elsif (exists $special{$tmp}) { $pos = $special{$tmp}{end}; $action = $special{$tmp}{action}; $counts{$action}{$tmp}++ } else { $pos = $tmp; $action = 'advance'; $counts{advance}++ } $msg .= sprintf 'end=%3d', $pos; print "$msg ($action)\n" if $verbose; } print Dumper(\%counts); # These may simplify parsing the output: #for (keys %{$counts{spin}}) {print "spin$_ = $counts{spin}{$_}\n"} #for (keys %{$counts{'up ladder' }}) {print "ladder$_ = $counts{'up + ladder' }{$_}\n"} #for (keys %{$counts{'down chute'}}) {print "chute$_ = $counts{'do +wn chute'}{$_}\n"} print "Game = $game , Moves = $mvcnt\n"; } sub parse_args { my $help; GetOptions( 'moves' => \$verbose, 'games=i' => \$games, 'help' => \$help ) or pod2usage(); $help and pod2usage(-verbose => 2); $games = 1 unless $games; @ARGV and pod2usage(-msg => "Error: unexpected args: @ARGV", -verbo +se => 1); }
Update July 1, 2009: Removed unused $full variable in parse_args sub. Refer to wrinkles' node below.
Miscellaneous game characteristics:
Here is a sample histogram of the number of moves for 1 million games:
Number of samples in population: 1000000 Value range: 7 - 399 Mean value: 39 Median value: 33 < 7: 0 7 - 46: 698863 46 - 85: 238740 85 - 124: 49545 124 - 163: 10267 163 - 202: 2029 202 - 241: 436 241 - 280: 97 280 - 319: 17 319 - 358: 5 358 - 397: 0 >= 397: 1
What fascinating statistics can you dial up?
|
|---|