2015-10-06 2 views
5

У меня есть массив m целых чисел. Я ищу способ проверить, являются ли элементы m последовательными. Есть ли способ проверить последовательные номера?Проверить для последовательных номеров

Я придумал этот код, предназначенный для работы, когда длина массива четыре:

m.count == 4 && (m.max-m.min) == 3 

который неправильно возвращает true для [1,1,1,4] или [0,0,0,3].

+0

вы хотите '[4,6, 5,7] 'пройти? – illusionist

+0

Простейший возможный ?: 'm.count == 4 && (m.size-1). {| i | m [i + 1] == m [i] + 1} '. –

+0

@illusionist, см. [This Wiki] (https://simple.wikipedia.org/wiki/Consecutive_integer) для определения последовательных целых чисел. Поэтому '[4,6,5,7]' должен возвращать 'false'. –

ответ

4

перечислимых имеет очень удобный метод, называемый each_cons который работает следующим образом:

[1,2,3,4].each_cons(2).to_a # => [ [1, 2], [2, 3], [3, 4] ] 

То есть, она дает каждый последующий набор п элементов. В нашем случае п равно 2.

Конечно, как следует из названия, она возвращает Enumerator, поэтому мы можем приковать его с другими методами перечислимых как 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 

Этот метод имеет то преимущество, выше, потому что all? замыкается, как только блок возвращает false, он будет проверять только числа, пока не найдет пару, которая не соответствует условию (b == a + 1). Конечно, только с четырьмя элементами это действительно не имеет значения - если вы не вызываете этот метод тысячи раз в ситуации, когда имеет значение производительность.

+1

Я забыл поблагодарить вас! – mdalmau

4

Вы можете попробовать это:

a == (a.min..a.max).to_a && a.count == 4 

это работает только, когда массив в порядке возрастания. [3, 4, 5, 6] пройдет, но [4, 3, 5, 6] не будет.

+0

Я думаю, что это не проходит '[4, 3, 5, 6]' – illusionist

+0

@illusionist, который возвращает false, как и следовало ожидать. Однако существует проблема, поскольку 'a = [1,2,3]' возвращает 'истина', даже если' a' не содержит элементов '4'. –

+0

@CarySwoveland отредактирован, чтобы взять 'a.count' в considaration – izaban

2

Ответ основан на математической задаче для Sum of consecutive integers

Sum = n∗(n+1)/2 

Код:

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 

Ориентировочное Объяснение:

enter image description here

+0

Вау! Впечатлительный. Я должен был записать некоторые цифры, чтобы понять это, но определенно работает. Как вы думаете, есть ли другой способ сделать это, не превращаясь в метод? – mdalmau

+3

Как вы говорите, '[4,6,5,7]' возвращает 'true', но это должно быть' false', поскольку элементы не являются последовательными. Кроме того, '[3,4,5]' возвращает 'true', даже если он не содержит элементов' 4'. –

+1

Черт возьми! Самый классный метод – asiniy

3

Если a является массивом и n является требуемым размером:

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 
0

компактным решением, которое я мог придумать выглядят следующим образом:

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 

Выход:

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 
+0

Элементы '[4,6,5,7]' не являются последовательными, поэтому нужно возвращать 'false'. –

+0

, чтобы получить 'sorted_arr.last' вам не нужно сортировать, просто' arr.max' достаточно – illusionist

Смежные вопросы