エイトクイーンパズル、昨日の続き。答えが合わないと思ったのは探索の途中で解を表示させていたせいだった。バックトラック法なので、最後に生成したクイーンを置く位置を探すときに、既に置かれているクイーンの位置が変わることがあるのだった。
探索が終わってから表示させたらちゃんと正しい解が求まっていた。
以下、修正版。

#!/usr/bin/ruby -Ks
# 8 queen problem

$n = 8
$ini_row = 1

class Queen
  def initialize(col, neighbor)
    @row = $ini_row
    @col = col
    @neighbor = neighbor
  end

  def show
    print "|", "_|"*(@row-1), "Q", "_|"*($n-@row), " (#@row, #@col)\n"
  end

  def findSolution
    while @neighbor and @neighbor.canAttack?(@row, @col)
      unless advance
        return false
      end
    end
    true
  end

  def canAttack?(row, col)
    if (row == @row) or ((@col-col).abs == (@row-row).abs)
      return true
    end
    @neighbor and @neighbor.canAttack?(row, col)
  end

  def advance
    if @row < $n
      @row += 1
      return findSolution
    elsif @neighbor and (not @neighbor.advance)
      return false
    end
    @row = 1
    return findSolution
  end
end

queens = []
lastQueen = nil
(1..$n).each do |i|
  lastQueen = Queen.new(i, lastQueen)
  lastQueen.findSolution
  queens << lastQueen
end

queens.each {|q| q.show}