On Dec 5, 2004, at 8:07 AM, Markus Koenig wrote:

> This is my solution.

Here's mine...  again.  (Feel bad about the early spoiler.  Sorry!)

This code is far from pretty.  It was one of those solutions that kept 
getting fixes piled on until it works.  I probably should has rewritten 
it, but it does work.

If you did this problem in 20 minutes, you're about 5 times smarter 
than me.

James Edward Gray II

#!/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