From: Dave Burt Date: 2005-04-22T00:34:33+09:00 Subject: Re: [SOLUTION] Madlibs (#28) I wrote earlier: # Version 1 is a function, and requires serial input. Version 2 is a class, and handles random input, which means you can easily use it to power your new graphical interface. Cheers, Dave class MadLib # You can enumerate the placeholders... not too useful, though. include Enumerable def initialize(string) # the original madlib string is kept @s = string # a placeholder for each user entry required # maps a tag name or number onto a [question, answer] array. @placeholders = {} # an index for each set of brackets in @s # the key into @placeholders for each respective set of brackets @index = [] # the initial scan gets tag names and assigns numbers for tags with no name i = '0' @s.scan /\(\(([^:)]*):?(.*?)\)\)/ do |a, b| if @placeholders.has_key? a @index << a elsif b.size > 0 @index << a @placeholders.update a => [b, nil] else @index << i @placeholders.update i => [a, nil] i = i.succ end end end def []=(index, answer) @placeholders[index][1] = answer @placeholders[index] end def [](index) @placeholders[index] end def outstanding @index.select {|i| @placeholders[i][1].nil? }.uniq end def outstanding_questions outstanding.map {|i| @placeholders[i][0] } end def each_outstanding outstanding.each do |i| yield @placeholders[i] end end def all @index.uniq end def all_questions all.map {|i| @placeholders[i][0] } end def each all.each do |i| yield @placeholders[i] end end def done? @placeholders.all? {|k, v| v[1] } end def collect! all.each do |i| self[i] = yield @placeholders[i] end self end def to_s if done? story else "" end end private def story i = 0 @s.gsub /\(\(.*?\)\)/ do |token| i = i.succ @placeholders[@index[i - 1]][1] end end end if $0 == __FILE__ m = MadLib.new(ARGF.read) m.collect! do |question, answer| answer or begin print "#{question}? " gets.chomp end end puts m end