I have an array m
of integers. I'm looking for a method to check if the elements of m
are consecutive. Is there a way to test for consecutive numbers?
I came up with this code intended to work when the array length is four:
m.count == 4 && (m.max-m.min) == 3
which incorrectly returns true
for [1,1,1,4]
or [0,0,0,3]
.
For any two consecutive odd numbers, the difference is 2. For example, 3 and 5 are two consecutive odd numbers, their difference = 5 - 3 = 2. For any two consecutive even numbers, the difference is 2. For example, 6 and 8 are two consecutive even numbers, their difference = 8 - 6 = 2.
By using Carl Gauss's clever formula, (n / 2)(first number + last number) = sum, where n is the number of integers, we learned how to add consecutive numbers quickly. We now know that the sum of the pairs in consecutive numbers starting with the first and last numbers is equal.
The natural numbers from 1 to 100 are 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, ...
Enumerable has a really handy method called each_cons
that works like this:
[1,2,3,4].each_cons(2).to_a # => [ [1, 2], [2, 3], [3, 4] ]
That is, it yields each consecutive set of n elements. In our case n is 2.
Of course, as the name implies, it returns an Enumerator, so we can chain it with other Enumerable methods like all?
:
def four_consecutive?(arr)
return false unless arr.size == 4
arr.each_cons(2).all? {|a, b| b == a + 1 }
end
four_consecutive?([2,3,4,5]) # => true
four_consecutive?([2,2,2,5]) # => false
four_consecutive?([1,2,3,4,5]) # => false
This method has the advantage above others that, because all?
short-circuits as soon as the block returns false, it will only test numbers until it finds a pair that don't meet the condition (b == a + 1
). Of course, with only four elements this doesn't really make a difference—unless you're calling this method thousands of times in situation where performance matters.
You can try this:
a == (a.min..a.max).to_a && a.count == 4
This only works when the array is in increasing order. [3, 4, 5, 6]
will pass but [4, 3, 5, 6]
won't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With