snippetrubyMinor
Parse sentences and calculate mathematical results
Viewed 0 times
parsecalculatesentencesandresultsmathematical
Problem
Content of task:
Given a string of words and numbers. Extract the expression including:
Return the result of the calculation.
Example:
"Panda has 48 apples and loses 4" returns 44
"Jerry has 34 apples and gains 6" returns 40
"loses" and "gains" are the only two words describing operators.
Should be a nice little kata for you :)
Note: No fruit debts nor bitten apples = The numbers are integers and
no negatives
source: codewars.com
I want to optimise so ugly code:
This code nice works(all tests was passed). But I don't want a large number of variables. Maybe have you some advice how to optimise this code? Thank you in advance.
Given a string of words and numbers. Extract the expression including:
- the operator: either addition or subtraction
- the two numbers that we are operating on
Return the result of the calculation.
Example:
"Panda has 48 apples and loses 4" returns 44
"Jerry has 34 apples and gains 6" returns 40
"loses" and "gains" are the only two words describing operators.
Should be a nice little kata for you :)
Note: No fruit debts nor bitten apples = The numbers are integers and
no negatives
source: codewars.com
I want to optimise so ugly code:
def calculate(string)
operator = '-' if string.split(' ').include? 'loses'
operator = '+' if string.split(' ').include? 'gains'
sum = 0
count = 0
n1 = 0
n2 = 0
string.split(' ').map do |s|
if s.to_i != 0 && s.to_i.is_a?(Numeric)
if count == 0
n1 = s.to_i
count += 1
else
n2 = s.to_i
end
end
end
n1.method(operator).(n2)
endThis code nice works(all tests was passed). But I don't want a large number of variables. Maybe have you some advice how to optimise this code? Thank you in advance.
Solution
The problem is that you are manipulating text without using Regular Expressions.
Regular expressions are a tool made specifically for text manipulation (search, delete, replace ... ) and are extremely good at their job.
The over-complication you experience comes from the use loops, conditionals and arithmetic to manipulate strings.
Here is a solution using regular expressions:
First line explanation
This
The output is this list:
Almost what we want, we just need to remove (
So now we have
Second line explanation
We add if we find "gains" else subtract (
We need to find the parts of the string that match a given regex, given that the regex
We must "find all regex matches in ruby", searching Google for such a task lands us on StackOverflow reveals that
This code is more direct than splitting and filtering.
Regular expressions are a tool made specifically for text manipulation (search, delete, replace ... ) and are extremely good at their job.
The over-complication you experience comes from the use loops, conditionals and arithmetic to manipulate strings.
Here is a solution using regular expressions:
def text_calculation(text)
a, b = text.split(/[^0-9]/).reject(&:empty?).map(&:to_i)
text.include?("gains") ? a + b : a - b
endFirst line explanation
text.split(/[^0-9]/)This
splits the text at every character that is not a digit (^ negates and [0-9] means from 0 to 9.The output is this list:
["", "", "", "", "", "", "", "", "", "", "48", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "4"]Almost what we want, we just need to remove (
reject) the empty strings (empty?):.reject(&:empty?)So now we have
["48", "4"] that we must convert to integers before we can do arithmetic on, map applies a function to each item of a list and to_i converts to integer so .map(&:to_i)Second line explanation
We add if we find "gains" else subtract (
condition ? if_true : if_false is the Ternary operator).scanWe need to find the parts of the string that match a given regex, given that the regex
/\d+\ matches all the subsequent strings of digits.We must "find all regex matches in ruby", searching Google for such a task lands us on StackOverflow reveals that
.scan is exactly what we can use. (The second Stack Overflow example is even about searching digits in a string!) def text_calculation(text)
a, b = text.scan(/\d+/).map(&:to_i)
text.include?("gains") ? a + b : a - b
endThis code is more direct than splitting and filtering.
Code Snippets
def text_calculation(text)
a, b = text.split(/[^0-9]/).reject(&:empty?).map(&:to_i)
text.include?("gains") ? a + b : a - b
endtext.split(/[^0-9]/)["", "", "", "", "", "", "", "", "", "", "48", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "4"].reject(&:empty?)def text_calculation(text)
a, b = text.scan(/\d+/).map(&:to_i)
text.include?("gains") ? a + b : a - b
endContext
StackExchange Code Review Q#139863, answer score: 7
Revisions (0)
No revisions yet.