In order not to get rusty I want to refresh my knowledge of pure ruby by solving some algorithms. I can't solve a larger algorithm without solving a smaller one like the example below.
Have the function missing_digit(str) take the str parameter, which will be a simple mathematical formula with three numbers, a single operator (+, -, *, or /) and an equal sign (=) and return the digit that completes the equation. In one of the numbers in the equation, there will be an x character, and your program should determine what digit is missing. For example, if str is "3x + 12 = 46" then your program should output 4.
Examples
Input: "4 - 2 = x"
Output: 2
Input: "1x0 * 12 = 1200"
Output: 0
I think I found the solution for python but I can't find the corresponding Ruby code anywhere.
Python and Ruby are quite similar, though trying to convert this without some basic TDD would have been difficult. Here is the converted to Ruby file from your python example. I would refactor this code but the simple tests here pass, those given in your linked example.
class StringMathX
def self.calculate(str)
exp = str.split()
first_operand = exp[0]
operator = exp[1]
second_operand = exp[2]
resultant = exp[-1]
# If x is present in resultant
if resultant[/x/]
first_operand = first_operand.to_i
second_operand = second_operand.to_i
if operator == '+'
res = first_operand + second_operand
elsif operator == '-'
res = first_operand - second_operand
elsif operator == '*'
res = first_operand * second_operand
else
res = first_operand / second_operand
end
return res
end
# If x in present in operands
# If x in the first operand
if first_operand == 'x'
x = first_operand.to_i
second_operand = second_operand.to_i
if operator == '+'
res = resultant - second_operand
elsif operator == '-'
res = resultant + second_operand
elsif operator == '*'
res = resultant / second_operand
else
res = resultant / second_operand
end
# If x is in the second operand
else
x = second_operand.to_i
first_operand = first_operand.to_i
if operator == '+'
res = resultant-first_operand
elsif operator == '-'
res = first_operand - second_operand
elsif operator == '*'
res = resultant.to_i / first_operand.to_i
else
res = first_operand.to_i / resultant.to_i
end
end
res = res.to_s
k = 0
for i in [*0..x]
if i == x
result = res[k]
break
else
k += 1
end
end
result.to_i
end
end
require 'minitest/autorun'
require_relative '../lib/string_math_x'
class StringMathXTest < Minitest::Test
def test_basic_subtration
input = '4 - 2 = x'
assert(StringMathX.calculate(input) == 2, 'outputs 2')
end
def test_whats_up_returns_doc
input = '1x0 * 12 = 1200'
assert(StringMathX.calculate(input) == 0, 'outputs 0')
end
end
To run this you may need to gem install minitest
Then run ruby test/test.rb
def findx(str)
s = str.sub('=', '==')
i = s.index('x')
pre = s[0,i]
post = s[i+1..-1]
('0'..'9').find { |d| eval(pre+d+post) rescue nil }&.to_i
end
findx("4 - 2 = x") #=> 2
findx("1x0 * 12 = 1200") #=> 0
findx("3**x = 81") #=> 4
findx("1/x == 2.0").nil? #=> true
rescue nil is needed in case division by zero is performed. & is the safe harbor operator. It returns nil, disregarding all that follows, if the part before it returns nil.