(Image courtesy Tomohiro Tachi under Creative Commons license.)
Recently I came across a fun programming challenge called the Pythagoras Pie, which was described as:
At a party a pie is to be shared by 100 guests. The first guest gets 1% of the pie, the second guest gets 2% of the remaining pie, the third gets 3% of the remaining pie, the fourth gets 4% and so on.
Write a script that figures out which guest gets the largest piece of pie.
I sat down for a few minutes, and wrote the obvious code. It iterates over the list of guests. For each guest, it calculates how large a piece of pie the guest will get. All the while, it stores size of the largest piece of pie it has seen so far.
Here is a solution in Perl.
sub slice_pie { my $iters = shift; my $pie = 1; my $largest = 0; my $winner = 0; for ( 0 .. $iters ) { my $iter_value = $_ * .01; my $portion = ( $iter_value * $pie ); $pie = $pie - $portion; if ( $portion >= $largest ) { $largest = $portion; $winner = $_; } } print qq[Winner is guest # $winner with the largest portion: $largest\n]; } slice_pie(100);
The answer, as it turns out, is that the 10th guest gets the largest piece of the pie: 0.0628156509555295, or about 6%.
Just for fun, I wrote almost the same exact code once again, except this time in Perl 6. Even though this is a straightforward translation using the same basic loop structure, it has a few nice improvements:
- No need for argument unpacking (saves a horizontal line — vertical compactness is good)
- Nice type annotations mean we can call an integer an
Int
, which also helps the compiler - No need for parens around the
for
andif
checks
sub slice-pie(Int $iters) { my $pie = 1; my $largest = 0; my Int $winner; for 0 .. $iters { my $iter_value = $_ * .01; my $portion = $iter_value * $pie; $pie -= $portion; if $portion >= $largest { $largest = $portion; $winner = $_; } } say qq[Winner is guest number $winner with the largest portion: $largest ]; } slice-pie(100);