>From http://en.wikipedia.org/wiki/Monty_Hall_problem we have this description of the Monty Hall Problem:
> Suppose you're on a game show and you're given the choice of three > doors [and will win what is behind the chosen door]. Behind one > door is a car; behind the others, goats [unwanted booby prizes]. > The car and the goats were placed randomly behind the doors before > the show. The rules of the game show are as follows: After you have > chosen a door, the door remains closed for the time being. The game > show host, Monty Hall, who knows what is behind the doors, now has > to open one of the two remaining doors, and the door he opens must > have a goat behind it. If both remaining doors have goats behind > them, he chooses one [uniformly] at random. After Monty Hall opens > a door with a goat, he will ask you to decide whether you want to > stay with your first choice or to switch to the last remaining > door. Imagine that you chose Door 1 and the host opens Door 3, > which has a goat. He then asks you "Do you want to switch to Door > Number 2?" Is it to your advantage to change your choice? This Clojure code simulates the Monty Hall problem in an interesting way: the monty-hall function is passed a contestant function that, when invoked, a) picks a door at random and b) also returns a function that re-decides which door to open after Monty opens one of the other two and gives them the chance to switch (monty-hall does this by calling that function with the number of the door Monty opened). Two contestant functions are provided. Both make a uniformly random initial choice of door. The staying-contestant returns a function that will make the same choice of door after Monty opens one of the other two. The switching-contestant will switch to the other unopened door. The monty-avg function takes a contestant and a number of trials, has that contestant play that many games, and returns the proportion of times that contestant won. Example output for 10,000 trials is included; some people may find the results counterintuitive, but the math says that the results I got are exactly what they should be (and that 1000 PhDs were wrong about that). The code is idiomatic Clojure, using sequence functions in preference to loop/recur and itself using higher order functions in what might be described as a continuation-passing style. There is also no mutation or impure function use except for the calls to rand-int and that rng's hidden internal state; it could be made fully pure by passing around an extra parameter in the form of a seq of random bits supplied externally and, from functions that consume from the seq, returning the reduced seq. (defn rand-elt [seq] (nth seq (rand-int (count seq)))) (defn make-monty [] (rand-elt [[:car :goat :goat] [:goat :car :goat] [:goat :goat :car]])) (defn monty-hall [contestant] (let [m (make-monty) [door response-fn] (contestant) other-bad-doors (remove #(= (m %) :car) (remove #(= % door) [0 1 2])) wrong-door (rand-elt other-bad-doors) final-door (response-fn wrong-door)] (m final-door))) (defn staying-contestant [] (let [initial-door (rand-int 3)] [initial-door (constantly initial-door)])) (defn switching-contestant [] (let [initial-door (rand-int 3)] [initial-door (fn [wrong-door] (first (remove #(= % initial-door) (remove #(= % wrong-door) [0 1 2]))))])) (defn monty-avg [contestant n-trials] (double (/ (count (filter #(= :car %) (repeatedly n-trials #(monty-hall contestant)))) n-trials))) user=> (monty-avg staying-contestant 10000) 0.3362 user=> (monty-avg switching-contestant 10000) 0.6616 -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en