Last active
February 21, 2017 23:35
-
-
Save galaydaroman/8555d9bff6c8659d37a8444af46b77ef to your computer and use it in GitHub Desktop.
Solution to correct the equations with matches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Matches | |
MATCH_BITS = { | |
' ' => '', | |
'0' => '123567', | |
'1' => '36', | |
'2' => '13457', | |
'3' => '13467', | |
'4' => '2346', | |
'5' => '12467', | |
'6' => '124567', | |
'7' => '136', | |
'8' => '1234567', | |
'9' => '123467', | |
'*' => 'xy', | |
'/' => 'x', | |
'+' => 'xy', | |
'-' => 'x', | |
'=' => 'x' | |
} | |
class Equation | |
attr_reader :input, :strategy, :diff_count | |
def initialize input, strategy:, diff_count: | |
@input = input | |
@strategy = strategy | |
@diff_count = diff_count | |
validate! | |
end | |
def execute | |
input_matches = get_matches_count input | |
expected_matches = expected_count input_matches | |
[].tap do |solutions| | |
operation_types_for(input[1]).each do |operation| | |
digits.each do |a| | |
digits.each do |b| | |
next if b == 0 && operation == '/' | |
result = evaluate a, b, operation | |
next if Float === result | |
result = " #{result}" if input[/(\d+|\-\d)$/].size > result.to_s.size | |
new_input = [a, operation, b, '=', result].join | |
if expected_matches == get_matches_count(new_input) | |
# puts '>> ' + new_input | |
actual_diff = diff_count | |
actual_diff *= 2 if strategy == :move | |
solutions << new_input if changes(new_input) == actual_diff | |
end | |
end | |
end | |
end | |
raise 'Equation solution was not found!' if solutions.empty? | |
end | |
end | |
def changes new_input | |
input.chars.zip(new_input.chars).reduce(0) do |result, (a, b)| | |
bits_a = MATCH_BITS[a].chars | |
bits_b = MATCH_BITS[b].chars | |
added = (bits_b - bits_a).count | |
removed = (bits_a - bits_b).count | |
result += added + removed | |
end | |
end | |
def validate! | |
raise 'Input should be an equation string' unless /\d[+-\/\*]\d=(\d{1,2}|\-\d)/ === input | |
raise 'Stratagy is wrong type' unless %i[add remove move].include? strategy | |
end | |
def evaluate a, b, op | |
if op == '/' | |
res = a.to_f / b | |
res % 1 == 0 ? res.to_i : res | |
else | |
[a, b].reduce &op.to_sym | |
end | |
end | |
def digits | |
(0..9).to_a | |
end | |
def operation_types_for operation | |
/[+-]/ === operation ? %w(+ -) : %w(* /) | |
end | |
def expected_count count | |
case strategy | |
when :add then count + diff_count | |
when :move then count | |
when :remove then count - diff_count | |
end | |
end | |
def get_matches_count input | |
input.chars.reduce(0) do |sum, char| | |
sum += MATCH_BITS[char].size | |
end | |
end | |
end | |
end | |
# equation = Matches::Equation.new '2-7=5', strategy: :add, diff_count: 2 | |
# equation = Matches::Equation.new '7+9=15', strategy: :move, diff_count: 2 | |
# equation = Matches::Equation.new '4*3=85', strategy: :move, diff_count: 2 | |
equation = Matches::Equation.new '7-9=-9', | |
strategy: :add, | |
diff_count: 3 | |
puts equation.execute |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment