问题
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]
.
回答1:
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.
回答2:
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.
回答3:
The Answer is based on mathematical problem for Sum of consecutive integers
Sum = n∗(n+1)/2
Code:
def check_sum_match?(arr)
m = arr.min - 1
n = arr.max
sum1 = arr.inject{|sum, x| sum = sum + x}
sum2 = (n*(n+1) - m*(m+1))/2
sum1 == sum2
end
arr = [5,6,7,8]
if arr.count == 4 && check_sum_match?(arr)
puts 'Yes condition matches'
else
puts 'Invalid Array'
end
# valid arrays are
# [4,6,5,7], [4,5,6,7], etc
Tentative Explanation:
回答4:
If a
is the array and n
is the required size:
def size_and_consecutive?(a, n)
a == (a.first..(a.first+n-1)).to_a
end
size_and_consecutive? [3,4,5,6], 4
#=> true
size_and_consecutive? [4,3,5,6], 4
#=> false
size_and_consecutive? [3,4,5], 4
#=> false
回答5:
A compact solution that I could come up with is as follows:
def consec(arr)
is_of_proper_length = (arr.size == 4)
if(is_of_proper_length)
are_consec = true
arr.each_cons(2) {|x,y| are_consec = false unless ((y - x) == 1)}
end
is_of_proper_length && are_consec
end
Output:
consec([1,2,3,4])
=> true
2.2.0 :051 > consec([0,0,0,0])
=> false
2.2.0 :052 > consec([4,6,5,7])
=> true
2.2.0 :053 > consec([4,5,6,7])
=> true
2.2.0 :054 > consec([5,6,7,8])
=> true
2.2.0 :055 > consec([2,2,2,5])
=> false
2.2.0 :056 > consec([2,3,4,5])
=> true
2.2.0 :057 > consec([1,2,3,4,5])
=> false
来源:https://stackoverflow.com/questions/32973830/check-for-consecutive-numbers