腹立ちまぎれに
数独を解くナニを無理やり作ったら動いた。腹立ちまきれな上、相当に酔ってるんですが。
仕事な現実トウヒとして色々試してたんですが、動かなかったこれまでの試行錯誤は無駄ではなかったにせよ、何なんだという思いは強い。
# これはこれで腹立つな。(こらー
とりあえず、数え上げなナニでの手法はデキた (デキたのか?) ので、もう少し洗練されたアレな手法を試したいな、と。
# Solve Sudoku (Without even thinking!) ってカンジのナニ
読んでばかりだとストレスがタマる。crash 使ってみ、というエントリを発見しているんですが、もう少し現実逃避にハシる予定ッス。
で、とりあえずコードを晒してみる事にする。第一段階の総当たり方式。処理にかかる時間も結構かかっている模様。あと、速度的なナニは別として手を入れるトコは結構ありそうな感じなんですが、とりあえず。
基本的には、最初バージョンってコトで、OK, Sudokuになるべく手を入れない形で作成しています。あ、あと project.rb はOK, Sudokuと同じなので略します。
require 'project.rb' class TC_MyTest < Test::Unit::TestCase def setup end def test_cells game = Game.test_game (0..80).each do | i | assert_equal(i, game.cell(i)) end end def test_row_three game = Game.test_game assert_equal([27, 28, 29, 30, 31, 32, 33, 34, 35], game.row(3)) end def test_row_eight game = Game.test_game assert_equal([72, 73, 74, 75, 76, 77, 78, 79, 80], game.row(8)) end def test_column_three game = Game.test_game assert_equal([3, 12, 21, 30, 39, 48, 57, 66, 75], game.column(3)) end def test_square_four game = Game.test_game assert_equal( [30, 31, 32, 39, 40, 41, 48, 49, 50], game.square(4)) end def test_square_eight game = Game.test_game assert_equal( [60, 61, 62, 69, 70, 71, 78, 79, 80], game.square(8)) end def data4test [nil, 6, nil, 1, nil, 4, nil, 5, nil, nil, nil, 8, 3, nil, 5, 6, nil, nil, 2, nil, nil, nil, nil, nil, nil, nil, 1, 8, nil, nil, 4, nil, 7, nil, nil, 6, nil, nil, 6, nil, nil, nil, 3, nil, nil, 7, nil, nil, 9, nil, 1, nil, nil, 4, 5, nil, nil, nil, nil, nil, nil, nil, 2, nil, nil, 7, 2, nil, 6, 9, nil, nil, nil, 4, nil, 5, nil, 8, nil, 7, nil] end def test_cells obj = Game::test_game tbl = [] (0..80).each do | i | tbl << i end assert_equal(tbl, obj.cells) end def test_cells_init obj = Game.new assert(!obj.cells_init([])) obj.cells_init(data4test) assert_equal(data4test, obj.cells) end def test_row_integrate? obj = Game.new obj.cells_init(data4test) assert(obj.row_integrate?) tbl = data4test tbl[0] = 6 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.row_integrate?) end def test_col_integrate? obj = Game.new obj.cells_init(data4test) assert(obj.col_integrate?) tbl = data4test tbl[0] = 2 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.col_integrate?) end def test_square_integrate? obj = Game.new obj.cells_init(data4test) assert(obj.square_integrate?) tbl = data4test tbl[0] = 2 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.square_integrate?) end def test_integrate? obj = Game.new obj.cells_init(data4test) assert(obj.integrate?) tbl = data4test tbl[80] = 2 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.integrate?) tbl = data4test tbl[0] = 2 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.integrate?) tbl = data4test tbl[0] = 6 obj.cells_init(tbl) assert_not_equal(obj.cells, data4test) assert(!obj.integrate?) end def test_nilElements obj = Game.new obj.cells_init(data4test) tbl = [0, 2, 4, 6, 8, 9, 10, 13, 16, 17, 19, 20, 21, 22, 23, 24, 25, 28, 29, 31, 33, 34, 36, 37, 39, 40, 41, 43, 44, 46, 47, 49, 51, 52, 55, 56, 57, 58, 59, 60, 61, 63, 64, 67, 70, 71, 72, 74, 76, 78, 80] assert_equal(tbl, obj.nilElements) end def test_candidacy obj = Game.new obj.cells_init(data4test) assert_equal([3, 9], obj.candidacy(0)) end def test_getRowNumber obj = Game.new (0..80).each do | i | assert_equal(i / 9, obj.getRowNumber(i)) end end def test_getColumnNumber obj = Game.new (0..80).each do | i | assert_equal(i % 9, obj.getColumnNumber(i)) end end def test_getSquareNumber tbl = [0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 3, 3, 3, 4, 4, 4, 5, 5, 5, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 6, 7, 7, 7, 8, 8, 8, 6, 6, 6, 7, 7, 7, 8, 8, 8] obj = Game.new (0..80).each do | i | assert_equal(tbl[i], obj.getSquareNumber(i)) end end def test_solve obj = Game.new obj.cells_init(data4test) obj.solve obj.output end end class Result attr_accessor :result_list def initialize @result_list = [] end end class Game def initialize @result = Result.new end def Game::test_game game = Game.new game.test_game game end def test_game @cells = [] for i in 0..80 @cells.push i end end def cells_init(obj) @cells = Array.new(81) unless obj.size == 81 return false end (0..80).each do | i | @cells[i] = obj[i] end end def cell(i) @cells[i] end def cells @cells.collect { | item | item } end def row(row_number) row_start = row_number*9 @cells[row_start, 9] end def column(column_number) column_indexes(column_number).collect { | c | cell(c) } end def column_indexes(column_number) (0..8).collect { | row | column_number+row*9 } end def square(square_number) square_indexes(square_number).collect { | c | cell(c) } end def square_indexes(square_number) start_cell = start_cell(square_number) raw_square.collect { | offset | start_cell + offset } end def raw_square [0, 1, 2, 9, 10, 11, 18, 19, 20] end def start_cell(square_number) first_row = square_number / 3 * 3 first_column = (square_number % 3) * 3 first_row * 9 + first_column end def row_integrate? (0..8).each do | i | unless row(i).compact.size == row(i).compact.uniq.size return false end end true end def col_integrate? (0..8).each do | i | unless column(i).compact.size == column(i).compact.uniq.size return false end end true end def square_integrate? (0..8).each do | i | unless square(i).compact.size == square(i).compact.uniq.size return false end end true end def integrate? row_integrate? && col_integrate? && square_integrate? end def getRowNumber(idx) idx / 9 end def getColumnNumber(idx) idx % 9 end def getSquareNumber(idx) (idx / 3 % 3) + (idx / 27 * 3) end def fullElements [1, 2, 3, 4, 5, 6, 7, 8, 9] end def nilElements tbl = [] @cells.each_with_index do | itm, idx | if itm == nil tbl << idx end end tbl end def candidacy(idx) tmp = fullElements - row(getRowNumber(idx)) tmp -= column(getColumnNumber(idx)) tmp -= square(getSquareNumber(idx)) end def solve unless integrate? return else if nilElements == [] @result.result_list << @cells return end end idx = nilElements.first candidacy(idx).collect do | item | tmp = self.dup cells = @cells cells[idx] = item tmp.cells_init(cells) tmp.solve end end def output @result.result_list.collect do | item | str = "" (0..80).each do |i| if 0 == i % 9 p str str = "" end str += item[i].to_s + " " end p str end end end
識者のコメント求む。(って全然ダメ、とか強烈なダメが入りそうだなぁ)
output とか超手抜き。
あと、再起メソッドの test ってどうやって書くんでしょうね。