Объединить все n элементов в массиве - PullRequest
0 голосов
/ 22 декабря 2018

Я пытаюсь решить следующую загадку Ruby на CodeWars:

Напишите функцию с именем merge_every, которая принимает 3 аргумента: 2 массива и число, которое указывает количество элементов для вставкивторой массив элементов в первый.Третий аргумент является необязательным и должен иметь значение по умолчанию 4.

. Думайте о нем, как о массиве обычных событий и массиве избранных событий, и вы хотите объединить их, чтобы получить массив событий.с признаком, показывающим каждые, скажем, 3 элемента.

event_ids = [1, 2, 3, 4, 5, 6, 7]
featured_event_ids = [10, 11]
merge_every(event_ids, featured_event_ids, 3)
# => [1, 2, 3, 10, 4, 5, 6, 11, 7]

Если первый массив должен завершиться до второго, оставшаяся часть второго удаляется.Принимая во внимание, что если второе заканчивается перед первым, весь первый массив должен быть сохранен.Если значение равно 0 или меньше, никакие элементы не должны быть вставлены, и если целевой массив пуст, то должен быть возвращен пустой массив.

Дополнительные примеры

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
letters = ['a', 'b', 'c', 'd']
merge_every(numbers, letters)
# => [1, 2, 3, 4, 'a', 5, 6, 7, 8, 'b', 9, 10]

merge_every(letters, numbers)
# => ['a', 'b', 'c', 'd']

merge_every(letters, numbers, 2)
# => ['a', 'b', 1, 'c', 'd']

Мое решениеэто:

def merge_every(target, source, count=4)

  count == 0 ? number_of_source_in_target = 0 : number_of_source_in_target = target.count / count
  insertion_number = count
  source_number = 0

    if insertion_number == 0 || source.count == 0 || number_of_source_in_target <= 1
        target
    elsif target.count % insertion_number == 0
      number_of_source_in_target -= 1
      while source_number < number_of_source_in_target && source_number < source.count do
        modulo_0_return = target.insert(insertion_number, source[source_number])
        insertion_number += (count + 1)
        source_number += 1
      end
      modulo_0_return
    else
      while source_number < number_of_source_in_target && source_number < source.count do
          modulo_numbers_return = target.insert(insertion_number, source[source_number])
          insertion_number += (count + 1)
          source_number += 1
      end
      modulo_numbers_return
    end
end

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
letters = ['a', 'b', 'c', 'd']
print merge_every(numbers, letters, 3)

Когда я запускаю свой код на своем компьютере, я получаю правильный ответ, но на веб-сайте CodeWars их средство проверки выдает другой вывод.Различия происходят с:

merge_every(numbers, letters, 3)
# My Terminal: [1, 2, 3, 'a', 4, 5, 6, 'b', 7, 8, 9, 'c', 10]
# CodeWars "checker": [1, 2, 3, "a", 4, "a", 5, "b", 6, 7, 8, "c", "b", 9, 10]

merge_every(numbers, letters, 1)
# My Terminal: [1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 6, 7, 8, 9, 10]
# CodeWars "checker": [1, "a", 2, "b", 3, "c", "a", "d", 4, "a", 5, "b", 6, 7, 8, "c", "b", 9, 10]

Я не могу понять, почему.Может ли кто-нибудь помочь мне выяснить это несоответствие?

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

Это опция, использующая встроенные функции Enumerable#each_slice, может быть, вы также можете проверить в Codewar, чтобы увидеть, есть ли какая-то проблема:

n = 3
event_ids.each_slice(n).zip(featured_event_ids).flatten.compact
#=> [1, 2, 3, "a", 4, 5, 6, "b", 7]

Возможно, проверить, как это работаетмогу дать подсказку.Чтобы избежать этого результата, необходимо добавить условие, например, с n=6:

#=> [1, 2, 3, 4, 5, 6, "a", 7, "b"]
0 голосов
/ 23 декабря 2018

Если ваш код проходит ваши тесты, но не CodeWar, наиболее вероятным объяснением является то, что ваши тесты неверны или, что более вероятно, неполны.

Вот один из Ruby-подобных способов выполнения вставок.

def insert_em(arr, insertions, after_every = 4)
  return arr if after_every <= 0
  enum_arr = arr.to_enum
  isize = insertions.size
  arr.size.times.with_object([]) do |i,a|
    a << enum_arr.next
    a << insertions[i/after_every] if
      i <= after_every*isize && ((i+1) % after_every).zero?
  end
end

arr = (1..10).to_a

insert_em(arr, [:a, :b, :c],  -1)
  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
insert_em(arr, [:a, :b, :c],  0)
  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
insert_em(arr, [:a, :b, :c],  1)
  #=> [1, :a, 2, :b, 3, :c, 4, 5, 6, 7, 8, 9, 10]
insert_em(arr, [:a, :b, :c],  2)
  #=> [1, 2, :a, 3, 4, :b, 5, 6, :c, 7, 8, 9, 10]
insert_em(arr, [:a, :b, :c],  4)
  #=> [1, 2, 3, 4, :a, 5, 6, 7, 8, :b, 9, 10]
insert_em(arr, [:a, :b, :c],  5)
  #=> [1, 2, 3, 4, 5, :a, 6, 7, 8, 9, 10, :b]
insert_em(arr, [:a, :b, :c], 11)
  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
insert_em(arr, [])
  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
insert_em([], [:a, :b, :c])
  #=> []
insert_em([], [])
  #=> []
0 голосов
/ 22 декабря 2018

Я не уверен, что делают войны кода, но может случиться так, что он запускает ваш метод более одного раза.Одна из вещей, которую делает ваш код, - это изменение массива target, так что если вы сделаете ..

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
letters = ['a', 'b', 'c', 'd']
merge_every(numbers, letters, 3)
=> [1, 2, 3, 'a', 4, 5, 6, 'b', 7, 8, 9, 'c', 10]

Но тогда, если вы проверите numbers, вы увидите, что они изменились ...

p numbers
=> [1, 2, 3, 'a', 4, 5, 6, 'b', 7, 8, 9, 'c', 10]

Таким образом, ваш массив чисел изменяется, и каждый раз, когда вы запускаете merge_every с одним и тем же входным объектом, вы получаете другой результат (и снова мутируете массив numbers)

Выможет попытаться убедиться, что вы выполняете свой код на дубликате (копии) массива, а не на самом массиве ... массив, который выглядит так же, но это другой объект.Таким образом, когда код изменяет target, исходный входной массив не изменяется.

def merge_every(target, source, count=4)
  target = target.dup
  ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...