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

wordsearch.rb (3.48 KB)

wordsearchtest.rb (4.49 KB)

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 (key)
    @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

···

On 1/1/07, John Watson <jkwatson@gmail.com> wrote:

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