Ex3.5 20の質問

データ構造をプログラムから書き換える問題。
推論に失敗する度に、ツリーが拡張されていく。

;;; Exercise 3.5 [h] (Exercise in a altering structure.) Write a
;;; program that will play the role of the guesser in the game Twenty
;;; Questions. The user of the program will have in mind any type of
;;; thing. The program will ask questions of the user, which must be
;;; answered yes or no, or "it" when the program has guessed it. if
;;; the program runs out of guesses, it gives up and ask the user what
;;; "it" was. At first the program will not play well, but each time
;;; it plays, it will remember the user's replies and use them for
;;; subsequent guesses.
(defclass :guess-question ()
  ((class :initarg :class)
   (yes   :initarg :yes :initform 'nil :accessor yes)
   (no    :initarg :no  :initform 'nil :accessor no))
  (:documentation "推測のための質問。classはこの質問で特定するクラス。
yesは'yes'と答えた時に辿る次の質問。
noは'no'と答えた時に辿る次の質問。"))

(defvar *guesser-tree* (make-instance :guess-question :class "動物")
  "推測の為の質問木")

(defun get-next-question ()
  (format t "ギブアップ!「それ」はなんですか?: ")
  (make-instance :guess-question :class (read-line)))

(defun guesser (&optional (question *guesser-tree*) &aux answer)
  "質問に答えてもらい、ユーザが思っているモノを当てる。
分からなかった場合には、質問木を拡張してもらう。"
  (with-slots (class yes no) question
    (format t "それは、いわゆる「~a」ですか?(yes/no/it): " class)
    (case (setf answer (read))
      ((yes no)
       (let ((next-question (if (eql answer 'yes) yes no)))
	 (if next-question
	     (guesser next-question)
	     (setf (slot-value question answer) (get-next-question)))))
      (it
       (format t "なるほど!~%"))
      (t (format t "yes か no か it で答えてください。~%")
	 (guesser *guesser-tree*)))))

実行例

CL-USER> (guesser)
それは、いわゆる「動物」ですか?(yes/no/it): yes
ギブアップ!「それ」はなんですか?: ほ乳類

CL-USER> (guesser)
それは、いわゆる「動物」ですか?(yes/no/it): yes
それは、いわゆる「ほ乳類」ですか?(yes/no/it): yes
ギブアップ!「それ」はなんですか?: クマ

#<:GUESS-QUESTION {11F57CA1}>
CL-USER> (guesser)
それは、いわゆる「動物」ですか?(yes/no/it): yes
それは、いわゆる「ほ乳類」ですか?(yes/no/it): no
ギブアップ!「それ」はなんですか?: ペンギン

#<:GUESS-QUESTION {11F691E9}>
CL-USER> (guesser)
それは、いわゆる「動物」ですか?(yes/no/it): yes
それは、いわゆる「ほ乳類」ですか?(yes/no/it): yes
それは、いわゆる「クマ」ですか?(yes/no/it): it
なるほど!
NIL
CL-USER>