> by Jim Weirich
>
> Here's a program I've had a lot of fun with and might make a good Ruby
> Quiz entry. The program is a animal quiz program.
The first thing I thought was "Knowledge Representation" (expert systems
and the like). But then, for new animals you will have unanswered older
questions, and for old animals you will most definitely not have answers
to new questions.
So you could ask answers to the player for those as well, but that's
getting boring rather soon. If you had the info, you could start with the
question that best splits the collection of animals in half; rinse and
repeat. Hopefully, you wouldn't have to ask all questions, then.
But I don't know how to handle unknown answers for this. Anyone?
Put my solution on my webpages (very primitive for now).
http://chmeee.dyndns.org/~kero/ruby/quiz/index.html
Solution attached at the bottom if you can't read it from there.
Funny stuff is in the querying; I know Animal#to_s is rather
incomplete. Pointers welcome.
+--- Kero ----------------------- kero@chello@nl ---+
| all the meaningless and empty words I spoke |
| Promises -- The Cranberries |
+--- M38c ---
http://httpd.chello.nl/k.vangelder ---+
Animal = Struct.new(:name, :answers)
TreeNode = Struct.new(:question, :yes, :no) # left/right has no meaning
tree = Animal.new("cat", {})
class Animal
def to_s()
use_an = ["a", "e", "i", "o"].include? name[0,1]
"#{use_an ? "an" : "a"} #{name}"
end
end
def query(str)
STDOUT.write "#{str}? "; STDOUT.flush
gets
end
def boolean_query(str)
begin
STDOUT.write "#{str}? (y/n) "; STDOUT.flush
case gets
when /^y/i; true
when /^n/i; false
else raise "ugh" # an exception feels over the top...
end
rescue
puts "please answer with 'y' or 'n'."
retry # ...but the keyword "retry" feels very appropriate.
end
end
loop {
puts "You think of an animal..."
prev, branch = nil, tree
answers = {}
while branch.kind_of? TreeNode
ans = boolean_query branch.question
answers[branch.question] = ans
prev = branch
branch = ans ? branch.yes : branch.no
end
if boolean_query "Is it #{branch}"
puts "I win! Ain't I smart?

"
else
puts "I give up. You win!"
target = query "What animal were you thinking of"
target = Animal.new(target.chomp, answers)
puts "I want to learn from my mistake. Please give me"
question = query "a question that distinguishes #{target} from #{branch}"
question.chomp!
question.capitalize!
question.slice!(-1) if question[-1,1] == "?"
answer = boolean_query "What is the answer to '#{question}?' for #{target}"
target.answers[question] = answer
pair = (answer ? [target, branch] : [branch, target])
new_node = TreeNode.new(question, *pair)
if prev
if prev.yes == branch
prev.yes = new_node
else
prev.no = new_node
end
else
tree = new_node
end
end
ans = boolean_query "Do you want to play again"
break if not ans
}
puts "Thanks for playing!"