Here’s my submission. There are two programs: the first builds a set
of puzzles from a decent word list I found on line. Files like
/usr/dict/words have too many obscure words. The second is a (very)
simplistic game interface.
A “puzzle” is just a string of six or more 3-6 letter words, sorted by
length. The output of the first program is just one line per puzzle,
with the words separated by colons. The words are ROT13 encoded. The
puzzles.rb program generates 905 different puzzles.
Bob S.
---------- puzzles.rb ----------
puzzles.rb
generate puzzles for use by wordblend.rb program
usage: ruby puzzles.rb >puzzles.dat
require ‘open-uri’
require ‘yaml’
these urls point to text files with lists of 2000 commonest
English word “families”, including plurals and other forms.
this ends up generating reasonably good puzzles.
URIS = %w{
http://www1.harenet.ne.jp/~waring/vocab/wordlists/full1000.txt
http://www1.harenet.ne.jp/~waring/vocab/wordlists/full2000.txt
}
minimum number of words necessary to form a puzzle
MIN_SIZE = 6
define some helper functions
class String
returns string with characters in sorted order
def sort
split(//).sort.join
end
returns true if s is a subword of the string. both
the string and s must be sorted!
def subword?(s)
i = j = 0
while j < s.length
i += 1 while i < length and self[i] != s[j]
i < length or return false
j += 1
i += 1
end
true
end
end
grab the 3-6 letter words from word lists. sort each word by
character (e.g. ‘test’ becomes ‘estt’), and then accumulate
STDERR.puts “Fetching words…”
words = Hash.new {|h,k| h[k] = []}
URIS.each do |uri|
open(uri) do |f|
f.read.split.select {|w| w.length >= 3 and w.length <= 6}.each do
|word|
word.upcase!
sword = word.sort
words[sword] << word
end
end
end
find puzzles by looking at which sorted words are contained in
other six-character sorted words.
STDERR.puts “Finding puzzles…”
n = 0
words.keys.select {|w| w.length == 6}.each do |key|
puzzle = words.select {|ssub, subs| key.subword?(ssub)}.collect {|a|
a.last}.flatten.sort_by {|w| “#{w.length}#{w}”}
next if puzzle.size < MIN_SIZE
puts puzzle.join(‘:’)
end
---------- wordblend.rb ----------
wordblend.rb
simplistic Word Blend puzzle game
uses puzzles.dat file created by separate puzzles.rb program
class String
def rot13
tr ‘A-Za-z’, ‘N-ZA-Mn-za-m’
end
end
class Puzzle
attr_reader :words, :letters, :board
def self.pick
@@puzzles ||= IO.readlines(‘puzzles.dat’)
new(@@puzzles[rand(@@puzzles.size)].chomp.rot13.split(‘:’))
end
def initialize(words)
@words = words
scramble
@board = words.collect {|w| w.gsub(/./, ‘-’)}
end
def scramble
@letters = words.last.split(//).sort_by {rand}.join
scramble if words.include? @letters
end
def help
puts “Enter ‘Q’ to give up, ‘S’ to scramble letters”
end
def play
help
turn while board != words
puts board
end
def turn
puts board
puts
puts letters
while true
print "? "
guess = gets.strip.upcase
if guess == ‘’
help
redo
end
if guess == ‘S’
scramble
puts letters
redo
end
@board = words.dup if guess == ‘Q’
i = words.index(guess) and board[i] = guess
break
end
end
end
play a random game
p = Puzzle.pick
p.play