Returning the highest and lowest numbers in a string: Ruby

Viewed 2641

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 
5 Answers

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"

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}"

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

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]

Demo

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.

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.

Related