------=_Part_49079_10737769.1168200513069
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Here is my solution.

-Chunyun

#== Synopsis
#This is the solution to Ruby Quiz #108 described on
http://www.rubyquiz.com/quiz108.html.
#
#== Usage
#   text_twist.rb dictionary_file
#
#== Author
#   Chunyun Zhao(chunyun.zhao / gmail.com)
#
class Dictionary
  MIN_LEN, MAX_LEN = 3, 6
  attr_reader :max_letters
  def initialize(dict_file, min=MIN_LEN, max=MAX_LEN)
    @min_len = min
    @max_len = max
    @words = Hash.new {|hash,key|hash[key]=[]}
    File.foreach(dict_file) {|word|add_word(word.strip)}
    @max_letters = @words.keys.select {|key| key.size==@max_len}
  end
  def word_list(letters)
    words=[]
    permutate(letters).select {|letters|
      letters.size.between? @min_len, @max_len
    }.uniq.each {|key|
      words += @words[key]
    }
    words.sort_by {|word| word.size}
  end
  private
  def add_word(word)
    if (@min_len..@max_len)===word.size && word=~/^[a-z]+$/i
      word.downcase!
      @words[word.split(//).sort] << word
    end
  end
  def permutate(letters)
    _letters = letters.dup
    result = []
    while letter = _letters.shift
      permutate(_letters).each do |perm|
        result << [letter] + perm
      end
      result << [letter]
    end
    result
  end
end

Task = Struct.new(:letters, :words)

class GameUi
  def initialize(dict)
    @dictionary = dict
    @history_tasks = []
    @rounds = 1
    @score = 0
  end

  def next_task
    letters = @dictionary.max_letters[rand(@dictionary.max_letters.size)]
    retry if @history_tasks.include?(letters)
    task = Task.new(letters, @dictionary.word_list(letters))
    @history_tasks << task
    task
  end

  def run_task
    @task = next_task
    @found = []
    @cleared = false
    puts "\nRound #{@rounds}. Letters: #{@task.letters*', '}. Hint: number
of matching words: #{@task.words.size}"
    while !(word=ask("Enter your word:")).empty?
      if @found.include? word
        puts "Word already found!"
      elsif @task.words.include? word
        @found << word
        @score += word.size
        puts "Good job! You scored #{word.size} points!"
        if word.size == @task.letters.size
          @cleared = true
          puts "\nBingo! Round #@rounds cleared. You found #{@found.size}
word#{'s' if @found.size > 1}. "
          break
        end
      else
        puts "Wrong word!"
      end
    end
    puts "Missed words: #{(@task.words-@found)*', '}."
    @cleared
  end

  def run
    while run_task
      answer = ask("\nProceed to next round?")
      break if answer !~ /^y/i
      @rounds += 1
    end
    puts "\nYou've cleared #{cleared=@cleared?@rounds:@rounds-1} round#{'s'
if cleared > 1}, and your total score is #{@score}."
  end

  def ask question
    print question, " (Hit enter to exit)=> "
    gets.strip
  end
end
if __FILE__ == $0
  if ARGV.size != 1
    puts "Usage: #{File.basename(__FILE__)} dictionary_file"
    exit
  end
  GameUi.new(Dictionary.new(ARGV.shift)).run
end
__END__

On 1/5/07, Ruby Quiz <james / grayproductions.net> wrote:
>
> The three rules of Ruby Quiz:
>
> 1.  Please do not post any solutions or spoiler discussion for this quiz
> until
> 48 hours have passed from the time on this message.
>
> 2.  Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3.  Enjoy!
>
> Suggestion:  A [QUIZ] in the subject of emails about the problem helps
> everyone
> on Ruby Talk follow the discussion.  Please reply to the original quiz
> message,
> if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
>
> by Ben Bleything
>
> This is a riff on the Jumble puzzle found in many (US) newspapers. More
> specifically, it's based on the game TextTwist[1], made by GameHouse[2]
> and
> published in various places around the web.
>
> The mechanic of TextTwist is simple. The player is given six letters and
> is
> tasked with unscrambling those letters into as many words as possible. If
> the
> player can use all six letters in a word, they proceed to the next round.
>
> Your task is to build the back-end engine to run a TextTwist clone.
> Effectively,
> this means that you must generate a list of three- to six-letter words
> that can
> all be constructed from the same six letters. This list must contain at
> least
> one six-letter word.
>
> Bonus points for building a completely functional game!
>
>         [1]: http://games.yahoo.com/games/texttwist.html (just one
> example, java)
>         [2]: http://www.gamehouse.com/
>
>

------=_Part_49079_10737769.1168200513069--