Answer to “The Goats and the Corvette”
(b) It’s always better to switch. Yes, really. The explanation is below, followed by a simulation that demonstrates it.
Explanation
If you don’t switch, you have a 1 in 3 chance of winning the Corvette; if you do switch, you have a 2 in 3 chance.
Remember, there is an important hint in the formulation of the problem. The game show host is never going to open the door containing the car. He’s always going to show you a goat, eliminating one of the bad choices. Does that help?
”But,” you may say, “you might have picked right the first time.” Right. I think this kind of objection reveals the way our brains work; we feel like the “switcher” is throwing away a bird in the hand, that is, we assume that the first choice was a good one. But it is actually likely to be a bad one. 2/3 of the time, you’ll have picked a goat as your first choice. And now figure this: if you have made a bad first choice, your second choice is a guaranteed win. You’ll be sitting on a goat, and the game show host will reveal the other one. The only door left is the car!
The only way for the switcher to lose is to have made a good first choice, something that happens only 1/3 of the time.
If you think this is a bunch of hand-waving, try the simulation below.
Simulation
This is a program written in Unicon (formerly Icon), a programming language created by Dr. Ralph Griswold at the University of Arizona. If you don’t want to download Unicon and try it on your own computer, I think the code and the language are readable enough that you can transliterate it into your favorite language, using the guide at the end.
Here’s some sample output, from a couple of runs.
How many iterations? 100 Switcher: 78 cars; Stayer: 22 cars How many iterations? 1000 Switcher: 694 cars; Stayer: 306 cars How many iterations? 10000 Switcher: 6717 cars; Stayer: 3283 cars
The entire program:
# let’s make a deal global NDoors procedure none_the_same (n1, n2, n3) return n1 ~= n3 & n2 ~= n3 end procedure main () NDoors := 3 writes(”How many iterations? “) iterations := numeric(read()) switcher := stayer := 0 every i := 1 to iterations do { car := ?NDoors # Where the car is choice1 := ?NDoors # player’s first choice until dealers_choice := none_the_same(car, choice1, ?NDoors) choice2 := none_the_same(choice1, dealers_choice, 1 to NDoors) # OK! Who won? if car = choice1 then stayer +:= 1 else if car = choice2 then switcher +:= 1 } write(”Switcher: “, switcher, “ cars; Stayer: “, stayer, “ cars”) end
Guide to Icon
If Unicon is unfamiliar, here is a quick glossary:
?x
where x is an integer means “a random number between 1 and x inclusive”.~=
means “not numerically equal”.=
means “numerically equal”.:=
means assignment.
Programmers in other languages may be confused by the line
choice2 := none_the_same(choice1, dealers_choice, 1 to NDoors)
as it contains a loop construct within a function call. What it means is “try 1 through NDoors as arguments to ‘none_the_same’ until one of them succeeds”. An equivalent way to write it would be
every i := 1 to NDoors do { if none_the_same(choice1, dealers_choice, i) then { choice2 := none_the_same(choice1, dealers_choice, i) break } }
The first way is known as “goal-directed evaluation” and is one of the features of Icon that make it so expressive.
The body of the none_the_same
function may also be confusing.
It appears to be returning a boolean, but it isn’t; it’s returning
n3
if it succeeds. Icon has a concept of “failure”
whose closest analogue in C++ or Java would be an exception.
Think of the ~=
(numerically not equal) operator as throwing an
exception if its operands are equal but returning its right-hand
operand if they are not. In other words, in Java, it might
look like
int none_the_same (int n1, int n2, int n3) throws equal_after_all { if (n1 != n2 && n2 != n3) return n3; else throw equal_after_all; }
What makes failure nicer than exceptions in a program like this is how
you can put it to work for you, as is done with the expression 1 to NDoors
as an argument to the
function. As long as
the expression fails, any generators within it continue “trying”
values.