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