Difference between revisions of "RosettaCode Monty Hall"

(Monty Hall implementation that compiles and runs)
m (Eiffel code)
Line 11: Line 11:
  
 
Staying wins 333504 times.
 
Staying wins 333504 times.
 +
 
Switching wins 666496 times.
 
Switching wins 666496 times.
  

Revision as of 18:40, 11 August 2012


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?