@m_seki の

I like ruby tooから引っ越し

書き直し

IPSJの課題に合うように書き直してみる。課題の都合により次の行に進めるかどうかを試すメソッドをわけた。

class NQueen
  def concat(board, row)
    board.each_with_index do |v, col|
      return nil if v == row
      return nil if (v - row).abs == board.size - col
    end
    board + [row]
  end

  def nq(size, board=[])
    found = 0
    size.times do |row|
      fwd = concat(board, row)
      next unless fwd
      return 1 if fwd.size == size
      found += nq(size, fwd)
    end
    found
  end
end

if __FILE__ == $0
  size = (ARGV.shift || '5').to_i
  puts NQueen.new.nq(size)
end

Rinda化

まずipsjメソッドの方。

require 'rinda/rinda'

DRb.start_service

size = (ARGV.shift || '5').to_i
ro = DRbObject.new_with_uri('druby://localhost:12345')
ts = Rinda::TupleSpaceProxy.new(ro)

size.times do |r1|
  size.times do |r2|
    ts.write([:nq, size, r1, r2])
  end
end

found = 0
size.times do |r1|
  size.times do |r2|
    tuple = ts.take([:nq_ans, size, r1, r2, nil])
    found += tuple[4]
  end
end
puts found

そして仕事をする方(nq2)。

require 'rinda/rinda'
require 'nq'

DRb.start_service

ro = DRbObject.new_with_uri('druby://localhost:12345')
ts = Rinda::TupleSpaceProxy.new(ro)

while true
  symbol, size, r1, r2 = ts.take([:nq, nil, nil, nil])
  found = NQueen.new.nq2(size, r1, r2)
  ts.write([:nq_ans, size, r1, r2, found])
end

どうでもいいけどTupleSpaceサーバ。

require 'rinda/tuplespace'

ts = Rinda::TupleSpace.new
DRb.start_service('druby://localhost:12345', ts)
DRb.thread.join