Last active
July 9, 2017 23:40
-
-
Save briandfoy/1f27762e511d9074fb52a85ca0ace479 to your computer and use it in GitHub Desktop.
A Perl 6 version of Uri Wilensky's simulation
This file contains hidden or 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
#!/Applications/Rakudo/bin/perl6 | |
# http://www.decisionsciencenews.com/2017/06/19/counterintuitive-problem-everyone-room-keeps-giving-dollars-random-others-youll-never-guess-happens-next/ | |
multi MAIN ( Int $players = 100, Int $dollars = 100, Int $max-rounds = 5000 ) { | |
my @array = { | |
wallet => $dollars, # the current money N has | |
received => 0, # the cumulative money received | |
'given' => 0, # the cumulative money given | |
} xx $players; | |
my &recipient = &donate-to.assuming( @array.elems ); | |
# the starting sum should be the same as the ending some | |
# and we'll check that. | |
my $starting-sum = [+] @array»<wallet>; | |
for ^$max-rounds { | |
state $round = 0; | |
$round++; | |
for @array.kv -> $i, $wallet { | |
next if @array[$i]<wallet> == 0; # can't give if you don't have | |
my $j = &recipient( $i ); | |
send-from-to( @array[$i], @array[$j] ); | |
} | |
} | |
my $max = @array»<wallet>.max; | |
my $min = @array»<wallet>.min; | |
my $zeros = @array»<wallet>.grep( * == 0 ).elems; | |
my $sum = [+] @array»<wallet>; | |
# there's also the Stats module | |
say "Rounds: $max-rounds Max: $max Min: $min Zeros: $zeros Sum: $sum Starting Sum: $starting-sum Values: {@array.map( { qq/[{.<wallet given received>.join: ','}]/ } ).join: ','}"; | |
} | |
sub donate-to ( Int $max, Int $this ) { | |
#| Find a random integer between [0,$max) that is not $this | |
loop { | |
my $donate-to = $max.rand.Int; | |
return $donate-to if $donate-to != $this | |
} | |
} | |
sub send-from-to ( Hash $giver where $giver<wallet> > 0, Hash $receiver, Int $amount = 1 ) { | |
#! Transfer money from one wallet to another | |
$giver<wallet given> Z+= (-$amount, $amount); | |
$receiver<wallet received> Z+= ( $amount, $amount); | |
True; # hack: https://stackoverflow.com/q/45001820/2766176 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment