Reputation: 181
Not sure what I'm doing incorrect but I seem to be getting it woefully wrong.
The question is, you are given a string of space separated numbers, and have to return the highest and lowest number.
Note: All numbers are valid Int32, no need to validate them. There will always be at least one number in the input string. Output string must be two numbers separated by a single space, and highest number is first.
def high_and_low(numbers)
# numbers contains a string of space seperated numbers
#return the highest and lowest number
numbers.minmax { |a, b| a.length <=> b.length }
end
Output:
`high_and_low': undefined method `minmax' for "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6":String
Upvotes: 2
Views: 3237
Reputation: 106812
minmax
is not implemented for a string. You need to split your string into an array first. But note that split
will return an array of strings, not numbers, you will need to translate the strings to integers (to_i
) in the next step.
Because minmax
returns the values in the opposite order than required, you need to rotate the array with reverse
and then just join
those numbers with whitespace for the final result.
numbers = "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"
def high_and_low(numbers)
numbers.split.minmax_by(&:to_i).reverse.join(' ')
end
high_and_low(numbers)
#=> "542 -214"
Upvotes: 12
Reputation: 110675
There is no need to convert the string to an array.
def high_and_low(str)
str.gsub(/-?\d+/).
reduce([-Float::INFINITY, Float::INFINITY]) do |(mx,mn),s|
n = s.to_i
[[mx,n].max, [mn,n].min]
end
end
high_and_low "4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"
#=> [542, -214]
This uses the form of String#gsub that has one argument and no block, so it returns an enumerator that I've chained to Enumerable#reduce (a.k.a. inject
). gsub
therefore merely generates matches of the regular expression /-?\d+/
and performs no substitutions.
Upvotes: 1
Reputation: 11
My solution to this kata
def high_and_low(numbers)
numbers.split.map(&:to_i).minmax.reverse.join(' ')
end
Test.assert_equals(high_and_low("4 5 29 54 4 0 -214 542 -64 1 -3 6 -6"), "542 -214")
#Test Passed: Value == "542 -214"
Some docs about methods: String#split Array#map Array#minmax Array#reverse Array#join
More about Symbol#to_proc
numbers.split.map(&:to_i)
is same as number.split.map { |p| p.to_i }
But "minmax_by(&:to_i)" looks better, for sure I guess.
Upvotes: 0
Reputation: 1051
As you're starting with a String, you must turn it into an Array to cast minmax
on it.
Also, make sure to compare Integers by casting .map(&:to_i)
on the Array; otherwise you'd compare the code-point instead of the numerical value.
def get_maxmin(string)
string.split(' ')
.map(&:to_i)
.minmax
.reverse
.join(' ')
end
Upvotes: 1
Reputation: 6942
How about:
numbers_array = numbers.split(' ')
"#{numbers_array.max} #{numbers_array.min}"
If you're starting with a string of numbers you may have to cast the .to_i
after the call to split.
In that case:
numbers_array = numbers.split(' ').map { |n| n.to_i }
"#{numbers_array.max} #{numbers_array.min}"
Upvotes: 3