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.
CodePudding user response:
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.
string_math_x.rb
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
./test/test.rb
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
CodePudding user response:
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
.