Advertisement
t_a_w

MathMachine

Apr 15th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 2.53 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. require_relative "../lib/z3"
  4.  
  5. class MathMachine
  6.   def initialize
  7.     @solver = Z3::Solver.new
  8.     @cells     = {}
  9.     @a_source  = {}
  10.     @a_value   = {}
  11.     @b_source  = {}
  12.     @b_value   = {}
  13.     @operation = {}
  14.  
  15.     # First cell is special
  16.     (1..10).each do |i|
  17.       @cells[i] = cell_var(i)
  18.     end
  19.     @solver.assert @cells[1] == 0
  20.  
  21.     (2..10).each do |i|
  22.       @a_value[i], @a_source[i] = operand("a", i)
  23.       @b_value[i], @b_source[i] = operand("b", i)
  24.       if i == 2
  25.         @operation[i] = Z3::Int("op#{i}")
  26.         @solver.assert @operation[i] == 4
  27.         @solver.assert Z3::Implies(@operation[i] == 4, 1 == @cells[i])
  28.       elsif i >= 6
  29.         @operation[i] = operation(i, @cells[i-5])
  30.       else
  31.         @operation[i] = operation(i, 0)
  32.       end
  33.     end
  34.   end
  35.  
  36.   # Just to avoid dumb numbers
  37.   def cell_var(i)
  38.     v = Z3::Int("c#{i}")
  39.     @solver.assert v <= 0x1_0000_0000
  40.     @solver.assert v >= -0x1_0000_0000
  41.     v
  42.   end
  43.  
  44.   def operand(l,i)
  45.     value  = Z3::Int("#{l}#{i}_value")
  46.     source = Z3::Int("#{l}#{i}_source")
  47.     @solver.assert source >= 1
  48.     @solver.assert source < i
  49.     (1...i).each do |j|
  50.       @solver.assert Z3::Implies(source == j, value == @cells[j])
  51.     end
  52.     [value, source]
  53.   end
  54.  
  55.   def operation(i,x)
  56.     operation = Z3::Int("op#{i}")
  57.     @solver.assert operation >= 0
  58.     @solver.assert operation <= 3
  59.     @solver.assert Z3::Implies(operation == 0, (@a_value[i] + @b_value[i]) + x == @cells[i])
  60.     @solver.assert Z3::Implies(operation == 1, (@a_value[i] - @b_value[i]) + x == @cells[i])
  61.     @solver.assert Z3::Implies(operation == 2, (@a_value[i] * @b_value[i]) + x == @cells[i])
  62.     @solver.assert Z3::Implies(operation == 3, (@a_value[i] / @b_value[i]) + x == @cells[i])
  63.     @solver.assert Z3::Implies(operation == 3, @b_value[i] != 0)
  64.     operation
  65.   end
  66.  
  67.   def print_solution!
  68.     puts "Solution:"
  69.     c = @solver.check
  70.     if c == :sat
  71.       m = @solver.model
  72.       (1..10).each do |i|
  73.         print "Cell #{i}: "
  74.         if i != 1
  75.           print "[#{m[@a_source[i]]}] #{m[@a_value[i]]} "
  76.           print "#{ %W[+ - * / **][m[@operation[i]].to_s.to_i] } "
  77.           print "[#{m[@b_source[i]]}] #{m[@b_value[i]]} = "
  78.         end
  79.         puts "#{m[@cells[i]].to_s}"
  80.       end
  81.     else
  82.       puts "* Can't solve the problem (#{c})"
  83.     end
  84.   end
  85.  
  86.   def solve!
  87.     @solver.assert @cells[10] == 1337
  88.     print_solution!
  89.   end
  90. end
  91.  
  92. MathMachine.new.solve!
  93.  
  94. # https://www.sabrefilms.co.uk/revolutionelite/math-machine-basic.php
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement