find ?
and get
to make these statements correct:
get 24 by 4, 3, 4
get 40 by 6, 5, 2
get ? by 2, 3, 5
where get
is a function with only Elementary Arithmetics.
21
module HappyMath | |
class FullPermutationRepeat | |
include Enumerable | |
def initialize(args, n) | |
@args = args | |
@n = n | |
end | |
def each(&b) | |
_helper = ->(ret, n, args, &b) { | |
if n == 0 | |
yield ret | |
else | |
args.each do |a| | |
_helper.call(ret + [a], n - 1, args, &b) | |
end | |
end | |
} | |
_helper.call([], @n, @args, &b) | |
end | |
end | |
class FullPermutation | |
include Enumerable | |
def initialize(args, n = args.size) | |
@args = args | |
@n = n | |
end | |
def each(&b) | |
_helper = ->(ret, n, args, &b) { | |
if n == 0 | |
yield ret | |
else | |
args.each do |a| | |
_helper.call(ret + [a], n - 1, args - [a], &b) | |
end | |
end | |
} | |
_helper.call([], @n, @args, &b) | |
end | |
end | |
Add = -> { _1 + _2 } | |
Sub = -> { _1 - _2 } | |
Mul = -> { _1 * _2 } | |
Div = -> { _1 / _2 } | |
ElementaryArithmetic = [Add, Sub, Mul, Div] | |
Identity = -> { _2 } | |
Evaluate = ->(a, args, calcs) { | |
[Identity].concat(calcs).zip(args).reduce(nil) { |ret, pair| | |
pair.first.call(ret, a[pair.last]) | |
} | |
} | |
class Solution | |
include Enumerable | |
def initialize(vars, result, functions) | |
@vars = vars | |
@result = result | |
n = @vars.size | |
@args_iterator = FullPermutation.new(n.times.to_a) | |
@calcs_iterator = FullPermutationRepeat.new(functions, n - 1) | |
end | |
def each(&b) | |
@args_iterator.each do |args| | |
@calcs_iterator.each do |calcs| | |
if Evaluate.call(@vars, args, calcs) == @result | |
yield args, calcs | |
end | |
end | |
end | |
end | |
end | |
FindRules = ->(conditions) { | |
->(vars) { | |
conditions.collect(&-> { Solution.new(*_1, ElementaryArithmetic) }) | |
.map(&:to_a).reduce(&:&) | |
.collect(&-> { Evaluate.call(vars, *_1) }) | |
} | |
} | |
end | |
conditions = [] << [[4, 3, 4], 24] << [[6, 5, 2], 40] | |
vars = [2, 3, 5] | |
p HappyMath::FindRules[conditions][vars].uniq |