About two years ago, Veritasium posted The Riddle That Seems Impossible Even If You Know The Answer on Youtube. Today i was rewatching that video, because after seeing it initially i had some doubts, and it was a bit of an itch i finally decided to scratch.
The basic riddle goes something like this (watch the video for a much more coherent explanation AND the solution):
If prisoners just do random sampling, their chances are 0.5**100 = 0.0000000000000000000000000000008.
Is there a better tactic? (Rest of the post in spoiler tags if you want to have a go on the problem yourself).
According to Veritasium, the solution is this: Every prisoner picks the box with their number on top (=prisoner 42 picks box 42) to start with. He opens the box. If the box doesn't contain his number, he then picks the box with THAT number to open next, and so on. This improves the chances for the whole group to 0.31 (31%).
I'm not good at doing mathematics proves, or writing scientific papers. My one (and only) real talent is crunching data with software. But, wait. This IS a problem you can simulate! No math degree, no AI, just throw some raw CPU cycles at the problem and see if we can get a reasonable match to the results Veritasium posted.
#!/usr/bin/env perl # https://www.youtube.com/watch?v=iSNsgj1OCLA use v5.40; use strict; use warnings; use diagnostics; use Array::Contains; my $PRISONERCOUNT = 100; # How many prisoners my $OPENBOXES = $PRISONERCOUNT / 2; # Every prisoner can open half the + boxes my $LOOPCOUNT = 10_000; my $DEBUG = 0; STDOUT->autoflush(1); my @results = (0, 0); for(my $l = 0; $l < $LOOPCOUNT; $l++) { if($DEBUG) { print "== SIMULATION $l ==\n"; } elsif($l % 100 == 0) { print "== SIMULATION $l of $LOOPCOUNT ==\r"; # non-debug: over +write the line without scrolling } $results[simulate()]++; } print "\n"; print "Success: ", $results[1], "\n"; print "Fail: ", $results[0], "\n"; print "Fail rate: ", $results[0] / ($results[0] + $results[1]) * 100, +"%\n"; sub simulate { my $boxes = generateBoxes(); DumpBoxes($boxes) if($DEBUG); print "Checking prisoner " if($DEBUG); for(my $i = 0; $i < $PRISONERCOUNT; $i++) { print $i, " " if($DEBUG); if(!checkBoxes($boxes, $i, $OPENBOXES)) { print "Failed!\n" if($DEBUG); return 0; } } print "OK\n" if($DEBUG); return 1; } sub generateBoxes { print "Generating boxes...\n" if($DEBUG); my @boxes; while(scalar @boxes < $PRISONERCOUNT) { my $prisoner = int(rand($PRISONERCOUNT)); if(!contains($prisoner, \@boxes)) { push @boxes, $prisoner; } } return \@boxes; } sub checkBoxes($boxes, $prisoner, $count) { my $currentbox = $prisoner; while($count) { my $val = $boxes->[$currentbox]; # Get content of current box if($val == $prisoner) { return 1; } $currentbox = $val; $count--; } return 0; } sub DumpBoxes($boxes) { print "---- BOXES -------------\n"; for(my $i = 0; $i < $PRISONERCOUNT; $i++) { print $i, " => ", $boxes->[$i], "\n"; } print "---- LOOPS -------------\n"; my @seen; for(my $i = 0; $i < $PRISONERCOUNT; $i++) { my $currentbox = $i; my $count = 100; my $ok = 1; my @current; while($count) { if(contains($currentbox, \@seen)) { $ok = 0; # Part of already known loop last; } push @current, $currentbox; my $val = $boxes->[$currentbox]; if($val == $i) { last; # Loop done } $currentbox = $val; } if($ok) { print join(' ', @current), "\n"; push @seen, @current; } } print "------------------------\n"; return; }
And it seems to be a relatively good match:
$ perl simulate.pl == LOOP 99900 == Success: 31139 Fail: 68861 Fail rate: 68.861%
And if we activate $VERBOSE, we can get a simple view of those loops Veritasium was talking about:
---- LOOPS ------------- 0 72 86 73 80 1 96 19 83 91 47 75 18 53 3 50 24 81 59 38 23 44 67 39 55 65 2 20 45 98 84 89 63 93 46 58 68 28 56 64 78 6 87 52 8 82 97 34 31 85 7 +9 12 41 48 70 66 37 5 49 33 51 15 57 54 69 90 26 43 14 94 76 9 88 40 4 42 25 99 27 77 16 10 74 36 22 7 13 71 61 62 11 95 21 17 30 29 32 35 60 92 ------------------------
Frankly, even having programmed a full simulation of the solution myself, it still absolutely boggles my mind that this actually works at all. Maths is weird.
|
---|