def last_person_standing(arr)
(arr.size-1).times.reduce(arr) { |a,_| a << a.shift(2).last }.first
end
Далее следуют несколько пунктов.
- Если массив содержит
n
элементов, то существует n-1
шагов, при этом один элемент массива удаляется на каждом шаге; - с помощью Enumerable # уменьшать (он же
inject
) нет необходимости добавлять строку в конце, чтобы вернуть желаемое значение; - , чтобы избежать мутации
arr
replace *Аргумент 1015 * (arr
) с arr.dup
; a << a.shift(2).last
удаляет первые два элемента массива a
и добавляет второй из них в конец a
; - Я прикрепил
.first
к концу рабочей строки, чтобы вернуть оставшийся элемент, а не массив, содержащий этот единственный элемент, поскольку это кажется более полезным;и - код должен быть добавлен, чтобы справиться со случаями, когда
arr.size < 2
.
Давайте попробуем.
last_person_standing %w| Agnes Billy-Bob Trixy Bubba Wanda |
#=> "Billy-Bob"
Далее следуют другие примеры.
(2..10).each do |n|
a = [*1..n]
puts "#{ a }: #{ last_person_standing(a) }"
end
печатает
[1, 2]: 2
[1, 2, 3]: 2
[1, 2, 3, 4]: 4
[1, 2, 3, 4, 5]: 2
[1, 2, 3, 4, 5, 6]: 4
[1, 2, 3, 4, 5, 6, 7]: 6
[1, 2, 3, 4, 5, 6, 7, 8]: 8
[1, 2, 3, 4, 5, 6, 7, 8, 9]: 2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: 4
Вот еще один способ.
def last_person_standing(arr)
while arr.size > 1
odd = arr.size.odd?
arr.pop if odd
arr.delete_if.with_index { |_,i| i.even? }
arr.unshift(nil) if odd
end
arr.first
end
Если после каждого раунда удалений из arr
, если arr.size
нечетно, выскочитьпоследний элемент arr
, удалить элементы из arr
с четными индексами и затем unshift
любой объект-заполнитель (я выбрал nil
) в начале arr
(будет удален в следующем цикле);если arr.size
- это просто удалить элементы из arr
с четными индексами.