about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorJonas Hietala <tradet.h@gmail.com>2014-07-28 13:40:51 +0200
committerJonas Hietala <tradet.h@gmail.com>2014-07-28 13:57:30 +0200
commitbf1ba83292e767365be925c132027c67ec40fe68 (patch)
treea59567985c1120930e7c89add0fdc0b57587e04b /src/libstd
parentd114ddac030d6ed63b3076ccc0e7db081c0a9409 (diff)
downloadrust-bf1ba83292e767365be925c132027c67ec40fe68.tar.gz
rust-bf1ba83292e767365be925c132027c67ec40fe68.zip
doc: Monty Hall simulation for std::rand
A larger example for std::rand
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rand/mod.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index a9b9a907a26..273b1d7f343 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -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]