From: John Watson Date: 2007-01-03T03:37:32+09:00 Subject: Re: solution to ruby quiz #107 ------=_Part_14929_18838180.1167763044727 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 wrote: > > Hello. This is my first ever ruby program of more than 10 lines, so be > gentle. :) 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 > > > > ------=_Part_14929_18838180.1167763044727--