Проверьте, увеличивается ли массив целых чисел в Ruby - PullRequest
7 голосов
/ 16 апреля 2011

Я хочу проверить, увеличиваются ли значения массивов после сортировки на 1

Например

[1, 2, 3, 4, 5] = TRUE
[1, 2, 8, 9, 10] = FALSE

Любые предложения приветствуются

Ответы [ 10 ]

35 голосов
/ 16 апреля 2011
array = [1,2,4,3]
array.sort.each_cons(2).all? { |x,y| y == x + 1 }
5 голосов
/ 16 апреля 2011
def continguous?(arr)
  a = arr.sort
  (a.first..a.last).to_a == a
end

a = [2,1,3,4,5]
p continguous?(a)
#=> true
5 голосов
/ 16 апреля 2011

Попробуйте:

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
3 голосов
/ 16 апреля 2011

Я иду с этим:

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) && (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 указал на недостаток, который есть в последнем тесте выше. Я добавил раздел && для полной проверки, возвращает ли первый тест значение 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) && (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 && ((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 голос
/ 16 апреля 2011

Этот не требует sort.

a = [2, 8, 1, 9, 10]
b = a.dup
x = b.delete(b.min)
nil while b.delete(x+=1)
b.empty?
0 голосов
/ 26 мая 2017

Попробуйте это

def increase_by_one?(array)
  temp = array.first
  array.each_with_index do |val, index|
   return false unless temp == val-index
  end
  true 
end
0 голосов
/ 20 ноября 2014
a = [1,2,3,4,5]
a[a.size-1] == a[0] + a.size-1
TRUE
0 голосов
/ 21 октября 2012

Короткий и эффективный метод

sort не требуется, и сравнение прерывается в первом контрпримере.

def increase_by? (array, step)
    yes = true
    array.reduce { |l, r| break unless yes &= ( l+step == r ); l }
    yes
end
0 голосов
/ 16 апреля 2011
class Array
  def increase_by?(n)
    y = nil
    self.each {|x| return false if y && ((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
0 голосов
/ 16 апреля 2011

Если разница между a[i+1] и a[i] не равна 1, то очевидно, что они не в порядке возрастания увеличиваются на 1 или не увеличиваются вообще в порядке возрастания (без учета двух элементов в массиве) равны). Запустите цикл от нуля до длины массива минус 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...