# Difference between revisions of "RosettaCode Monty Hall"

Peter gummer (Talk | contribs) m |
Peter gummer (Talk | contribs) (Monty Hall implementation that compiles and runs) |
||

Line 8: | Line 8: | ||

==Eiffel code== | ==Eiffel code== | ||

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

− | + | Staying wins 333504 times. | |

+ | Switching wins 666496 times. | ||

<e> | <e> | ||

− | class MONTY_HALL | + | class |

+ | MONTY_HALL | ||

− | feature | + | 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 | play | ||

local | local | ||

− | |||

− | |||

doors: ARRAYED_LIST [BOOLEAN] | doors: ARRAYED_LIST [BOOLEAN] | ||

chosen, shown: INTEGER | chosen, shown: INTEGER | ||

− | |||

do | 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 | 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 | ||

## Revision as of 17:38, 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?