【问题标题】:First larger (common) lisp program -> 'random' not working as expected第一个更大(常见)的 lisp 程序 -> 'random' 没有按预期工作
【发布时间】:2012-05-23 17:46:37
【问题描述】:

只是为了好玩,我用 Python 写了一个 "monty hall problem" 的模拟。后来我用 Lua 进行了实验,并决定在 Lua 中再次编写它,看看对比起来会是什么样子。尽管程序看起来非常相似(Lua 版本略短),但这是一次非常有趣的体验。最近我开始用 CL 做实验,并想再次做同样的事情。但是,当我运行它时,它的行为并不像预期的那样。由于某种原因,不稳定的玩家(应该有 66% 的获胜机会)与天真的玩家(有 50% 的获胜机会)几乎相同。

有人可以给我提示一下出了什么问题吗?这不是作业或类似的东西,只是我第一次尝试用 CL 编写一个更大的程序。除了关于上述问题的提示外,我还欢迎有关如何改进我的风格的建议。我猜它仍然是 Python 风格的(或多或少是直接翻译)。

(defun choose-one (l)
  "Ramdomly chooses one element of the given list"
  (nth (random (length l)) l))

(defun remove-one (l)
  "Randomly removes one element of the given list"
  (remove (choose-one l) l))

(defun naive-player (initial-choice possible-choices)
  "The naive player randomly picks one choice. Should have a 50% chance to win."
  initial-choice ;keep compiler happy
  (choose-one possible-choices))

(defun stubborn-player (initial-choice possible-choices)
  "The stubborn player sticks with his initial choice. Should have a 33% chance to win."
  possible-choices ;keep compiler happy
  initial-choice)

(defun erratic-player (initial-choice possible-choices)
  "The erratic player will always change his choice. Should have a 66% chance to win."
  (choose-one (remove initial-choice possible-choices)))

(defun host-offer (prize possible-choices)
  "The host reveals one wrong choice."
  (let ((remaining (remove prize possible-choices)))
    (remove (choose-one remaining) possible-choices)))

(defun one-game (playerfn choices)
  "Simulates a single game with the given player. Evaluates to T if the player won."
  (let ((prize (choose-one choices))
        (player-choice (choose-one choices)))
    (eq (funcall playerfn player-choice (host-offer prize choices)) prize)))


(defun multiple-games (num-games)
  "Simulates the given number of games with all players. Evaluates to a result list."
  (let ((choices '(door_a door_b door_c))
        (naive-score 0)
        (stubborn-score 0)
        (erratic-score 0))
    ;(progn
      (dotimes (i num-games)
        ;(progn
          (if (one-game #'naive-player choices)
              (incf naive-score))
          (if (one-game #'stubborn-player choices)
              (incf stubborn-score)) 
          (if (one-game #'erratic-player choices)
              (incf erratic-score)));)
      (list 
       (list 'naive-player naive-score) 
       (list 'stubborn-player stubborn-score)
       (list 'erratic-player erratic-score))));)

;; Run simulation and display results
(defparameter *num-games* 10000)
(format *standard-output* "--- Monty Hall ---~%")
(format *standard-output* "Simulating ~D games...~%" *num-games*)
(let ((result (multiple-games *num-games*)))
  (format *standard-output* "~{~{~A score: ~D~}~%~}" result))

输出(例如):

--- Monty Hall ---
Simulating 10000 games...
NAIVE-PLAYER score: 5014
STUBBORN-PLAYER score: 3333
ERRATIC-PLAYER score: 4968

【问题讨论】:

  • 为什么不稳定的玩家应该做得更好?这些百分比不应该反过来吗?
  • 首先我不知道 erratic 这个名字是否真的是一个不错的选择。英语不是我的第一语言。不稳定的玩家总是会改变他的选择。在这样的游戏中,当您改变选择时获胜的机会会更大(参见维基百科文章)。在 python 和 lua 模拟中,我也在模拟结果中看到了这一点,但在 lisp 版本中没有:(
  • 我明白你的意思了。在英语中,“不稳定”更像是“不可预测”,所以我假设你的意思是不稳定的玩家做出了随机选择。
  • 好的,谢谢您的提示。在这个程序中,“不稳定”的玩家是可以预测的(他总是会切换),而天真的玩家实际上是随机选择的。对困惑感到抱歉!我称他为天真,因为在思考这个问题时,最初的想法往往是“不管你做什么,机会都是一样的”。

标签: lisp common-lisp clisp sbcl


【解决方案1】:

主机报价功能错误。在定义的蒙蒂霍尔问题中,主机永远不会打开玩家选择的门,但您的程序没有考虑到这一点。如果解决了这个问题,程序会返回预期的结果。

【讨论】:

  • 你是对的!当我搜索错误时,我完全错过了这一点,并专注于程序的其余部分......我在 Python 和 Lua 版本中也没有该功能(但当然我也在那里删除了玩家选择)。 CL 版本有更多更小的函数,因为我感觉 CL 中的很多嵌套很快(对我来说)变得不可读。修复后的输出:--- Monty Hall --- 模拟 10000 场比赛...... NAIVE-PLAYER 得分:4924 STUBBORN-PLAYER 得分:3325 ERRATIC-PLAYER 得分:6684
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多