Skip to content

Commit

Permalink
doc: Monty Hall simulation for std::rand
Browse files Browse the repository at this point in the history
A larger example for std::rand
  • Loading branch information
treeman committed Jul 28, 2014
1 parent d114dda commit bf1ba83
Showing 1 changed file with 103 additions and 0 deletions.
103 changes: 103 additions & 0 deletions src/libstd/rand/mod.rs
Expand Up @@ -71,6 +71,109 @@ use std::rand;
let tuple = rand::random::<(f64, char)>();
println!("{}", tuple)
```
This is a simulation of the [Monty Hall Problem][]:
> Suppose you're on a game show, and you're given the choice of three doors:
> Behind one door is a car; behind the others, goats. You pick a door, say No. 1,
> and the host, who knows what's behind the doors, opens another door, say No. 3,
> which has a goat. He then says to you, "Do you want to pick door No. 2?"
> Is it to your advantage to switch your choice?
The rather unintuitive answer is that you will have a 2/3 chance of winning if
you switch and a 1/3 chance of winning of you don't, so it's better to switch.
This program will simulate the game show and with large enough simulation steps
it will indeed confirm that it is better to switch.
[Monty Hall Problem]: http://en.wikipedia.org/wiki/Monty_Hall_problem
```
use std::rand;
use std::rand::Rng;
use std::rand::distributions::{IndependentSample, Range};
struct SimulationResult {
win: bool,
switch: bool
}
// Run a single simulation of the Monty Hall problem.
fn simulate<R: Rng>(rng: &mut R) -> SimulationResult {
let random_door = Range::new(0u, 3);
let car = random_door.ind_sample(rng);
// This is our initial choice
let mut choice = random_door.ind_sample(rng);
// The game host opens a door
let open = game_host_open(car, choice, rng);
// Shall we switch?
let switch = rng.gen();
if switch {
choice = switch_door(choice, open);
}
SimulationResult { win: choice == car, switch: switch }
}
// Returns the door the game host opens given our choice and knowledge of
// where the car is. The game host will never open the door with the car.
fn game_host_open<R: Rng>(car: uint, choice: uint, rng: &mut R) -> uint {
let choices = free_doors(vec![car, choice]);
rand::sample(rng, choices.move_iter(), 1)[0]
}
// Returns the door we switch to, given our current choice and
// the open door. There will only be one valid door.
fn switch_door(choice: uint, open: uint) -> uint {
free_doors(vec![choice, open])[0]
}
fn free_doors(blocked: Vec<uint>) -> Vec<uint> {
range(0u, 3).filter(|x| !blocked.contains(x)).collect()
}
fn main() {
// The estimation will be more accuraty with more simulations
let num_simulations = 10000u;
let mut rng = rand::task_rng();
let (mut switch_wins, mut switch_losses) = (0u, 0u);
let (mut keep_wins, mut keep_losses) = (0u, 0u);
println!("Running {} simulations...", num_simulations);
for _ in range(0, num_simulations) {
let result = simulate(&mut rng);
match (result.win, result.switch) {
(true, true) => switch_wins += 1,
(true, false) => keep_wins += 1,
(false, true) => switch_losses += 1,
(false, false) => keep_losses += 1,
}
}
let total_switches = switch_wins + switch_losses;
let total_keeps = keep_wins + keep_losses;
println!("Switched door {} times with {} wins and {} losses",
total_switches, switch_wins, switch_losses);
println!("Kept our choice {} times with {} wins and {} losses",
total_keeps, keep_wins, keep_losses);
// With a large number of simulations, the values should converge to
// 0.667 and 0.333 respectively.
println!("Estimated chance to win if we switch: {}",
switch_wins as f32 / total_switches as f32);
println!("Estimated chance to win if we don't: {}",
keep_wins as f32 / total_keeps as f32);
}
```
*/

#![experimental]
Expand Down

0 comments on commit bf1ba83

Please sign in to comment.