Advertisement
Guest User

Ruby Sudoku Bruteforce Solver

a guest
Aug 2nd, 2012
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 4.48 KB | None | 0 0
  1. ### NOTES:
  2. # some examples of how i use the term 'index', 'column', 'row', 'square' below
  3. # index(0)=row(0) col(0) square(0)
  4. # index(8)=row(0) col(1) square(3)
  5. # index(9)=row(1) col(0) square(0)
  6. # index(27)=row(3) col(0) square(4)
  7. # index(80)=row(8) col(8) square(8)
  8. #
  9. # index is between 0 and 80 inclusive
  10. # row column and square are between 0 and 8 inclusive
  11. #
  12. # i use the term 'box' to indicate a something which has one number in it. (each row has 9 boxes...)
  13.  
  14. ############################################################# THE BAREBONES
  15.  
  16.  
  17.  
  18.  
  19.  
  20. class Sudo
  21.     def self.index_to_row_col_sq(index) #### converts the index of a 'box' (0-81) to its row, column and square
  22.         row,col=index.divmod(9)
  23.         sq=((row/3)*3)+((col/3)) #Row 0 includes squares 0,1,2. Col 0 includes squares 0,3,6.
  24.         [row,col,sq]
  25.     end
  26.  
  27.     attr_accessor :rows,:cols,:squares
  28.     def initialize (arr) ### input is an array of 81 things in the set [1,2,3,4,5,6,7,8,9,nil]
  29.         if arr.length != 81 then raise "BAD INPUT - length not 81" end
  30.         if arr.uniq - [1,2,3,4,5,6,7,8,9,nil] != [] then raise "BAD INPUT - includes things that arent 1-9 or nil" end
  31.  
  32.         @rows=Array.new;@cols=Array.new; @squares=Array.new
  33.         9.times{ @rows << Array.new; @cols << Array.new; @squares << Array.new}
  34.  
  35.         arr.each_with_index{|anel,i|
  36.             row,col,sq=Sudo.index_to_row_col_sq(i)
  37.             @rows[row] << anel; @cols[col] << anel; @squares[sq] << anel
  38.         }      
  39.     end
  40.     def potential_numbers_at_index(index) #checks the row,square and column of
  41.         row,col,sq=Sudo.index_to_row_col_sq(index)
  42.         [1,2,3,4,5,6,7,8,9]-@rows[row]-@cols[col]-@squares[sq]
  43.     end
  44.     def simple_children
  45.         tochange=@rows.flatten.index(nil) #fill in the first blank
  46.         totry=potential_numbers_at_index(tochange)
  47.        
  48.         totry.collect{|onetotry|
  49.             newarr=@rows.flatten; newarr[tochange]=onetotry
  50.             Sudo.new(newarr)
  51.         }
  52.     end
  53.     def solutions
  54.         poss=[self]
  55.         @rows.flatten.count(nil).times{|i| ### for every unsolved number
  56.             nextset=[]
  57.             poss.each{|aposs| nextset+=aposs.simple_children}
  58.             poss=nextset
  59.         }
  60.         poss
  61.     end
  62. end
  63.  
  64. # asquare=Sudo.new [nil, nil, 3,   nil, 2,   nil, 6,   nil, nil,
  65. #                 9  , nil, nil, 3,   nil, 5,   nil, nil, 1,
  66. #                 nil, nil, 1,   8,   nil, 6,   4,   nil, nil,
  67.  
  68. #                 nil, nil, 8,   1,   nil, 2,   9,   nil, nil,
  69. #                 7  , nil, nil, nil, nil, nil, nil, nil, 8,
  70. #                 nil, nil, 6,   7,   nil, 8,   2,   nil, nil,
  71.  
  72. #                 nil, nil, 2,   6,   nil, 9,   5,   nil, nil,
  73. #                 8  , nil, nil, 2,   nil, 3,   nil, nil, 9,
  74. #                 nil, nil, 5,   nil ,1,   nil, 3,   nil, nil,
  75. # ]
  76.  
  77. # z=Time.now
  78. # asquare.solutions
  79. # p Time.now-z #0.0625 seconds
  80.  
  81. # asquare.solutions[0].rows.each{|arow| p arow}
  82.  
  83.  
  84. # [4, 8, 3, 9, 2, 1, 6, 5, 7]
  85. # [9, 6, 7, 3, 4, 5, 8, 2, 1]
  86. # [2, 5, 1, 8, 7, 6, 4, 9, 3]
  87. # [5, 4, 8, 1, 3, 2, 9, 7, 6]
  88. # [7, 2, 9, 5, 6, 4, 1, 3, 8]
  89. # [1, 3, 6, 7, 9, 8, 2, 4, 5]
  90. # [3, 7, 2, 6, 8, 9, 5, 1, 4]
  91. # [8, 1, 4, 2, 5, 3, 7, 6, 9]
  92. # [6, 9, 5, 4, 1, 7, 3, 8, 2]
  93.  
  94.  
  95. # exit
  96.  
  97. ############################################################# SOME 'NICE TO HAVE's
  98.  
  99. class Sudo
  100.     def self.fromtext(string)
  101.         newstring=string.gsub(/\s/,"")
  102.         newarr=[]
  103.         newstring.each_char{|a| if a=="0" then newarr << nil else newarr << a.to_i end}
  104.         self.new(newarr)
  105.     end
  106.  
  107.     def showsolutions
  108.         timeatstart=Time.now
  109.         allsol=self.solutions
  110.         timeatend=Time.now
  111.         if allsol.empty? then puts "NO SOLUTIONS" end
  112.         self.solutions.each_with_index{|asol,i|
  113.             puts
  114.             puts "SOLUTION: "+(i+1).inspect+" of "+allsol.length.inspect
  115.             asol.showit
  116.         }
  117.         p "TIME TO SOLVE: "+(timeatend-timeatstart).inspect+" seconds"
  118.     end
  119.     def showit
  120.         self.rows.each_with_index{|arow,index|
  121.             arow.each_with_index{|abox,i| print abox; if i==2 or i==5 then print "|" end };puts
  122.             # puts arow[0..2].inspect+"|"+arow[3..5].inspect+"|"+arow[6..8].inspect
  123.             if index==2 or index==5 then
  124.                 puts "---+---+---"
  125.             end
  126.         }
  127.  
  128.        
  129.     end
  130. end
  131.  
  132. #### EXAMPLES FROM http://projecteuler.net/project/sudoku.txt
  133.  
  134. ### Grid 01
  135. # Sudo.fromtext("003020600
  136. # 900305001
  137. # 001806400
  138. # 008102900
  139. # 700000008
  140. # 006708200
  141. # 002609500
  142. # 800203009
  143. # 005010300").showsolutions #0.078125 seconds
  144.  
  145. ### Grid 25
  146. # Sudo.fromtext("360020089
  147. # 000361000
  148. # 000000000
  149. # 803000602
  150. # 400603007
  151. # 607000108
  152. # 000000000
  153. # 000418000
  154. # 970030014").showsolutions #0.578125 seconds
  155.  
  156.  
  157. ### Grid 50
  158. # Sudo.fromtext("300200000
  159. # 000107000
  160. # 706030500
  161. # 070009080
  162. # 900020004
  163. # 010800050
  164. # 009040301
  165. # 000702000
  166. # 000008006").showsolutions #8.078125 seconds
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement