Here is my solution for the word search quiz. It's faily simple and stupid and
doesn't do any of the extras, except it accepts a '?' wildcard.
But then it also finds words that break the board boundaries and continue on
the other side.. call it bug of feature ;) , so this:
$ ruby wordsearch.rb
UEWRTRBHCB
CXGZUWRYUR
ROCKSBARCU
SFKFMTYSGE
YSOOUNMZIM
TCGPRTIDAN
HZGHQGWTUV
HQMNDXZBST
NTCLATNBCE
YBURPZUXMS
Ruby, rocks, DAN, matZ
... gives you:
+++R+++++B
++++U+++U+
ROCKSB+R++
++++++Y+++
+++++++++M
+++++++DAN
+++++++T++
++++++Z+++
++++++++++
YBUR++++++
Happy new year,
Martin
# wordquiz.rb
# create a each_chr method
class String
def each_chr
self.each_byte { |b| yield b.chr }
end
end
class Puz
DIRECTIONS = [[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]]
# puzzle - array of strings (one for each line)
# word_list - array for words to look for
def initialize(puzzle, word_list)
@puzzle = puzzle
@word_list = word_list
# get dimention of the board
@x,@y = @puzzle[0].length-1, @puzzle.length-1
# create an empty result board
@result = Array.new(@y+1)
0.upto(@y) { |i| @result[i] = String.new("+"*(@x+1)) }
end
protected
# return cursor to the next position in direction
def gonext(x,y,d)
x+=d[0]; y+=d[1]
x = 0 if x > @x; x = @x if x < 0
y = 0 if y > @y; y = @y if y < 0
[x,y]
end
# writes a word into the @result container
def write_result(word, x,y, direction)
word.each_chr do |c|
@result[y][x] = c
x,y = gonext(x,y, direction)
end
end
# yields all possible cursor positions of the board
def each_position
0.upto(@y) { |y| 0.upto(@x) { |x| yield x,y }}
end
def char_match(char, x, y)
return true if char == '?' # allow wildcard '?'
@puzzle[y][x].chr == char
end
# finds a given word on a position in a specific direction
def find_in_direction(word, x, y, d)
word.each_chr do |c|
return false if !self.char_match(c, x, y)
x,y = gonext(x,y,d)
end
true
end
# finds a word on a position
def find(word, x, y)
DIRECTIONS.each do |d|
write_result(word, x,y,d) if find_in_direction(word, x,y, d)
end
end
public
def resolve
@word_list.each do |word|
each_position { |x,y| find(word, x, y) }
end
return (@result.join("\n"))
end
end
board = []
while true do
inp = STDIN.gets.strip
if inp.length > 0 then board << inp else break end
end
puts Puz.new(board, STDIN.gets.split(',').collect{ |w|
w.strip.upcase}).resolve
On Friday 29 December 2006 16:06, Ruby Quiz 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 Daniel Finnie
>
> Today's quiz would've been most useful in elementary school, where over
> half of the homework assignments were word search puzzles. The concept of
> these puzzles is simple enough that an elementary school student could
> understand it: given a box of letters, find a line containing the letters
> of a specified word in order.
>
> For example, find the words ruby, dan, rocks, and matz in the following
> text:
>
> U E W R T R B H C D
> C X G Z U W R Y E R
> R O C K S B A U C U
> S F K F M T Y S G E
> Y S O O U N M Z I M
> T C G P R T I D A N
> H Z G H Q G W T U V
> H Q M N D X Z B S T
> N T C L A T N B C E
> Y B U R P Z U X M S
>
> The correct answer in the correct output format:
>
> + + + R + + + + + +
> + + + + U + + + + +
> R O C K S B + + + +
> + + + + + + Y + + +
> + + + + + + + + + M
> + + + + + + + D A N
> + + + + + + + T + +
> + + + + + + Z + + +
> + + + + + + + + + +
> + + + + + + + + + +
>
> Notice that the words can go backwards and diagonally, and can intersect
> one another. Searching is case insensitive.
>
> The word search solver should accept input entered by the user after
> running the program, i.e., not exclusively through STDIN or a file, by
> entering the puzzle line by line, pressing return after each line. A blank
> line indicates the end of the puzzle and the start of the comma separated
> words to find. The following example shows how a user would enter the above
> puzzle, with descriptive text
>
> >from the program removed.
>
> $ ./wordsearch.rb
> UEWRTRBHCD
> CXGZUWRYER
> ROCKSBAUCU
> SFKFMTYSGE
> YSOOUNMZIM
> TCGPRTIDAN
> HZGHQGWTUV
> HQMNDXZBST
> NTCLATNBCE
> YBURPZUXMS
>
> Ruby, rocks, DAN, matZ
>
> Now, by itself, this quiz is fairly simple, so I offer an additional
> challenge. Write a beautiful, extensible, and easily-modifiable program
> without looking at the extra credit before starting. When you're done, try
> implementing extra credit options using less than 5 or 6 (reasonable) lines
> of code.
>
> * An output format superior to the one given. The output format given
> should remain the default unless both formats don't differ on a
> textual basis. That should sound cryptic until pondered, I can't
> give too much away!
> * Allow for "snaking" of answers, in other words, the letters
> composing a word don't have to be in a straight line.
> * An option to give a hint, i.e., "The word ruby traverses the bottom
> left and bottom right quadrants."
> * Decide what to do with accented letters.
> * Allow for wildcard letters.