KobbyAdarkwa
KobbyAdarkwa

Reputation: 181

Returning the highest and lowest numbers in a string: Ruby

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

Answers (5)

spickermann
spickermann

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

Cary Swoveland
Cary Swoveland

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]

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.

Upvotes: 1

Dream
Dream

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

Sumak
Sumak

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

NM Pennypacker
NM Pennypacker

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

Related Questions