Mailing List Archive: 49091 messages

# A Rebol Challenge. The Monty Hall Puzzle

### [1/22] from: reichart::prolific::com at: 15-Dec-2001 23:47

We Reboler have been challenged. I was posing some puzzles with some friends on another mailing list I belong to, the enjoyment of which is provided here first should you want to try and solve this for yourself. However, one of the people responding was a programmer, and he wrote a program to try to solve the problem. First he wrote this in Pearl (183 characters), then in Matlab (136 characters). I put it to you--smarter people than I--to put this man to shame! Give me your best Rebolette, and I will make him see the error of his ways :-) OK, no looking this up on the web. This is a real fun one if you have not seen it before, or better stated, worked through it. The scenario is such: you are given the opportunity to select one closed door of three, behind one of which there is a prize. The other two doors hide "goats" (or some other such "non-prize"), or nothing at all. Once you have made your selection, Monty Hall will open one of the remaining doors, revealing that it does not contain the prize. He then asks you if you would like to switch your selection to the other unopened door, or stay with your original choice. Here is the problem: Does it matter if you switch? P.S. this problem was presented to two of my engineers and myself many many years ago. We were told that the "staff" scientist at the company of the presenter all got it wrong. So the three of us worked on it together for about 25 minutes. Came to our conclusion, then wrote a computer program to prove it. I then wrote a layman's description of "why." Which I found was needed because SO MANY PEOPLE CAN NOT ACCEPT THE ANSWER. Especially statisticians! Too funny. If anyone wants a copy, I will dig it up. Now for the Email from my friend: He writes... Nah, matlab is the way to go for this: b=sum(floor(3*rand(100,100))==0);y=floor(3*rand(100,100)); o=(floor(2*rand(100,100))+1).*(y==0)+(3-y).*(y>0);c=sum(y.*o>0); d=sum(c>b-c<b); [b;c] if (d>90) fprintf(1,"Switching is better (95%%+ confidence)\n"); end But maybe you can do better in Rebol. I don't see a way to off the top of my head. Note that if we're just comparing the core computation, the matlab is barely three lines. (The "o" variable is not strictly needed, but I am including it anyway to explicitly construct the door-picked-by-Monty.) Perl is 183 characters, not counting invocation from the command line or comments. Matlab is 136. /usr/bin/perl -e 'print "St Sw (%win)\n";\$d=0;for(\$i=0;\$i<100;\$i++){ \$b=0;\$c=0;for(\$a=0;\$a<100;\$a++){\$b+=int(rand(3))==0}; for(\$a=0;\$a<100;\$a++){\$y=int(rand(3));\$o=\$y?(3-\$y):(int(rand(2))+1); \$c+=\$o*\$y>0;};\$d+=(\$c>=\$b)-(\$c<=\$b);print "\$b \$c\n"};print "St Sw (%win)"; if (\$d>90) { print "\nSwitching is better (95%+ confidence)" };print "\n"' Reichart... [Reichart--Prolific--com] Be useful.

### [2/22] from: carl:cybercraft at: 17-Dec-2001 0:15

On 16-Dec-01, Reichart wrote:
> We Reboler have been challenged. > I was posing some puzzles with some friends on another mailing list
<<quoted lines omitted: 44>>
> (%win)"; if (\$d>90) { print "\nSwitching is better (95%+ > confidence)" };print "\n"'
Not being a statistician, (or having a clue what the above code does:), my approach to such problems is to simulate them many times and see if there's a noticable difference in the results. So here's my code to do that, but it may be bugged as it wasn't giving the results I was expecting. But then, what's expected is not what we're supposed to get, right? (: rebol[]k: s: 0 r: func[n][random n]a: does[p: r 3 c: r 3 p = c] loop 10000 [if a[k: k + 1]if if not a[r 2 = 1][s: s + 1]]print ["Kept" k "Switched" s] I especially like the "if if" as it sounds like an accurate description of my code. (: Anyway, it's 151 bytes long for what it's worth. -- Carl Read

### [3/22] from: sunandadh:aol at: 16-Dec-2001 6:52

Hi Reichart.
> But maybe you can do better in Rebol. I don't see a way to off the top of > my head. Note that if we're just comparing the core computation, the
matlab
> is barely three lines. (The "o" variable is not strictly needed, but I am > including it anyway to explicitly construct the > door-picked-by-Monty.)
Here's my attempt. It runs a simulated Monty 500 times. I get a "length" of 142 (length? mold load %doors.r), but I don't have the same text message as you and the "external" length could be shorter by one-lining it all and reducing the variables to W and N. The core calculation is just one line, but I'm using a different algorithm. rebol [] Win: 0 n: 0 loop 500 [ n: n + 1 win: win + last sort next random [0 0 1] ] Print ["Win%" win * 100 / n] In slow motion and with intermediate variables this is: Three doors: one has a 1 behind it (thats the car) the other two have a big zero. Doors: random [0 0 1] whichever door I pick is modelled by MyDoor: first Doors Monty then shows me a zero door: MontyDoor: mimimum Door/2 Door/3 I then select the other of Monty's doors: MySwappedDoor: Maximim Door/2 Door/3 which is the same as MySwappedDoor: last sort next Doors so if MySwappedDoor is a 1, I'm a winner! Sunanda

### [4/22] from: rotenca:telvia:it at: 16-Dec-2001 14:11

----- Original Message ----- From: <[SunandaDH--aol--com]> To: <[rebol-list--rebol--com]> Sent: Sunday, December 16, 2001 12:52 PM Subject: [REBOL] Re: A Rebol Challenge. The Monty Hall Puzzle
> Hi Reichart. > > > > But maybe you can do better in Rebol. I don't see a way to off the top
of
> > my head. Note that if we're just comparing the core computation, the > matlab > > is barely three lines. (The "o" variable is not strictly needed, but I
am
> > including it anyway to explicitly construct the > > door-picked-by-Monty.)
<<quoted lines omitted: 10>>
> ] > Print ["Win%" win * 100 / n]
Beautiful! You can remove the n + 1: Win: 0 n: 500 print ["Win%" 100 / n * loop n [win: win + last sort next random [0 0 1]]] --- Ciao Romano

### [5/22] from: brett:codeconscious at: 17-Dec-2001 0:33

Hi Reichart, The one is not as wonderous as Sunanda's solution but is interesting because you can use whatever symbols you like to represent the boxes :) The code below simulates the always switch strategy - returns rough probability of winning: REBOL[] d: {123}w: 0 loop n: 500 [ p: func[s][copy/part random s 1] b: p d c: p d if b = p union b c [w: w + 1]] w / n d: represents the choices - could have been any series of 3 elements e.g [box1 box2 box3] p: makes a random selection from a series b: the winning box c: the first choice (union b c) is equivalent to the two closed boxes after monty has opened one empty box That is it is equivalent too box-to-remove: exclude d union b c choices: exclude d box-to-remove An anxious person would probably figure out they'd more than likely goofed first go :) Cheers Brett.

### [6/22] from: rebol:optushome:au at: 16-Dec-2001 23:58

> REBOL[] > d: {123}w: 0 loop n: 500 [
<<quoted lines omitted: 4>>
> [box1 box2 box3] > p: makes a random selection from a series
Hi Brett, Just to point out a lesser known refinement of random p: func[s][copy/part random s 1] I think could be replaced by p: func[s][random/only s] Cheers, Allen K

### [7/22] from: andreas:bolka:gmx at: 16-Dec-2001 15:17

16 Dec 2001, 08:47:34, Reichart wrote:
> P.S. this problem was presented to two of my engineers and myself > many many years ago. We were told that the "staff" scientist at the
<<quoted lines omitted: 4>>
> PEOPLE CAN NOT ACCEPT THE ANSWER. Especially statisticians! Too > funny. If anyone wants a copy, I will dig it up.
I'd like to have a copy ;) -- Best regards, Andreas mailto:[andreas--bolka--gmx--net]

### [8/22] from: sunandadh:aol at: 16-Dec-2001 10:19

Hi Romano,
> Beautiful! You can remove the n + 1: > > Win: 0 n: 500 print ["Win%" 100 / n * loop n [win: win + last sort next > random > [0 0 1]]] >
Thanks. I thought I'd minimised it completely, but it's amazing what teamwork can do. If we just want to print the winning percentage, and we shorten the variable names we get: W: 0 n: 500 100 / n * loop n [w: w + last sort next random [0 0 1]] which is just length? {W: 0 n: 500 100 / n * loop n [w: w + last sort next random [0 0 1]]} 67 bytes. Which--spookily enough--equals our win percentage for swapping. Sunanda.

### [9/22] from: doncox:enterprise at: 16-Dec-2001 17:01

On 16-Dec-01, Andreas Bolka wrote:
> 16 Dec 2001, 08:47:34, Reichart wrote: >> P.S. this problem was presented to two of my engineers and myself
<<quoted lines omitted: 6>>
>> funny. If anyone wants a copy, I will dig it up. > I'd like to have a copy ;)
If it's not too long, post it. Regards -- Don Cox [doncox--enterprise--net]

### [10/22] from: rotenca:telvia:it at: 16-Dec-2001 17:33

Hi Sunanda,
> Thanks. I thought I'd minimised it completely, but it's amazing what
teamwork
> can do.
Nothing in front of your wonderful: last sort next random P.S. Are you from India? --- Ciao Romano

### [11/22] from: rebol665:ifrance at: 16-Dec-2001 17:37

Hi Romano and Sunanda, Your work is brilliant ! It helps me to get to the problem, and finally my 17 years'old son explained it to me. If you consider that each time I loose I did not win, the answer can be shorten a bit. rebol[] win: 100 print ["Win% = " loop win [ win: win - first random [0 0 1]]] It is a beat cheatting considering that your version iterate 500 times so I give also my 1000 iterations version. rebol[] win: 1000 print ["Win% = " (loop win [ win: win - first random [0 0 1]]) / 10] These are respectively 43 and 51 bytes long. Patrick

### [12/22] from: g:santilli:tiscalinet:it at: 16-Dec-2001 15:27

Hello Reichart! On 16-Dic-01, you wrote: R> Does it matter if you switch? Readable version: random/seed now no-switch-wins: 0 switch-wins: 0 loop 1000 [ winning: random 3 your-choice: random 3 either your-choice = winning [ no-switch-wins: no-switch-wins + 1 ] [ switch-wins: switch-wins + 1 ] ] print [ "If you switch, you win" switch-wins "times" newline "If you don't switch, you win" no-switch-wins "times" ] Compact version: r: does[random 3]n: s: 0 loop 1000[either r = r[n: n + 1][s: s + 1]] print [ "If you switch, you win" s "times" newline "If you don't switch, you win" n "times" ] I presume the code you show is doing something different, but I don't speak perl or matlab... :) Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

### [13/22] from: sunandadh:aol at: 16-Dec-2001 14:18

Hi Patrick,
> Your work is brilliant ! It helps me to get to the problem, and finally my > 17 years'old son explained it to me. If you consider that each time I loose > I did not win, the answer can be shorten a bit.
Thanks,
> rebol[] > win: 100 print ["Win% = " loop win [ win: win - first random [0 0 1]]]
<<quoted lines omitted: 4>>
> 10] > These are respectively 43 and 51 bytes long.
Good stuff! Your solutions embody the logic that : 1. If I stick with what I've got, I've a 1/3rd chance of winning 2. Therefore Monty has a 2/3 chance of having the car 3. But Monty has shown me an empty door, So, if Monty has the car it MUST be behind the door he didn't open. 4. Therefore I'll take that unopened door and win 2/3s of the time Given we all accept that logic, that, we could shorten the puzzle even more: Print ["Win% " 200 / 3] <g!> The problem being that not everyone does accept that logic at first view. So, to be fair, we need code that runs a fair emulation of making a choice. Sunanda

### [14/22] from: sunandadh:aol at: 16-Dec-2001 16:43

Hi Romano, P.S.
> Are you from India?
Sorry No. Irish descent, living in Birmingham, England. Sunanda.

### [15/22] from: rebol665:ifrance at: 16-Dec-2001 22:54

Hi, Sunanda Print ["Win% " 200 / 3] I came to the same conclusion thanks to your "slow motion" explanation but I did not dare to put that. Indeed the 2/3 emerges from your explanation.
>so if MySwappedDoor is a 1, I'm a winner!
Actually this already points to "how can that happens if the 1 comes first in the block?". However it was not my aim to "stole your thunder" (as would Monica Geller say*).
>The problem being that not everyone does accept that logic at first view.
My version could have come without any assumption, even without knowing what it was all about. Your program was counting how many times a random block including two zero and only one one could either be [0 0 1] or [0 1 0]. My version said that it suffice to count how many times it would not be [1 0 0]. I must confess that I too prefer your version that not only gives the answers but also "explains" it. That was a very very clever piece of code ! Patrick ps: * comes from the serie FRIENDS, episode 701

### [16/22] from: brett:codeconscious at: 17-Dec-2001 11:34

Hi Allen, You're right. I didn't know about that refinement. I would have used "first random s" instead of "random/only". But here though, I used copy/part because I needed a series to work in the union operation. Otherwise I'll need to add "to-string" before the "random/only" and d will need to be restricted to being a string only. Doing this yields, REBOL[] d: {123}w: 0 loop n: 500 [ p: func[s][to-string random/only s] b: p d c: p d if b = p union b c [w: w + 1]] w / n Which is about 3 characters longer than the original :) Cheers Brett.

### [18/22] from: carl:cybercraft at: 17-Dec-2001 21:13

> Not being a statistician, (or having a clue what the above code > does:), my approach to such problems is to simulate them many times
<<quoted lines omitted: 8>>
> description of my code. (: Anyway, it's 151 bytes long for what it's > worth.
I thought the above was bugged, and it was. Here's a fixed version... rebol[]k: s: 0 r: func[n][random n]m: does[p: r 3 c: r 3 p = c] loop 10000 [if m[k: k + 1]if not m[s: s + 1]]print ["Kept" k "Switched" s] Nowhere near as short as some of the other posts, but anyway, here's my reasoning behind it... The prize is placed behind one of 3 doors... prize: random 3 You choose one of the doors... chosen: random 3 Now, Monty can see if they're a match - ie, if you've picked a winner... matched?: prize = chosen Which returns true if you've chosen the prize. If you decide to keep this then it's obvious (I hope:) that you had 1 chance in 3 of picking the prize. But what if you accept Monty's offer to switch? Well, there's only two posibilities: 1) You'd chosen the prize, so switching from that means you lose regardless of what Monty does. 2) You hadn't chosen the prize, Monty exposes the other losing door, and so you switch to the winning door. So a switch always means a reversal of your original choice - a winning choice becoming a losing one and vice-versa. So... matched?: not matched? But what happens to the "1 chance in 3 of picking the prize."? Well that also means you had 2 chances in 3 of losing, right? And the switch makes an original loss a win, so switching gives you 2 chances in 3 of winning, thus doubling your chances of a win. Note that I originally (though vaguely) thought switching would improve your chances from 1 in 3 to 1 in 2, but this result is much more fun. (: -- Carl Read

### [19/22] from: sunandadh:aol at: 17-Dec-2001 9:39

Hi Joel,
> It seems to me that the problem in the original post was persuasion > and not just computation. That being the case, the text of the
<<quoted lines omitted: 4>>
> program that seemed to contain assumptions about the very answer > I was having trouble with.
I completely agree that a highly compressed program isn't often a great way to win an argument. But (just to defend myself for a moment) my attempt embodied all the "rules": I picked a door; Monty picked an empty one of the other two; I swap to his unopened one. No built-in assumptions there. i also agree with an earlier post of yours (about Perl and parlor games). The best test of a programming language isn't how compact a program it can write, but (I would claim) how easy it is to write maintainable programs in it. But even that tests mainly the design skills and long-term vision of the programmer. A good test of all of our (and Perl and Matlab) solutions is how easily can they be modified as various "real world" changes are required. Almost by definition, we can't know what our programs will face over there lifetimes, but here are a few of the sort of things that might beset a Monty simulator: -- Not three doors, but 10 -- Not 10 but 25 million doors (challenging many language implementations to handle this as in-store arrays) -- Monty opens more than one door --there is more than one door with a car behind it -- I get to pick more than one originally, but can only open ONE of mine, OR one of his once Monty has opened the ones on his side -- I get to pick more than one door, and Monty opens N of mine and M of his. -- There are several prizes (a Saab and a Mercedes) including some booby prizes (A tribe and a yugo maybe). Monty will open up to N doors at random; I can't win the prize behind an opened door; but I can tell him to stop at any moment, and then make my choice. -- The program running as a CGI is so overwhelming popular that it is swamping the server: rewrite it to use half the cpu cycles. -- The government will buy 3,000,000 copies but only after the simulation is run not 500 times but 500,000,000 times. (Rebol can handle this number, but for most languages Wins + 1 = Wins for a sufficiently large value of Wins. If you exceed that, you need extra special code). I can see how my solution will naturally extend for some of these; can be bodged into shape for others; and would be scrapped and rewritten for the rest. And that's programming! Sunanda.

### [20/22] from: joel:neely:fedex at: 17-Dec-2001 12:27

> I completely agree that a highly compressed program isn't often a > great way to win an argument. But (just to defend myself for a > moment) ... >
No defense necessary (except perhaps on my part for poor choice of wording -- perhaps I should have said "inferences" or "conclusions" instead of "assumptions")! All I meant was that several of the very compact solutions were the *result* of reasoning about the problem, rather than a *record* of the reasoning process itself. In such a situation, a skeptical audience simply shifts its skepticism to the program itself, rather than having its skepticism relieved.
> The best test of a programming language isn't how compact a program > it can write, but (I would claim) how easy it is to write maintain- > able programs in it. But even that tests mainly the design skills > and long-term vision of the programmer. >
Per your following discussion, I believe we'd agree that "ability to guess -- most of the time -- what is likely to change in the future" is an important part of "long-term vision".
> A good test of all of our (and Perl and Matlab) solutions is how > easily can they be modified as various "real world" changes are > required. Almost by definition, we can't know what our programs > will face over there lifetimes, but here are a few of the sort of > things that might beset a Monty simulator: >
...
> I can see how my solution will naturally extend for some of these; > can be bodged into shape for others; and would be scrapped and > rewritten for the rest. And that's programming! >
A *VERY* interesting and thought-provoking list! Thanks! -jn-

### [21/22] from: carl:cybercraft at: 18-Dec-2001 11:57

> Here's a fixed version... > rebol[]k: s: 0 r: func[n][random n]m: does[p: r 3 c: r 3 p = c] loop
<<quoted lines omitted: 25>>
> switch makes an original loss a win, so switching gives you 2 > chances in 3 of winning, thus doubling your chances of a win.
After showing the above explaination to someone (not on this list) they still didn't believe it, so I've written a graphical version in the hope that pictures will win out where words fail... (Not a View version though - run it from the Console.) rebol [] doors: func [n c][ d: copy/deep ["[ ]" "[ ]" "[ ]"] d/:n/2: c return d ] game: does [ print " Switching Keeping" prize: random 3 print ["Prize: " doors prize #"P" " " doors prize #"P"] guess: random 3 print ["Guess: " doors guess #"G" " " doors guess #"G"] opened: first random difference [1 2 3] reduce [prize guess] prin ["Opened:" doors opened #"X"] prin " " print either prize = guess [kept: kept + 1 "Win"]["Loss"] sw: first difference [1 2 3] reduce [guess opened] print ["Switch:" doors sw #"S"] prin " " print either prize = sw [switched: switched + 1 "Win"]["Loss"] played: played + 1 print [ "Wins: " switched " " kept " Played:" played ] ] played: 0 kept: 0 switched: 0 quit?: false print "" while [not quit?][ game print "" print "Enter to continue - Esc to quit." inp: input quit?: inp = "q" ] Enough! (: -- Carl Read

### [22/22] from: nitsch-lists:netcologne at: 18-Dec-2001 0:41

RE: [REBOL] Re: A Rebol Challenge. The Monty Hall Puzzle [carl--cybercraft--co--nz] wrote:
> On 17-Dec-01, Carl Read wrote: > > Here's a fixed version...
<<quoted lines omitted: 30>>
> the hope that pictures will win out where words fail... (Not a View > version though - run it from the Console.)
well, thats to complicated to me, i give up. i have a 2/3 choice to get a priceless door, this chances are better, and so i want to be priceless. hey, and if i hit, Monty will show me the other priceless door! so i have two :) happy without a price -Volker ;-)

Notes
• Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted