#ruby #arrays
#ruby #массивы
Вопрос:
Я хочу проверить, увеличиваются ли значения массива после сортировки на 1
Например
[1, 2, 3, 4, 5] = TRUE
[1, 2, 8, 9, 10] = FALSE
Любые предложения приветствуются
Комментарии:
1. Я надеюсь, что нет, учитывая, что я не хожу в школу.
2. IIRC, есть еще один вопрос, который спрашивает, как извлечь списки последовательных элементов из массива.
Ответ №1:
array = [1,2,4,3]
array.sort.each_cons(2).all? { |x,y| y == x 1 }
Комментарии:
1. Благодарим вас за использование
each_cons
в этом примере. Это делает его прекрасным.2. Потрясающе; моя первая встреча с each_cons, и это упрощает эту и другие ситуации … спасибо!
3. Это неверно. Удалите
sort
, иначе он всегда будет возвращать true.
Ответ №2:
Попробуйте это:
def array_increments_by?(step, array)
sorted = array.sort
lastNum = sorted[0]
sorted[1, sorted.count].each do |n|
if lastNum step != n
return false
end
lastNum = n
end
true
end
Использование:
array_increments?(1, [0,1,2,3]) #=> true
array_increments?(2, [0,2,4,6]) #=> true
array_increments?(2, [0,2,4,8]) #=> false
Комментарии:
1. Я думаю, вам нужно ‘lastNum = sorted[0]’ в противном случае ‘array_increments_by? (1, [3,2,1,0])’ сбой.
2. На самом деле, я был близок к этому, я делал то же самое, что и в вашей старой версии, устанавливал мой базовый номер (то есть ваше последнее число) в array [0], а не в предварительно отсортированном массиве. Спасибо!
Ответ №3:
def continguous?(arr)
a = arr.sort
(a.first..a.last).to_a == a
end
a = [2,1,3,4,5]
p continguous?(a)
#=> true
Ответ №4:
Я придерживаюсь этого:
def is_consecutive_array?(ary)
sorted_array = ary.sort
first_element = sorted_array.first
last_element = sorted_array.last
((last_element - first_element) == ary.size - 1) amp;amp; (sorted_array[0].upto(sorted_array[-1]).to_a == sorted_array)
end
is_consecutive_array?([1,2]) # => true
is_consecutive_array?([1,2,3]) # => true
is_consecutive_array?([3,2,1]) # => true
is_consecutive_array?([-1,0,1]) # => true
is_consecutive_array?([1,3]) # => false
is_consecutive_array?([1, 2, 2, 2, 5]) # => false
Это изменение по сравнению с предыдущей версией. Я не был доволен этим, но не мог понять, почему. @sawa указал на недостаток, который есть в последнем тесте выше. Я добавил amp;amp;
раздел, чтобы выполнить исчерпывающую проверку, возвращает ли первый тест true. Общий эффект проявляется в этом тесте:
Benchmark.bm do |_bench|
ary2 = ary[0 .. -3] ary[-1,1]
_bench.report { loops.times {
is_consecutive_array?(ary2)
}}
_bench.report { loops.times {
is_consecutive_array?(ary)
}}
end
# >> user system total real
# >> 2.140000 0.200000 2.340000 ( 2.328039)
# >> 18.430000 0.020000 18.450000 ( 18.442234)
Большинство массивов не будут последовательными и не будут иметь правильной комбинации, чтобы обмануть первый тест. Для тех, кто увеличивается, второй тест должен уловить это.
РЕДАКТИРОВАТЬ: Вот несколько тестов для сравнения различных предложенных методов. Ответы до этого момента времени были сохранены настолько точно, насколько это возможно. Мне пришлось изменить increase_by?
ответ, потому что он исправлял массив и не сортировал. Я не хотел, чтобы это случайно оказало пагубное влияние на другие тесты или дало несправедливое преимущество.
ПРИМЕЧАНИЕ: Я увеличил TIMEOUT_LIMIT, потому что я также увеличил тестовый массив.
require 'benchmark'
require 'timeout'
TIMEOUT_LIMIT = 60 # in seconds
ary = [*(1..10_000)]
loops = 10_000
def is_consecutive_array?(ary)
sorted_array = ary.sort
first_element = sorted_array.first
last_element = sorted_array.last
((last_element - first_element) == ary.size - 1) amp;amp; (sorted_array[0].upto(sorted_array[-1]).to_a == sorted_array)
end
is_consecutive_array?([1,2]) # => true
is_consecutive_array?([1,2,3]) # => true
is_consecutive_array?([3,2,1]) # => true
is_consecutive_array?([-1,0,1]) # => true
is_consecutive_array?([1,3]) # => false
is_consecutive_array?([1, 2, 2, 2, 5]) # => false
def sawa(a)
b = a.dup
x = b.delete(b.min)
nil while b.delete(x =1)
b.empty?
end
sawa([1,2]) # => true
sawa([1,3]) # => false
sawa([1,3,3]) # => false
def array_increments_by?(step, array)
sorted = array.sort
lastNum = sorted[0]
sorted[1, sorted.count].each do |n|
if lastNum step != n
return false
end
lastNum = n
end
true
end
array_increments_by?(1,[1,2]) # => true
array_increments_by?(1,[1,3]) # => false
array_increments_by?(1,[1,3,3]) # => false
def continguous?(arr)
a = arr.sort
(a.first..a.last).to_a == a
end
continguous?([1,2]) # => true
continguous?([1,3]) # => false
continguous?([1,3,3]) # => false
def fgb(array)
array.sort.each_cons(2).all? { |x,y| y == x 1 }
end
fgb([1,2]) # => true
fgb([1,3]) # => false
fgb([1,3,3]) # => false
# changed from a monkey-patch on Array to avoid any unintended side-effects.
def increase_by?(ary, n)
ary.sort # added sort to put on same ground as all other tests
y = nil
ary.each {|x| return false if y amp;amp; ((x-y) != n); y=x}
true
end
increase_by?([1,2],1) # => true
increase_by?([1,3],1) # => false
increase_by?([1,3,3],1) # => false
Benchmark.bm(20) do |_bench|
begin
testname = 'is_consecutive_array?'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { is_consecutive_array?(ary) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
begin
testname = 'sawa'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { sawa(ary) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
begin
testname = 'array_increments_by?'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { array_increments_by?(1, ary) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
begin
testname = 'continguous?'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { continguous?(ary) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
begin
testname = 'fgb'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { fgb(ary) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
begin
testname = 'increase_by?'
status = Timeout::timeout(TIMEOUT_LIMIT) { _bench.report(testname) { loops.times { increase_by?(ary, 1) } } }
rescue Timeout::Error => e
puts "#{testname} timed out"
end
end
И результаты для последовательного массива:
# >> user system total real
# >> is_consecutive_array? 18.470000 0.020000 18.490000 ( 18.476536)
# >> sawa sawa timed out
# >> array_increments_by? 37.070000 0.670000 37.740000 ( 37.734562)
# >> continguous? 18.720000 0.890000 19.610000 ( 19.590057)
# >> fgb fgb timed out
# >> increase_by? 41.510000 0.610000 42.120000 ( 42.090960)
Комментарии:
1. @железный дровосек, это печально для меня. Я уберу из своего ответа часть, в которой упоминается скорость.
2. @ железный дровосек Очевидно, что ваш ответ лучший.
3. @the Tin Man Я только что понял, что ваш ответ будет неверно судить о том, что массив типа
[1, 2, 2, 2, 5]
является последовательным.4. @железный дровосек, твой по-прежнему самый быстрый. Хорошо.
5. Для прерывистых массивов это время сократится до 2 секунд из-за люка. Окончательный тест этого не отражает. Возможно, завтра я обновлю его более полным тестом.
Ответ №5:
Для этого не требуется sort
.
a = [2, 8, 1, 9, 10]
b = a.dup
x = b.delete(b.min)
nil while b.delete(x =1)
b.empty?
Ответ №6:
class Array
def increase_by?(n)
y = nil
self.each {|x| return false if y amp;amp; ((x-y) != n); y=x}
true
end
end
[1, 2, 3, 4, 5].increase_by?(1) # => true
[1, 2, 8, 9, 10].increase_by?(1) # => false
Комментарии:
1. Вы не должны использовать исправление, если это не является абсолютно необходимым.
2. @Jacob: да, я так думаю, это просто так весело =)
3. @Julio: изменение встроенных классов. Обратите внимание, что я добавляю этот метод в класс Array вместо моего собственного класса; практика сравнима с добавлением функций к прототипу объектов JavaScript и не одобряется по уважительным причинам. Мне просто нравится делать это для небольших примеров.
Ответ №7:
Если разница между a[i 1]
и a[i]
не равна 1, то очевидно, что они либо не увеличиваются в порядке возрастания на 1, либо вообще не увеличиваются в порядке возрастания (учитывая, что никакие два элемента в массиве не равны). Запустите цикл от нуля до длины массива минус 1.
Ответ №8:
Короткий и эффективный метод
sort
не требуется, и сравнение прерывается при первом контрпримере.
def increase_by? (array, step)
yes = true
array.reduce { |l, r| break unless yes amp;= ( l step == r ); l }
yes
end
Ответ №9:
a = [1,2,3,4,5]
a[a.size-1] == a[0] a.size-1
TRUE
Комментарии:
1. Это могло бы использовать немного больше объяснений того, что вы на самом деле делаете.
2. Это предполагает, что массив отсортирован и не имеет дубликатов. Это не сработало бы для = [1, 5, 5, 5, 5] например.
Ответ №10:
Попробуйте это
def increase_by_one?(array)
temp = array.first
array.each_with_index do |val, index|
return false unless temp == val-index
end
true
end