Solution to ruby quiz #107

Hello. This is my first ever ruby program of more than 10 lines, so be
gentle. :slight_smile: I’m a java programmer by profession and it will probably
show
in my solution, but I thought I’d post it and get feedback on my code.

I didn’t do any of the extra credit, although the to_s on the LetterGrid
class is an alternate output format. Wildcards would be very easy to
add.

I attached both my solution and some test cases I wrote along the way.
If
attachments are not appropriate, I can re-submit with my code copied
into
the body of the message (sorry for my n00b ignorance here!)

Thanks!
John

Since it seems like the posting that made it up on rubyquiz.com didn’t
end
up so easy to read, here is my code in-line.
John

wordsearch.rb
#!/sw/bin/ruby
require ‘delegate’

class LetterGrid
attr_reader :characterRows
def initialize(*rows)
@characterRows = rows.collect{|x| GridLetterSequence.new(x)}
end

def
@characterRows[key]
end

def each
@characterRows.each { |c| yield c }
end

def sequences
(horiz_sequences + vert_sequences + diag_right_sequences +
diag_left_sequences).uniq
end

def horiz_sequences
result = @characterRows + @characterRows.collect{|x| x.reverse}
result.uniq
end

def vert_sequences
result = []
@characterRows.each{|row| row.each_with_index {|c,i| result[i] ?
result[i] << c : result[i] = [c]} }
result.collect!{|x| GridLetterSequence.new(x)}
result += result.collect{|x| x.reverse}
result.uniq
end

def diag_right_sequences
diag_sequences(@characterRows)
end

def diag_sequences(arrayToLookAt)
lists = right_diag(arrayToLookAt.length-1,
arrayToLookAt[0].length-1)
seqs = lists.collect{|x|
x.inject(GridLetterSequence.new(“”)){|accum, y|
accum << arrayToLookAt[y[0]][y[1]]}}
seqs += seqs.collect{|x| x.reverse}
seqs.uniq
end

def diag_left_sequences
diag_sequences(@characterRows.reverse)
end

def to_s
@characterRows.inject(“”){|accum, row| accum += (row.to_s + “\n”)}
end

def search(*tokens)
s = sequences
s.each do |s|
seq = GridLetterSequence.new(s)
tokens.each{|token| seq.findAndMark(token)}
end
end
end

class GridLetter
def initialize(char)
@char = char
@found = false
end

attr_accessor :found
attr_reader :char

def eql?(object)
self == (object)
end

def ==(object)
object.equal?(self) || (object.instance_of?(self.class) &&
object.char == char && object.found == found)
end

def to_s
if (@found)
@char.upcase
else
@char.downcase
end
end
end

class GridLetterSequence < DelegateClass(Array)
def initialize(value)
if (value.instance_of?(String))
super(value.split(//).collect{|x| GridLetter.new(x)})
else
super
end
end

def to_s
join(" ")
end

def find(pattern)
stringval = join
results = []
i = 0
while (loc = stringval.index(Regexp.new(pattern, “i”), i))
results << [loc, (loc -1 + pattern.length)]
i = loc + 1
end
results
end

def markFound(ranges)
ranges.each{|r| self[Range.new(*r)].each{|x| x.found = true}}
end

def findAndMark(pattern)
markFound(find(pattern))
end
end

def right_diag(rows, columns)
maxr=rows
minr=rows
maxc=0
minc=0
results = []
while (maxr >= 0 && minc <= columns)
while (minr >= 0 && maxc <= columns)
cs = []
rs = []
(minr…maxr).each {|r| rs << r}
(minc…maxc).each {|c| cs << c}

  minr = minr - 1
  maxc = maxc + 1
  subresult = []
  rs.each_with_index{|x,i| subresult << [x, cs[i]]}
  #subresult.each{|x| puts "#{x[0]}, #{x[1]}"}
  #puts
  results << subresult
end
maxr = maxr - 1 if (minc > 0 || rows >= columns)
minc = minc + 1 if (maxr < columns || columns >= rows)
minr = 0
maxc = columns

end
results
end

if FILE == $0
rows = []
while ((row = gets.chomp) != “” )
rows << row
end
words = gets.chomp.split(/,/)
words.collect{|word| word.strip!}

g = LetterGrid.new(*rows)
g.search(*words)

puts
g.each do |r|
r.each do |c|
if (c.found)
print c
else
print “+”
end
print " "
end
puts
end
end