RosettaCode Monty Hall: Difference between revisions

From EiffelStudio: an EiffelSoftware project
Jump to navigation Jump to search
mNo edit summary
Marco2357 (talk | contribs)
No edit summary
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Rosetta Code]]
[[Category:Rosetta Code]]
[[Category:Flash Code ]]
[[Category:Flash Code ]]
'''-> [[RosettaCode]] Overview'''


==Reference==
==Reference==
Line 8: Line 10:
==Eiffel code==
==Eiffel code==


Here's an initial implementation, just to get things started. I just typed this straight into the wiki, so it might not even compile.
Here's a candidate implementation. This compiles and runs, producing output similar to this:
 
Staying wins 333504 times.


Please feel free to edit this in place, I won't be offended.
Switching wins 666496 times.


<e>
<e>
class MONTY_HALL
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
feature -- Commands


play
play
local
local
games: INTEGER
random: RANDOM
doors: ARRAYED_LIST [BOOLEAN]
doors: ARRAYED_LIST [BOOLEAN]
chosen, shown: INTEGER
chosen, shown: INTEGER
stayWins: INTEGER
do
do
games := 1000000
create doors.make_filled (Door_count) -- False is a goat, True is a car
create random.make
doors [next_random_door] := True -- Put a car behind a random door
chosen := next_random_door -- Pick a door, any door


across 1 |..| games as plays loop
-- Monty selects a door which is neither the winner nor the choice
create doors.make_filled (3) -- False is a goat, True is a car
from
random.forth
shown := next_random_door
doors [random.item \\ 3 + 1] := True -- Put a car behind a random door
until
shown /= chosen and not doors [shown]
random.forth
loop
chosen := random.item \\ 3 + 1 -- Pick a door, any door
shown := next_random_door
end
from shown := chosen until shown /= chosen and not doors [shown] loop
random.forth
shown := random.item \\ 3 + 1
end


if doors [chosen] then -- If you would have won by staying, count it
if doors [chosen] then -- If you would have won by staying, count it
stay_wins := stay_wins + 1
staying_wins := staying_wins + 1
end
end
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.


out ("Staying wins " + stay_wins + " times.%N")
next_random_door: INTEGER
out ("Switching wins " + games - stay_wins + " times.%N")
-- 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



Latest revision as of 08:27, 3 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?