From: Ruby Quiz Date: 2004-12-03T22:50:59+09:00 Subject: [QUIZ] crossword.rb (#10) 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.grayproductions.net/ruby_quiz/ 3. Enjoy! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #!/usr/bin/env ruby class Square @@count = 1 def initialize( holds_letter = false ) @holds_letter = holds_letter @edge = false end attr_reader :holds_letter attr_accessor :edge def render( row, top, left, right, bottom ) if @holds_letter number = "" if (top.nil? or not top.holds_letter) and (bottom and bottom.holds_letter) number = @@count.to_s @@count += 1 elsif (left.nil? or not left.holds_letter) and (right and right.holds_letter) number = @@count.to_s @@count += 1 end if top.nil? and left.nil? row[0] << "######" row[1] << sprintf("#%-4s#", number) row[2] << "# #" row[3] << "######" elsif top.nil? row[0] << "#####" row[1] << sprintf("%-4s#", number) row[2] << " #" row[3] << "#####" elsif left.nil? row[1] << sprintf("#%-4s#", number) row[2] << "# #" row[3] << "######" else row[1] << sprintf("%-4s#", number) row[2] << " #" row[3] << "#####" end else if @edge if top.nil? and left.nil? row[0] << " " row[1] << " " row[2] << " " row[3] << " " elsif top.nil? row[0] << " " row[1] << " " row[2] << " " row[3] << " " elsif left.nil? row[1] << " " row[2] << " " row[3] << " " else row[1] << " " row[2] << " " row[3] << " " end if right and not right.edge row.each { |e| e.sub!(/ $/, "#") } end if left and not left.edge row.each { |e| e.sub!(/ (.{5})$/, '#\1') } end if top and not top.edge row[0].sub!(/ +(#?)$/) do |m| "#" * (m.length - $1.length) + $1 end end if bottom and not bottom.edge row[3].sub!(/ +(#?)$/) do |m| "#" * (m.length - $1.length) + $1 end end else if top.nil? and left.nil? row[0] << "######" row[1] << "######" row[2] << "######" row[3] << "######" elsif top.nil? row[0] << "#####" row[1] << "#####" row[2] << "#####" row[3] << "#####" elsif left.nil? row[1] << "######" row[2] << "######" row[3] << "######" else row[1] << "#####" row[2] << "#####" row[3] << "#####" end end end end end board = [ ] while line = ARGF.gets board << [ ] line.chomp.delete(" ").each_byte do |c| if c == ?X board[-1] << Square.new else board[-1] << Square.new(true) end end end loop do changed = false board.each_with_index do |row, y| row.each_with_index do |cell, x| next if cell.holds_letter or cell.edge if x == 0 or y == 0 or x == board[0].size - 1 or y == board.size - 1 cell.edge = true changed = true next end top = board[y - 1][x] left = board[y][x - 1] right = board[y][x + 1] bottom = board[y + 1][x] if (top and top.edge) or (left and left.edge) or (right and right.edge) or (bottom and bottom.edge) cell.edge = true changed = true end end end break if not changed end board.each_with_index do |row, y| drawn_row = ["", "", "", ""] row.each_with_index do |cell, x| top = y == 0 ? nil : board[y - 1][x] left = x == 0 ? nil : board[y][x - 1] right = x == board[0].size - 1 ? nil : board[y][x + 1] bottom = y == board.size - 1 ? nil : board[y + 1][x] cell.render drawn_row, top, left, right, bottom end drawn_row.each { |e| puts e if e.length > 0 } end