daily pastebin goal
2%
SHARE
TWEET

Untitled

a guest Mar 14th, 2018 52 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module Rudoku
  2.   class Sudoku
  3.     attr_reader :fields
  4.    
  5.     def initialize
  6.       @fields = Array.new(9 * 9) do |i|
  7.         x = i % 9
  8.         y = i / 9
  9.         Field.new(x, y)
  10.       end
  11.     end
  12.    
  13.     def [](*val) # 1-based
  14.       if val.size == 2 # 2, 3
  15.         x = val[0] - 1
  16.         y = val[1] - 1
  17.       elsif val.size == 1 # B3
  18.         str = val[0].to_s
  19.         x = str[0] - ?A
  20.         y = str[1] - ?1
  21.       else
  22.         return nil
  23.       end
  24.      
  25.       @fields[x + y * 9]
  26.     end
  27.    
  28.     def []=(i, number) # also allows setting of multiple values: s[:B5] = [1, 2, 5]
  29.       self[i].remove((1..9).to_a - number.to_a.flatten)
  30.     end
  31.    
  32.     def solved?
  33.       @fields.all? { |f| f.solved? }
  34.     end
  35.    
  36.     def to_s
  37.       row_strings = (1..9).collect { |i| row_to_s(i) }
  38.       row_strings.join("\n-+-+-+-+-+-+-+-+-\n")
  39.     end
  40.    
  41.     def row(i) # 1-based
  42.       @fields[(9 * (i - 1))..(9 * (i - 1) + 8)]
  43.     end
  44.    
  45.     def column(i) # 1-based
  46.       @fields[(0..8).collect{ |j| 9 * j + i - 1}]
  47.     end
  48.    
  49.     def grid(i) # 1-based
  50.       # TODO
  51.     end
  52.    
  53.     def row_to_s(i)
  54.       (row(i).collect { |f| f.to_s }).join("|")
  55.     end
  56.    
  57.    
  58.     def each_row
  59.       # TODO
  60.     end
  61.    
  62.     def each_column
  63.       # TODO
  64.     end
  65.    
  66.     def each_grid
  67.       # TODO
  68.     end
  69.    
  70.    
  71.     def apply_rule(rule)
  72.       rule.apply_to(self)
  73.     end
  74.   end
  75.  
  76.   class Field
  77.     attr_reader :possibilities, :x, :y
  78.    
  79.     def initialize(x,y)
  80.       @possibilities = (1..9).to_a
  81.       @x = x
  82.       @y = y
  83.     end
  84.    
  85.     def remove(numbers)
  86.       numbers = numbers.to_a.flatten # this works for a single number and for ranges, too
  87.       new_possibilities = @possibilities - numbers
  88.       @possibilities = new_possibilities if (new_possibilities.size >= 1) # fails silently!
  89.     end
  90.    
  91.     def position
  92.       (?A + x).chr + (y + 1).to_s # 2, 3 => B3
  93.     end
  94.    
  95.     def solved?
  96.       @possibilities.size == 1
  97.     end
  98.    
  99.     def to_s
  100.       solved? ? @possibilities[0].to_s : " "
  101.     end
  102.   end
  103.  
  104.   class Rule
  105.     attr_reader :salience
  106.    
  107.     def initialize(salience = 0, &block)
  108.       @logic = block
  109.       @salience = salience
  110.     end
  111.    
  112.     def apply_to(sudoku)
  113.       args_iterate(@logic.arity - 1) do |*args|
  114.         @logic.call(sudoku, *args)
  115.       end
  116.       # applies the rule to the sudoku.
  117.       # iterates over all possible values for all parameters (thats why they're kept in a hash)
  118.     end
  119.    
  120.     protected
  121.       def args_iterate(n) # n: number of arguments
  122.         if n == 0
  123.           yield
  124.         else
  125.           # fill in leftmost parameter, iterate over the remaining argumnents
  126.           args_iterate(n - 1) do |*args|
  127.             ret = false
  128.             (1..9).each do |i|
  129.               ret = yield(i, *args)
  130.               break if ret # breaks out of all
  131.             end
  132.            
  133.             ret # return value has to be passed on to the higher level    
  134.           end
  135.         end      
  136.       end
  137.   end
  138.  
  139.   class Solver
  140.     attr_reader :rules
  141.    
  142.     def initialize(rules)
  143.       @rules = rules
  144.     end
  145.    
  146.     def sort_rules
  147.       @rules = @rules.sort_by { |r| r.salience }.reverse # highest salience first
  148.     end
  149.    
  150.     def solve(sudoku, allow_bruteforce = false)
  151.       # if apply_rules returns true, no bruteforcing is required.
  152.       return true if apply_rules(sudoku)
  153.       return false unless allow_bruteforce
  154.       bruteforce(sudoku)
  155.       return true
  156.     end
  157.    
  158.     def apply_rules(sudoku)
  159.       # iterate over all implemented rules in order of saliency
  160.       # if one is applicable and changes the sudoku, start over
  161.       @rules.each do |rule|
  162.         retry if rule.apply_to(sudoku) # true -> something has changed
  163.       end
  164.      
  165.       sudoku.solved?
  166.     end
  167.    
  168.     def bruteforce(sudoku)
  169.       # TODO
  170.     end
  171.   end
  172. end
  173.  
  174.  
  175.  
  176. include Rudoku
  177.  
  178. =begin RULE BLOCK:
  179. heeft een aantal parameters, de eerste is het sudoku-object
  180. geeft "true" terug als er een aanpassing gebeurd is aan de sudoku
  181. =end
  182.  
  183.  
  184. s = Sudoku.new
  185. r = Rule.new do |s, i, j, k|
  186.   puts i.to_s + "," + j.to_s + "," + k.to_s
  187.   true if i == 3 && j == 5 && k == 2
  188. end
  189.  
  190. r.apply_to(s)
  191.  
  192. # test code
  193. =begin
  194. s = Rudoku::Field.new(2,3)
  195. puts s.position
  196. s.remove(1..9)
  197. puts s.possibilities
  198. s.remove(1..4)
  199. puts s.possibilities
  200. puts s.solved?
  201. s.remove(6..9)
  202. puts s.possibilities
  203. puts s.solved?
  204.  
  205.  
  206. s = Rudoku::Sudoku.new
  207. s[:B5] = [1,2,5]
  208. s[:A1] = 1
  209. s[:A2] = 2
  210. puts s
  211. =end
  212.  
  213. # s.row(3).each do |f|
  214. #   puts f.position
  215. # end
  216.  
  217. # puts s[9, 9].position
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top