#a sudoku solver in Rubymodule Sudokuclass PuzzleASCII=".123456789"BIN="\000\001\002\003\004\005\006\007\010\011"def initialize(lines)if(lines.respond_to?:join)s=lines.joinelses=lines.dupends.gsub!(/\s/,"")raise Invalid,"Grid is the wrong size" unless s.size==81if i=s.index(/[^123456789\.]/)raise Invalid,"Illegal character #{s[i,1]} in puzzle"ends.tr!(ASCII,BIN)@grid=s.unpack('c*')raise Invalid,"Initial puzzle has duplicates" if has_duplicates?enddef to_s(0..8).collect{|r|@grid[r*9,9].pack('c9')}.join("\n").tr(BIN,ASCII)enddef dupcopy=super@grid=@grid.dupcopyenddef[](row,col)@grid[row*9+col]enddef[]=(row,col,newvalue)unless (0..9).include? newvalueraise Invalid ,"illegal cell value"end@grid[row*9+col]=newvalueendBoxOfIndex=[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,].freezedef each_unknown 0.upto 8 do |row| 0.upto 8 do |col| index=row*9+col next if @grid[index]!=0 box=BoxOfIndex[index] yield row,col,box end endenddef has_duplicates?0.upto(8) {|row| return true if rowdigits(row).uniq!} 0.upto(8) {|col| return true if rowdigits(col).uniq!} 0.upto(8) {|box| return true if rowdigits(box).uniq!}falseendAllDigits=[1,2,3,4,5,6,7,8,9].freezedef possible(row,col,box)AllDigits-(rowdigits(row)+coldigits(col)+boxdigits(box))endprivatedef rowdigits(row)@grid[row*9]-[0]enddef coldigits(col)result=[]col.step(80,9){|i|v=@grid[i]result<<v if (v!=0)}resultendBoxToIndex=[0,3,6,27,30,33,54,57,60].freezedef boxdigits(b)i=BoxToIndex[b][@grid[i],@grid[i+1],@grid[i+2],@grid[i+9],@grid[i+10],@grid[i+11],@grid[i+18],@grid[i+19],@grid[i+20],]-[0]endendclass Invalid<StandardErrorendclass Impossible<StandardErrorenddef Sudoku.scan(puzzle)unchanged=falseuntil unchangedunchanged= truermin,cmin,pmin=nilmin=10 puzzle.each_unknown do |row,col,box|p=puzzle.possible(row,col,box)case p.sizewhen 0raise Impossiblewhen 1puzzle[row,col]=p[0]unchanged=falseelseif unchanged && p.size<minmin=p.sizermin,cmin,pmin=row,col,pendendendendreturn rmin,cmin,pminenddef Sudoku.solve(puzzle)puzzle=puzzle.dupr,c,p=scan(puzzle)return puzzle if r==nilp.each do |guess|puzzle[r,c]=guessbeginreturn solve(puzzle)rescue Impossiblenextendraise Impossibleendend