11
\$\begingroup\$

There’s already been a question about simulating the Monty Hall Problem. This one is different. The user will play the Monty Hall Problem. Your program will play the role of the host. Montybot, if you like.

Here are the steps:

  1. Pick (randomly) which of the three doors hides the prize.
  2. Output a visual display of three doors. A simple ABC will do. Or three squares. Or whatever.
  3. Receive input choosing one of the doors. This could be a mouse click on the chosen door, or a single letter input (B) or whatever.
  4. Open another door. You do not open the chosen door. You do not open the door hiding the main prize. That may mean you have no choice, or it may mean that you have a choice of two. If you have a choice of two, pick one at random. Visually indicate that the door has been opened and that no prize was hidden behind it. For a program text-based input/output, this could be as simple as outputting AB0, to show that door C has been opened. Feel free to be more inventive. If you’re doing a GUI program, your choice of display is up to you.
  5. Accept input from the user. The user may input stick or switch (or, for a GUI program, click on buttons, or use a select input, or whatever). If the user enters anything other than stick or switch, the implementation is undefined. Do whatever you want.
  6. Output the text You won! or You lost.
  7. Terminate the progam.

Rules:

  1. When you have to choose something at random, don’t worry about cryptographic randomness. Any rand() function will do.
  2. The program must not cheat. The prize must be in place before the game starts. That is to say that the steps must be performed in the order given: First choose a door behind which to hide your prize, then ask the player to choose. The choice of which door to open in step 4 must happen in step 4: it is not selected in advance.
  3. The output in step 6 must be honest.
  4. This is code golf. Shortest code wins.
\$\endgroup\$
  • \$\begingroup\$ My first time posting on this site, but I lurk a lot, so I think I'm familiar with your norms. \$\endgroup\$ – TRiG Feb 17 '14 at 19:14
  • \$\begingroup\$ On meta.codegolf.stackexchange.com there's a thread for proposing questions and letting people work out any problems with it before it gets officially posted. I don't know if there's anything specifically wrong here that could have been ironed out, but it might be good to know for next time. \$\endgroup\$ – undergroundmonorail Feb 17 '14 at 19:28
  • \$\begingroup\$ I am previewing that the winner will be just another golfscript answer... \$\endgroup\$ – Victor Stafusa Feb 17 '14 at 19:39
  • 1
    \$\begingroup\$ BTW, "being inventive" does not goes well with codegolfing, since being inventive consumes some bytes and the objective of codegolfing is the opposite of this. \$\endgroup\$ – Victor Stafusa Feb 17 '14 at 19:41
  • \$\begingroup\$ Yeah, @Victor. Being inventive is not a requirement. I just (a) did not want to limit this to command line programs, and (b) had no idea how a non-command line program should implement user selection. So I left it up to the answerers. Being inventive is an option, but it's one that'll garner no extra points. \$\endgroup\$ – TRiG Feb 17 '14 at 19:43
2
\$\begingroup\$

APL, 77

p←?3⋄d[e[?⍴e←(⍳3)~p,c←⍞⍳⍨⎕←d←3↑⎕A]]←'_'⋄⎕←d⋄⎕←'You','lost' 'won!'[(c=p)=5=⍴⍞]

Needs ⎕IO←0. Tested on Dyalog.

Explanation

p←?3                       ⍝ p(rize) is a random number between 1 and 3
⎕←d←3↑⎕A                   ⍝ d(oors) is the string 'ABC'; output it
c←d⍳⍞                      ⍝ ask for one of the letters; c(hoice) is its position
o←e[?⍴e←(⍳3)~p,c]          ⍝ o(pen) is a random position except for p and c
d[o]←'_'                   ⍝ replace the o position in the d string with a '_'
⎕←d                        ⍝ output the modified d string
w←(c=p)=5=⍴⍞               ⍝ get choice, if it's stick (5 chars) and c=p, or neither, (w)in 
⎕←'You','lost' 'won!'[w]   ⍝ print the result

Examples

      p←?3⋄d[e[?⍴e←(⍳3)~p,c←⍞⍳⍨⎕←d←3↑⎕A]]←'_'⋄⎕←d⋄⎕←'You','lost' 'won!'[(c=p)=5=⍴⍞]
ABC
A
AB_
stick
You lost 
      p←?3⋄d[e[?⍴e←(⍳3)~p,c←⍞⍳⍨⎕←d←3↑⎕A]]←'_'⋄⎕←d⋄⎕←'You','lost' 'won!'[(c=p)=5=⍴⍞]
ABC
A
AB_
stick
You won! 
\$\endgroup\$
  • \$\begingroup\$ Lovely! But I think there's a in the source which mutates into a = in the explanation. \$\endgroup\$ – TRiG Feb 17 '14 at 22:16
  • \$\begingroup\$ Thanks, that was a typo, the last bug I fixed before posting. \$\endgroup\$ – Tobia Feb 17 '14 at 22:35
2
\$\begingroup\$

Python, 157

from random import*
C=choice
I=raw_input
p='\n> '
a='ABC'
g=C(a)
i=I(a+p)
print'You '+'lwoosnt!'[(i==g)^('w'in I(a.replace(C(list(set(a)-{g,i})),'_')+p))::2]

Example:

$ python monty.py
ABC
> A
AB_
> switch
You won!
\$\endgroup\$
2
\$\begingroup\$

PowerShell: 192 174

Changes from original:

  • -8 Characters Since the visual display of doors can be "whatever" I realized that I could save some characters (particularly, the apostrophes required to define strings) by using numbers instead of letters.
  • -8 Characters By specifically choosing single-digit, prime numbers to represent the doors I could use the shorter modulo operator instead of an actual comparison operator when I needed to match doors to figure out the host's possible choices or the player's door swap. (Briefly explained here.)
  • -2 Characters Swapping the win/loss responses in the final if/else statement allowed me to use the modulo trick there also.

Golfed Code

$w=($d=3,5,7)|random;357;$p=read-host;-join$d-replace($h=$d|?{$_%$w-and$_%$p}|random),0;if((read-host)-match'w'){$p=$d|?{$_%$p-and$_%$h}}if($p%$w){'You lost'}else{'You won!'}

Un-Golfed Code With Comments

# Set up an array of doors ($d), and choose one to be the winner ($w).
$w=($d=3,5,7)|random;

# Show doors.
357;

# Get input and save player's choice ($p).
$p=read-host;

# Join the doors into one string, replacing the host's choice ($h) with a zero, and display them again.
-join$d-replace
(
    # Host will randomly choose a door from those which are not evenly divisible by $w or $p.
    $h=$d|?{$_%$w-and$_%$p}|random
 ),0;

# Get input from player. If it contains a 'w', switch doors.
# While this is generally a sloppy way to distinguish 'switch' from 'stick', it is allowed by the rules.
# "If the user enters anything other than stick or switch, the implementation is undefined. Do whatever you want."
if((read-host)-match'w')
{
    # Player will switch doors to one which is not evenly divisible by the $h or the original $p.
    $p=$d|?{$_%$p-and$_%$h}
}

# Announce the result.
# If $p is not evenly divisible by $w, player has lost. Otherwise, they have won.
if($p%$w){'You lost'}else{'You won!'}

# Variables cleanup - not included in golfed code.
rv w,d,p,h
\$\endgroup\$
  • \$\begingroup\$ I like the if it contains a 'w' trick. \$\endgroup\$ – TRiG Feb 25 '14 at 0:28
  • \$\begingroup\$ Incidentally, I originally said that if the input was anything other than "stick" or "switch", the program should terminate, but I changed my mind before posting. \$\endgroup\$ – TRiG Feb 25 '14 at 0:29
  • \$\begingroup\$ @TRiG Thanks for that. While it wouldn't have been hard to implement, it would have added a bit of bloat. \$\endgroup\$ – Iszi Feb 25 '14 at 3:10
  • \$\begingroup\$ And the various tricks (your w detection, or counting characters) are more fun, anyway. \$\endgroup\$ – TRiG Feb 25 '14 at 3:12
0
\$\begingroup\$

Javascript, 221 197

(function(q,r,s,t,u,v){f='ABC';d=[0,1,2];b=q()%3;a=r(f);d.splice(a,1);(a==b)?(r(f[d[q()%2]])==t)?s(u):s(v):(r(f[d[(d[0]==b)+0]])!=t)?s(u):s(v)})(Date.now,prompt,alert,'stick','You won!','You lost')

It uses two calls to Date.now() for randomness with a prompt in between to guarantee a delay. The user input is a 0-based index (the rule did say "whatever"). The following alert says which door was opened. Here's a slightly longer version that gives the answer before the user picks, to verify that it doesn't cheat:

(function(q,r,s,t,u,v){f='ABC';d=[0,1,2];b=q()%3;s('ans:'+b);a=r(f);d.splice(a,1);(a==b)?(r(f[d[q()%2]])==t)?s(u):s(v):(r(f[d[(d[0]==b)+0]])!=t)?s(u):s(v)})(Date.now,prompt,alert,'stick','You won!','You lost')

Fiddle: http://jsfiddle.net/acbabis/9J2kP/

EDIT: Thanks dave

\$\endgroup\$
  • \$\begingroup\$ You could shorten it to 197: (function(q,r,s,t,u,v){f='ABC';d=[0,1,2];b=q%3;a=r(f);d.splice(a,1);(a==b)?((r(f[d[q%2]])==t)?s(u):s(v)):(r(f[d[(d[0]==b)+0]])!=t)?s(u):s(v)})(Date.now(),prompt,alert,'stick','You won!','You lost') \$\endgroup\$ – dave Feb 17 '14 at 21:38
  • \$\begingroup\$ @dave That's helpful. I didn't think to use the ternary operator here. I can't pass Date.now(), though, because the random numbers need to be independent. I can, however, pass Date.now. \$\endgroup\$ – acbabis Feb 17 '14 at 21:44
  • \$\begingroup\$ @acbabis "I can't pass Date.now() ... I can, however, pass Date.now" ??? \$\endgroup\$ – Timtech Feb 17 '14 at 21:45
  • \$\begingroup\$ @Timtech date.now passes the function, date.now() passes the result of the function \$\endgroup\$ – dave Feb 17 '14 at 21:46
  • \$\begingroup\$ @dave Oh, I get it. Thanks :) \$\endgroup\$ – Timtech Feb 17 '14 at 21:48
0
\$\begingroup\$

PHP >= 5.4, 195 192

$r=[0,1,2];unset($r[$p=rand(0,2)]);$d='012';echo"$d\n";fscanf(STDIN,"%d",$c);unset($r[$c]);$d[array_rand($r)]='_';echo"$d\n",!fscanf(STDIN,"%s",$s),'You '.($s=='switch'^$c==$p?'won!':'lost.');

Output:

012
1
01_
stick
You won!
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.