Ruby で任意サイズの数独の解答例を作る

与えられた問題の解答を求めるのではなくて,数独のルールに従って 1 から z までの数を盤面にうめた例を作るというプログラム.任意のサイズで作れるプログラムが見つからなかったので作ってみた.なお,実際に数独の問題を作成するには,ここから盤面に穴をあけていって,解答できるかどうかチェックするという作業が必要になる.

↓は参考

def makeBoard(n)
  z = n * n
  arr = []
  seed = []

  # [1,2,3,....,z] という配列を作る
  (1..z).each do |x|
    seed.push x
    arr.push []
  end

  # 配列の中身を適当にシャッフルする
  (1..z*100).each do
    i = rand(z)
    j = rand(z)
    t = seed[i]
    seed[i] = seed[j]
    seed[j] = t
  end
  
  # seed を1行目として2行目以降を作る
  (0..z-1).each do |x|
    (0..z-1).each do |y|
      arr[x][y] = seed[(y + (x%n)*n + (x/n))%z]
    end
  end

  # 行をランダムに入れかえる
  (1..z*10).each do
    i = rand(n)
    j = rand(n)
    k = rand(n)
    next if j == k
    l = i*n
    t = arr[l+j]
    arr[l+j] = arr[l+k]
    arr[l+k] = t
  end

  # 列のランダムな入れかえをするとなおよいはず
    
  return arr
end

arr = makeBoard 4
arr.each do |x|
  print x.join(',')
  print "\n"
end

列方向の入れかえをしてないのと,行のシャッフルが不十分 (i から i+n-1 の間でしかシャッフルしてない)ので偏った解答例が出てくる.下の 3x3 の例だと,隣りあう二つの数字の並びが固定されているのがわかる.もうちょっとランダムな答えにしたければ,少なくとも列方向のシャッフルをすべき.