Difference between revisions of "RosettaCode Monty Hall"

 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
[[Category:Rosetta Code]]
 
[[Category:Rosetta Code]]
 
[[Category:Flash Code ]]
 
[[Category:Flash Code ]]
 +
 +
'''-> [[RosettaCode]] Overview'''
  
 
==Reference==
 
==Reference==
 
Statement of the Monty Hall problem on RosettaCode: [http://rosettacode.org/wiki/Monty_Hall_problem here].
 
Statement of the Monty Hall problem on RosettaCode: [http://rosettacode.org/wiki/Monty_Hall_problem here].
<p>Deadline for adding to RosettaCode page: 31 Aug 2012; submitter:
+
<br>Deadline for adding to RosettaCode page: 31 Aug 2012; submitter:
  
 
==Eiffel code==
 
==Eiffel code==
 +
 +
Here's a candidate implementation. This compiles and runs, producing output similar to this:
 +
 +
Staying wins 333504 times.
 +
 +
Switching wins 666496 times.
 +
 +
<e>
 +
class
 +
MONTY_HALL
 +
 +
create
 +
make
 +
 +
feature {NONE} -- Initialization
 +
 +
make
 +
local
 +
games_count: INTEGER
 +
do
 +
create random_generator.make
 +
games_count := 1000000
 +
 +
across 1 |..| games_count as game loop
 +
play
 +
end
 +
 +
print ("Staying wins " + staying_wins.out + " times.%N")
 +
print ("Switching wins " + (games_count - staying_wins).out + " times.%N")
 +
end
 +
 +
feature -- Commands
 +
 +
play
 +
local
 +
doors: ARRAYED_LIST [BOOLEAN]
 +
chosen, shown: INTEGER
 +
do
 +
create doors.make_filled (Door_count) -- False is a goat, True is a car
 +
doors [next_random_door] := True -- Put a car behind a random door
 +
chosen := next_random_door -- Pick a door, any door
 +
 +
-- Monty selects a door which is neither the winner nor the choice
 +
from
 +
shown := next_random_door
 +
until
 +
shown /= chosen and not doors [shown]
 +
loop
 +
shown := next_random_door
 +
end
 +
 +
if doors [chosen] then -- If you would have won by staying, count it
 +
staying_wins := staying_wins + 1
 +
end
 +
ensure
 +
staying_wins_valid: staying_wins = old staying_wins or staying_wins = old staying_wins + 1
 +
end
 +
 +
feature {NONE} -- Implementation
 +
 +
Door_count: INTEGER = 3
 +
-- The total number of doors.
 +
 +
staying_wins: INTEGER
 +
-- The number of times that the strategy of staying would win.
 +
 +
random_generator: RANDOM
 +
-- A random number generator for selecting doors.
 +
 +
next_random_door: INTEGER
 +
-- A door chosen at random.
 +
do
 +
random_generator.forth
 +
Result := random_generator.item \\ Door_count + 1
 +
ensure
 +
valid_door: Result >= 1 and Result <= Door_count
 +
end
 +
 +
end
 +
 +
</e>
  
 
==Comments==
 
==Comments==
 +
 +
Note that the implementations in many other languages maintain a separate variable to count the number of switch wins. They calculate whether switching wins at each step via some funky logic that relies on zero-based array indexing, which would be inconvenient in Eiffel. But we don't need to do that at all anyway, because calculating it at each step is completely redundant: we can just do a final subtraction at the end, right?

Latest revision as of 23:27, 2 October 2012


-> RosettaCode Overview

Reference

Statement of the Monty Hall problem on RosettaCode: here.
Deadline for adding to RosettaCode page: 31 Aug 2012; submitter:

Eiffel code

Here's a candidate implementation. This compiles and runs, producing output similar to this:

Staying wins 333504 times.

Switching wins 666496 times.

class
	MONTY_HALL
 
create
	make
 
feature {NONE} -- Initialization
 
	make
		local
			games_count: INTEGER
		do
			create random_generator.make
			games_count := 1000000
 
			across 1 |..| games_count as game loop
				play
			end
 
			print ("Staying wins " + staying_wins.out + " times.%N")
			print ("Switching wins " + (games_count - staying_wins).out + " times.%N")
		end
 
feature -- Commands
 
	play
		local
			doors: ARRAYED_LIST [BOOLEAN]
			chosen, shown: INTEGER
		do
			create doors.make_filled (Door_count)	-- False is a goat, True is a car
			doors [next_random_door] := True	-- Put a car behind a random door
 			chosen := next_random_door	-- Pick a door, any door
 
			-- Monty selects a door which is neither the winner nor the choice
			from
				shown := next_random_door
			until
				shown /= chosen and not doors [shown]
			loop
				shown := next_random_door
			end
 
			if doors [chosen] then	-- If you would have won by staying, count it
				staying_wins := staying_wins + 1
			end
		ensure
			staying_wins_valid: staying_wins = old staying_wins or staying_wins = old staying_wins + 1
		end
 
feature {NONE} -- Implementation
 
	Door_count: INTEGER = 3
			-- The total number of doors.
 
	staying_wins: INTEGER
			-- The number of times that the strategy of staying would win.
 
	random_generator: RANDOM
			-- A random number generator for selecting doors.
 
	next_random_door: INTEGER
			-- A door chosen at random.
		do
			random_generator.forth
			Result := random_generator.item \\ Door_count + 1
		ensure
			valid_door: Result >= 1 and Result <= Door_count
		end
 
end

Comments

Note that the implementations in many other languages maintain a separate variable to count the number of switch wins. They calculate whether switching wins at each step via some funky logic that relies on zero-based array indexing, which would be inconvenient in Eiffel. But we don't need to do that at all anyway, because calculating it at each step is completely redundant: we can just do a final subtraction at the end, right?