-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtchisla.rb
executable file
·77 lines (69 loc) · 2.76 KB
/
tchisla.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#! /usr/bin/env ruby
require 'set'
details = ARGV.delete('--details')
target, k = ARGV[0..1].map(&:to_i)
def facto(a)
(2..a).reduce(1, :*)
end
def square?(a)
return false if a <= 1
r = Math.sqrt(a).round
r.finite? && a == r * r
end
def sqrt(a)
Math.sqrt(a).round
end
class Tchisla
def initialize(target, c, k)
@target = target
@values = [k] * c
@c = c
@viewed = Set.new()
end
def solve(values = @values.dup, concatenation: true, depth: 15,backtrack: [])
return backtrack if values.include?(@target)
return nil if depth < 0
return nil if @viewed.include?(values.sort)
@viewed << values.sort
(0...values.size).each do |i|
(0...values.size).each do |j|
vals = values.dup
a = vals.delete_at([i, j].max)
r = nil
if i != j
b = vals.delete_at([i, j].min)
r ||= solve(vals.dup + [a + b], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{a + b} = #{a} + #{b}"])
r ||= solve(vals.dup + [a * b], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{a * b} = #{a} * #{b}"])
r ||= solve(vals.dup + [a - b], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{a - b} = #{a} - #{b}"])
r ||= solve(vals.dup + [b - a], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{b - a} = #{b} - #{a}"])
r ||= solve(vals.dup + [a ** b], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{a ** b} = #{a}^#{b}"]) if a > 1 && b.abs < 50 && (a**b) < 10 ** 30
r ||= solve(vals.dup + [b ** a], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{b ** a} = #{b}^#{a}"]) if b > 1 && a.abs < 50 && (b**a) < 10 ** 30
r ||= solve(vals.dup + [a / b], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{a / b} = #{a} / #{b}"]) if b != 0 && a % b == 0
r ||= solve(vals.dup + [b / a], concatenation: false, depth: depth, backtrack: backtrack.dup + ["#{b / a} = #{b} / #{a}"]) if a != 0 && b % a == 0
r ||= solve(vals.dup + [(a.to_s + b.to_s).to_i], concatenation: true, depth: depth) if concatenation
end
r ||= solve(vals.dup + [facto(a)], concatenation: false, depth: depth - 1, backtrack: backtrack.dup + ["#{facto(a)} = #{a}!"]) if a < 10 && a > 2
r ||= solve(vals.dup + [sqrt(a)], concatenation: false, depth: depth - 1, backtrack: backtrack.dup + ["#{sqrt(a)} = V(#{a})"]) if square?(a)
return r unless r.nil?
end
end
nil
rescue
end
end
c = 1
sol = nil
while sol.nil?
break if c > 10
solver = Tchisla.new(target, c, k)
sol = solver.solve
unless sol.nil?
puts "#{target} with #{c} #{k}'s:"
break unless details
sol.each do |op|
puts "\t" + op
end
break
end
c += 1
end