Монти Холл и ленивые последовательности (?) - PullRequest
0 голосов
/ 04 марта 2019

Я только начинаю изучать Clojure и пытаюсь смоделировать проблему Монти Холла :

(defn create-contest
  "Creates a monty hall doors contest"
  [n]
  (do (def door-with-car (rand-int n))
      (map
       (fn [i] (if (= i door-with-car) :car :closed))
       (range n)))) 

(defn create-doors
  "Create a collection of monty hall contests"
  [doors contests]
  (doall
   (map
     (fn [i] (create-contest i))
     (repeat contests doors))))

Но каждый раз, когда я выполняю функцию create-doors, вседвери с автомобилями оказываются в одном и том же положении:

broker.core> (create-doors 4 10)
((:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed)
 (:car :closed :closed :closed))
broker.core> (create-doors 4 10)
((:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed))
broker.core> (create-doors 4 10)
((:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed))

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

Исходя из решения @ TaylorWood , вы можете выразить обе свои функции более кратко, хотя я не уверен, что краткие версии так же ясны.

Ваша функция create-contest map проверяет каждое число i, чтобы определить, является ли оно единицей .Лучше просто поменяйте на напрямую.Для этого нам нужен вектор, который, я думаю, вы все равно захотите найти при моделировании игры:

 (defn create-contest [n]
  (assoc (vec (repeat n :closed)) (rand-int n) :car))

Ваша функция create-doors многократно передает один и тот же аргумент своему map 'с функцией.Вы можете использовать repeatedly на закрытии, чтобы получить тот же эффект:

(defn create-doors [doors contests]
  (repeatedly contests (partial create-contest doors)))

или

(defn create-doors [doors contests]
  (repeatedly contests #(create-contest doors)))
0 голосов
/ 04 марта 2019

Вы очень близки, вы должны просто использовать форму let вместо def здесь:

(defn create-contest
  "Creates a monty hall doors contest"
  [n]
  (let [door-with-car (rand-int n)] ;; let instead of def
    (map
      (fn [i] (if (= i door-with-car) :car :closed))
      (range n))))

def свяжет некоторое значение с переменной в текущем пространстве имен, ноВы хотите связать значение в области действия этой функции, и для этого подходит let.См. этот Q & A для другого объяснения.

(defn create-doors
  "Create a collection of monty hall contests"
  [doors contests]
  (map
    create-contest ;; no need to wrap create-contest in another function here
    (repeat contests doors)))

Вам не нужно заключать create-contest в другую функцию для использования с map - вы можете просто передать функцию непосредственноmap как значение.doall необходим только для принудительной реализации отложенной последовательности из map, поэтому вам, вероятно, не нужно / не нужно этого внутри create-doors.

(create-doors 4 10)
=>
((:closed :closed :car :closed)
 (:closed :closed :closed :car)
 (:closed :car :closed :closed)
 (:closed :closed :closed :car)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :car :closed :closed)
 (:closed :closed :closed :car)
 (:closed :closed :car :closed)
 (:closed :closed :car :closed))
...