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>