Sunday, August 28, 2005

The Monty Hall problem and LISP

I recently stumbled upon the Monty Hall problem at Wikipedia. I've seen this problem before, and have always used good old bayes theorem to solve it. Since, I was hacking at some boring regular expressions and needed to take a break, and also Wikisource site has C/C++/Java and Perl simulations but none in LISP, so I decided to try my hand at it.

Since, I am not some 'uber-lisp-hacker' this is not the most efficient code one can write and if some uber lisp hacker finds this , maybe he can improve it.

Anyway here is the code..




;; Monty Hall.LISP
;; Simulation for the Monty Hall problem as in Wikipedia..

(let ((host 0) (stick-wins 0) (switch-wins 0) (total-trials 3000))
  (dotimes (i total-trials)
    ; chose random postions for car and goat, choices for contestant

    (let* ((car (random 3))
      (goat1 (cond ((= car 0) 1) ((= car 1) 2) ((= car 2) 0)))
      (goat2 (cond ((= goat1 0) 1) ((= goat1 1) 2) ((= goat1 2) 0)))
      (sticker (random 3))
      (switcher sticker))

    ; select the door that the host opens and
    ; the door the switcher switches too..
    (setf host (cond ((= sticker goat1) goat2) (t goat1)))
    (setf switcher (cond ((= host goat2) car)
          (t (cond ((= switcher car) goat2)
             ((= switcher goat2) car)))))
    (if (= sticker car) (incf stick-wins))
    (if (= switcher car) (incf switch-wins))

    (format t "Car:~D, Goat 1:~D, Goat 2:~D, Sticker:~D, Switcher:~D~%"
      car goat1 goat2 sticker switcher)))

   (format t "Total Trials : ~D, Sticker Wins ~D times(~D %),
     Switcher Wins ~D times (~D %)~%"
   total-trials
   stick-wins
   (* (/ stick-wins total-trials) 100.00)
   switch-wins
   (* (/ switch-wins total-trials) 100.00)))



Signing Off,
Vishnu Vyas

1 comment:

Anonymous said...

I was not allowed to use the PRE-tag in html, so indentation is screwed.

;;;
;;; The Monty Hall Problem (a bit reduced)
;;;

(defun percentage (part total)
(float (* (/ part total) 100)))

(defun measure-winning-rate (times)
(let ((win-first 0)
(win-second 0))
(loop repeat times do
;; If the first choice is a car, first choice wins.
;; If not, the second choice would have won this round,
;; because it MUST be the car then.
(if (eql (nth (random 3) '(:goat :goat :car)) :car)
(incf win-first)
(incf win-second)))
(list (list 'first-choice :absolute win-first :percentage (percentage win-first times))
(list 'second-choice :absolute win-second :percentage (percentage win-second times)))))