Ruby で任意サイズの数独の解答例をやや真面目に作る
どうせやるならちゃんと作れという指令がきたので,仕方なくやや真面目にシャッフルするようにしてみた.長くなるからやだったのに.
# -*- coding: utf-8 -*- 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 # 行をランダムに入れかえる (i..i+n-1の間) (1..z*100).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 # n 行単位で行をランダムに入れかえる (1..z*100).each do j = rand(n) k = rand(n) next if j == k (0..n-1).each do |y| t = arr[y+j*3] arr[y+j*3] = arr[y+k*3] arr[y+k*3] = t end end # 列をランダムに入れかえる (i..i+n-1の間) (1..z*100).each do i = rand(n) j = rand(n) k = rand(n) next if j == k (0..z-1).each do |x| l = i*n t = arr[x][l+j] arr[x][l+j] = arr[x][l+k] arr[x][l+k] = t end end # n 列単位で列をランダムに入れかえる (1..z*100).each do j = rand(n) k = rand(n) next if j == k (0..n-1).each do |y| (0..z-1).each do |x| t = arr[x][y+j*3] arr[x][y+j*3] = arr[x][y+k*3] arr[x][y+k*3] = t end end end return arr end arr = makeBoard 3 arr.each do |x| print x.join(',') print "\n" end
これでもまだ規則性はのこる.たとえば下の例だと 7,4 が 3x3 のマスで見たとき,必ず同じ列にあらわれる.9, 8 とかもそう.他もそう.そうか,seed から 2 行目以降をつくるときにちょっと手を加えれば (ry
実行例 (3x3)
3,1,5,8,6,7,2,9,4
2,9,4,1,3,5,6,8,7
6,8,7,9,2,4,3,1,5
7,2,9,3,4,1,5,6,8
4,3,1,6,5,8,7,2,9
5,6,8,2,7,9,4,3,1
9,4,3,5,1,6,8,7,2
1,5,6,7,8,2,9,4,3
8,7,2,4,9,3,1,5,6