I'm so sorry for the basic question. Studied coding for a month now and I still blank out at data structure questions.
array = [6,2,3,7]
6 cannot be subtracted with something
2 - 6 = -4
3 - 2 = 1
7 - 3 = 4
so 4 is the max difference
CodePudding user response:
The Ruby-like way is to use Enumerable#each_cons, which @Joel has done in his answer. I will present an alternative approach.
Let's create a method max_consecutive_diff
that takes a single argument, an array of integers.
def max_consecutive_diff(arr)
...
end
We should start by dealing with the case where the array arr
is empty or contains a single integer. It appears from your example that the method should only be called when arr
contains at least two elements. You therefore way want to check that at the beginning and raised an exception if arr
contains zero or one element.
def max_consecutive_diff(arr)
raise(ArgumentError, "arr contains fewer than two elements") if arr.size < 2
...
end
In the following I will use the array
arr = [6,2,3,7]
for illustration.
We first need to compute an array of element differences. Suppose we begin by computing an array of the indices of all but the first element of array
: [1,2,3]
. Then we can use Array#map to map those indices to the associated differences:
indices = [1,2,3]
diffs = indices.map { |i| arr[i]-arr[i-1] }
#=> [-4, 1, 4]
There are various ways to compute indices
. Here is one, that uses the class method Array::new:
indices = Array.new(array.size-1) { |i| i 1 }
#=> [1, 2, 3]
Another way is to compute a range of indices:
indices = 1..arr.size-1
#=> 1..3
and then write
diffs = indices.map { |i| arr[i]-arr[i-1] }
#=> [-4, 1, 4]
This does not use, Array#map
, as map
's receiver is a range, not an array. Instead, Ruby sees that this is Enumerable#map). Enumerable
is a module and not a class. As
Range.included_modules
#=> [Enumerable, Kernel]
we see that the class Range
has included the module Enumerable
, so it has access to all of its instance methods. In time you will learn the details of how this works and why it is so useful.
Note that storage requirements are reduced by using a range instead of an array. I believe that most Rubyists would use a range here.
Regardless of how diffs
is computed, the final step is to compute its largest value, using Array#max:
diffs.max
#=> 4
Our method now becomes
def max_consecutive_diff(arr)
raise(ArgumentError, "arr contains fewer than two elements") if arr.size < 2
indices = 1..arr.size-1
diffs = indices.map { |i| arr[i]-arr[i-1] }
return diffs.max
end
We can simplify this by substituting out the variables indices
and diffs
, and removing the keyword return
. We can do the latter because when return
is not present Ruby will return the result of the last calculation made by the method.
def max_consecutive_diff(arr)
raise(ArgumentError, "arr contains fewer than two elements") if arr.size < 2
(1..arr.size-1).map { |i| arr[i]-arr[i-1] }.max
end
It's entirely up to you to decide whether to make these simplifications. That is, it's a question of programming style.
Let's try it.
max_consecutive_diff([])
#=> ArgumentError: arr contains fewer than two elements
max_consecutive_diff([1])
#=> ArgumentError: arr contains fewer than two elements
max_consecutive_diff([1,'cat'])
#=> NoMethodError: undefined method `-' for "cat":String
max_consecutive_diff([1,2])
#=> 1
max_consecutive_diff([2,1])
#=> -1
max_consecutive_diff([1,2,4])
#=> 2
max_consecutive_diff([1,2,5,4,6])
#=> 3
CodePudding user response:
array.each_cons(2).map { |a,b| b-a }.max
https://ruby-doc.org/core-3.1.1/Enumerable.html#method-i-each_cons