Закрой нули в списке


41

Вдохновленный этим ТАКИМ вопросом

В качестве входных данных вам будет дан непустой список целых чисел, где первое значение гарантированно будет ненулевым. Чтобы построить вывод, перейдите от начала списка, выводя каждое ненулевое значение по пути. Когда вы встретите ноль, вместо этого повторите значение, которое вы недавно добавили в вывод.

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

Самый короткий код в байтах побеждает.

Тестовые случаи

[1, 0, 2, 0, 7, 7, 7, 0, 5, 0, 0, 0, 9] -> [1, 1, 2, 2, 7, 7, 7, 7, 5, 5, 5, 5, 9]
[1, 0, 0, 0, 0, 0] -> [1, 1, 1, 1, 1, 1]
[-1, 0, 5, 0, 0, -7] -> [-1, -1, 5, 5, 5, -7]
[23, 0, 0, -42, 0, 0, 0] -> [23, 23, 23, -42, -42, -42, -42]
[1, 2, 3, 4] -> [1, 2, 3, 4]
[-1234] -> [-1234]

21
Немного мелочей: эта операция в мире статистики называется LOCF (последнее наблюдение перенесено).
Алекс А.

Что произойдет, если вход был [0,0]?
Критиси Литос

4
@ KριτικσιΛίθος "... где первое значение гарантированно не равно нулю"
Sp3000

Что делать, если вход [1,01]? Используя ответ Исаака Пита, сравните это и это .
Арктур

@Eridan 01не является допустимым целым числом во входных данных Pyth, поэтому isaac не должен это учитывать. Другие ответы могут принимать входные данные, если они этого хотят, только до тех пор, пока они непротиворечивы (например, как ответ Исаака никогда не выдаст этот список в качестве выходных данных)
FryAmTheEggman

Ответы:


19

Pyth, 6 байт

mJ|dJQ

демонстрация

m ... Qозначает, что это отображает функцию на входе. Функция привязывается является J|dJ. Это означает J = d or Jв Python, поскольку Jпри первом использовании присваивается следующее значение: В отличие от Python, выражения присваивания возвращают значение, назначенное в Pyth, поэтому карта возвращает каждое последующее значение по Jжеланию.


23

Желе неконкурентоспособное

3 байта Этот ответ не является конкурирующим, поскольку он использует функции, которые устарели.

o@\

Попробуйте онлайн!

Как это работает

o      Take the logical OR of its arguments.
 @     Reverse the argument order of the link to the left.
  \    Do a cumulative reduce, using the link to the left.

6
Мой мозг не может постичь ... Деннис наконец-то нашел способ навсегда поиграть в гольф с нами. Как он не сделал уже. Add_ಠ
Аддисон Крамп

1
Объяснение больше не соответствует программе
Quintopia

18

Рубин, 25 байт

->a{a.map{|x|x==0?a:a=x}}

Это на самом деле действительно зло.

В частности, фрагмент x==0 ? a : (a=x).

Если бы я использовал любое другое имя переменной для a(предыдущее ненулевое значение) - скажем, - я yдолжен был бы объявить его вне map(потому y=xчто имел бы только область внутри этой единственной mapитерации). Это будет использовать четыре символа больше ( y=0;).

Но если я использую имя переменной a... да, вы догадались. Я фактически переназначаю аргумент, который мы получили в качестве входных данных (исходный массив).

mapне волнует, потому что он заботится только о первоначальной ценности того, к чему он призван, так что это на самом деле работает.


17

Haskell, 21 байт

a%0=a
a%b=b
scanl1(%)

Созданная нами (анонимная) функция находится в последней строке. Первые две строки определяют вспомогательную функцию.

scanl1(%) [1,0,2,0,7,7,7,0,5,0,0,0,9]
[1,1,2,2,7,7,7,7,5,5,5,5,9]

Двоичная функция %выводит второй аргумент, если это не так 0, и в этом случае она выводит первый аргумент. scanl1выполняет итерации этой функции по списку ввода, выводя результат на каждом шаге.


13

J, 8 байт

{:@-.&0\

Это унарная функция, вызываемая следующим образом.

   f =: {:@-.&0\
   f 2 0 0 4 0 _1 0
2 2 2 4 4 _1 _1

объяснение

{:@-.&0\
       \  Map over non-empty prefixes:
   -.      remove all occurrences
     &0    of the number 0 and
{:@        take the last element.

Можете ли вы повторить по абсолютному значению вместо удаления 0?
lirtosiast

@ThomasKwa Это была моя первая попытка. Это {:@(#~|)\так на один байт длиннее.
Згарб

13

Сед, 8

/^0$/g
h
  • /^0$/соответствует нулю в строке - если это так, gкопирует пространство удержания в пространство шаблона
  • h копирует пространство образца в пространство удержания

Целые числа разделены новой строкой. например:

$ printf -- "-1\n0\n5\n0\n0\n7\n" | sed -f zerocover.sed
-1
-1
5
5
5
7
$ 

11

Javascript ES6, 19 байт

s=>s.map(i=>p=i||p)

Простое решение, переберите ввод, присвойте pтекущему элементу iили pесли iесть 0и выведите его.

Пример выполнения (назначение анонимной функции f):

>> f([1, 0, 2, 0, 7, 7, 7, 0, 5, 0, 0, 0, 9])
<< Array [1, 1, 2, 2, 7, 7, 7, 7, 5, 5, 5, 5, 9]

Всякий раз, когда я запускаю это, я получаю сообщение об ошибке «не могу найти переменную p»
Downgoat

@Downgoat Это потому, что переводчик является только в строгом режиме. Если вы не запускаете этот код в строгом режиме, он должен работать.
wizzwizz4

@ wizzwizz4 ооо, г хорошо
Downgoat

1
@ wizzwizz4 Строгий режим глупый.
SuperJedi224

1
@ SuperJedi224 Это не глупо. Это очень полезно; он гарантирует, что ваш код не является двусмысленным, и будет работать даже с серьезным обновлением, и не будет использовать неопределенное поведение и т. д. Но глупо то, что он включен по умолчанию, так как в строгом режиме не указывается способ его отключения. и если вы не поместите строку строгого режима в начале, вы не захотите этого и / или играете в код.
wizzwizz4


7

Dyalog APL, 12 10 9 байтов

(⊃0~⍨,⍨)\

Вдохновленный ответом @ Zgarb's J.

(⊃0~⍨,⍨)\      Monadic function:
        \      Cumulative reduce by
(⊃0~⍨,⍨)       the dyadic function:
     ,⍨           Arguments concatenated in reverse order
  0~⍨             With zeroes removed
 ⊃                Take the first element

Попробуй это здесь .


6

Pyth, 8 байт

t.u|YNQ0

Использует .u(кумулятивное уменьшение) на |(Python or), с базовым регистром 0.


@isaacg Кажется, что .uэто дольше, даже если Jи Kсвязаны. Это когда-нибудь оптимально?
lirtosiast

Это было (по крайней мере, afaik) здесь . Обычно это помогает, когда вы хотите получить все результаты по какой-либо причине.
FryAmTheEggman

5

Python 2, 29 байт

while 1:x=input()or x;print x

Принимает данные в виде чисел, заданных по одному на строку, и выводит их в том же формате. Завершается с ошибкой после окончания.

Используя короткое замыкание or, переменная xобновляется на входе, если только этот вход не равен 0 (что является Falsey), и в этом случае он остается его текущим значением. Затем xпечатается. Обратите внимание, что, поскольку первое значение списка ненулевое, xоно не оценивается в правой части, прежде чем оно будет присвоено.


Это 6 байт в Pyth, и он подавляет ошибку:#\nJ|EJ
isaacg

5

Mathematica 38 байт

Сопоставление ...a,0,...с образцом многократно заменяется на...a,a...

#//.{b___,a_/;a!=0,0,e___}:>{b,a,a,e}&

5

Матлаб, 41 46 байт

Это вдохновлено моим первоначальным ответом со следующими отличиями:

  1. Используйте логическое индексирование вместо nonzeros .
  2. Двойное логическое отрицание вместо сравнения с 0 .
  3. Транспонирование может быть удалено, поскольку выходной формат гибкий
  4. Удаление промежуточной переменной.

Спасибо Тому Карпентеру за пункт 4 и за его предложение использовать программу вместо функции; вместе они позволили уменьшить 5 байтов.

x=input('');u=x(~~x);disp(u(cumsum(~~x)))

Пример:

>> x=input('');u=x(~~x);disp(u(cumsum(~~x)))
[4 0 3 2 0 5 6 0]
     4     4     3     2     2     5     6     6

Вы можете сохранить один байт, преобразовав его в программу - используйте x=input('')вместо объявления функции и disp(u(t)вместоy= бита. Кроме того, вы можете сохранить еще четыре байта, избавившись от tпеременной, получив x=input('');u=x(~~x);disp(u(cumsum(~~x)))41
Том Карпентер,

@ TomCarpenter Большое спасибо! Отредактировано
Луис Мендо

У меня нет Matlab, но @(x)x(~~x)(cumsum(~~x))работает в Октаве.
алефальфа

@alephalpha Matlab не разрешает повторное индексирование.
AlexR


5

Japt 8 7 байт

N£U=XªU

Довольно просто Принимает ввод через запятую. Попробуйте онлайн!

Неуправляемый и объяснение

N£    U=Xª U
NmXYZ{U=X||U

        // Implicit: N = input, U = first item
NmXYZ{  // Map each item X to:
U=Z||U  //  Set U to (X || U) and return.
        //  If X is non-zero, this sets U to X.
        //  Otherwise, this leaves U as the last non-zero we've encountered.
        // Implicit: output last expression

Неконкурентная 4-байтовая версия: ( åкоманда и !-auto-function добавлены после вызова)

Nå!ª

Объяснение:

Nå!ª
Nå!||
NåXY{Y||X}

        // Implicit: N = input, U = first item
NåXY{   // Cumulatively reduce N; take each item Y and prev value X,
Y||X}   //  and return Y if it is non-zero; return X otherwise.
        // Implicit: output last expression

Попробуйте онлайн!


Подожди, ªскорее ИЛИ, чем º? Есть ºи случайно?
caird coinheringaahing

@cairdcoinheringaahing Нет, ºесть ((. Они были назначены по значению Unicode, так как я нашел в них необходимость: P ªnd и ºr гениальны, хотя, я мог бы использовать это для Japt 2.0 ...
ETHproductions

5

Ява, 78

int[]f(int[]a){for(int i=-1,b=i;++i<a.length;a[i]=b=a[i]==0?b:a[i]);return a;}

Здесь мы просто следим за последними ненулевыми значениями и добавляем их в случае необходимости. Похоже, очевидный способ сделать это.


5

Пролог (SWI) , 54 байта

[X,0|T]+[X,X|Y]:-[X|T]+[X|Y].
[X|T]+[X|Y]:-T+Y.
[]+[].

Попробуйте онлайн!

объяснение

Я действительно счастлив с этим ответом.

Сначала мы говорим, что пустой список - это решение пустого списка:

[]+[].

Тогда мы говорим, что [X,X|Y]это решение [X,0|T], если путем удаления второй записи каждого из оставшихся решений.

[X,0|T]+[X,X|Y]:-[X|T]+[X|Y].

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

Если это объяснение не работает для вас, вот код, переведенный на Haskell:

g(a:0:x)=a:g(a:x)
g(a:x)=a:g x
g x=x

Попробуйте онлайн!


Очень лаконично! Мне нравится, как некоторые функциональные и логические языки программирования позволяют вам делать такой буквальный перевод правил. Это такой естественный способ написать это!
ThePlasmaRailgun

4

GolfScript, 10 байт

~{1$or}*]`

Эта программа принимает входные данные из stdin в форме литерала массива GolfScript (например, [1 0 2 0]) и записывает свои выходные данные в стандартный вывод (например, [1 1 2 2]).

Попробуйте онлайн.

Функция (принимающая и возвращающая массив GolfScript) будет на три байта длиннее из-за необходимости обернуть ее в блок и назначить ее символу:

{[{1$or}*]}:f

Конечно, если подсчитывается только тело функции (то есть [{1$or}*]), то я могу фактически сохранить один байт по сравнению с автономной программой.


Возможно, неудивительно, что новая, более короткая версия оказалась очень похожей на запись Денниса CJam . Он выигрывает на один байт, потому что GolfScript считывает ввод автоматически, и поэтому для этого не требуется дополнительная команда.
Илмари Каронен

4

Минколанг 0,14 , 12 10 байт

$I?.nd?xdN

Попробуй это здесь. Ввод может быть дан как в вопросе, но без скобок .

объяснение

$I      Push the length of the input on the stack.
  ?.    If this is 0, stop. Otherwise, continue.

nd        Take number from input and duplicate it.
  ?x      If this number is 0, dump the top of stack.
    dN    Duplicate the top of stack and output as number

Минколанг тороидален, поэтому он вращается вокруг начала и продолжает движение, пока не достигнет .и не остановится.


4

𝔼𝕊𝕄𝕚𝕟, 7 символов / 12 байтов

ïⓜa=$⋎a

Try it here (Firefox only).

объяснение

        // implicit: ï = input array
ïⓜ     // map over input
  a=    // set a to:
    $   // (if element is truthy (not 0)) element itself
     ⋎a // else whatever a was set to before
        // implicit output

4

O , 31 байт

[[I',T%T/]{n#}d]{n.{:V}{;V}?}d]

Это берет вход, разделенный ,и выводит тот же список в [].

7,0,3,0,0,2,-50,0,0 => [7,7,3,3,3,2,-50,-50,-50]

Объяснение:

[] Поместить результат в массив
 [I ', T% T /] {n #} d] Форматировать ввод в массив чисел
                {n. {: V} {; V}?} d Заполните нулями (как это работает, смотрите ниже)


17 байт

I~]{n.{:V}{;V}?}d

Вводит в виде списка чисел, разделенных пробелами, используя постфиксную нотацию и может обрабатывать только однозначные шестнадцатеричные числа Негативы с постфиксом _.

5 4 0 0 1 0 0 => 5 4 4 4 1 1 1
A 3 0 0 1 B 0 => 10 3 3 3 1 11 11
67* 0 0 78* 0 => 42 42 42 56 56
67*_ 4 3_ 0 0 => -42 4 -3 -3 -3

Объяснение:

I ~] Помещает ввод в целочисленный массив
   {} d Для каждого числа на входе
    . П {; V}, {: V}? Если число равно 0, нажмите V
                  Если нет, установите V на номер

Вы можете сохранить два байта с помощью I~]{n.{:V}{;V}?}d. Интересно, стоит ли dпросто поместить значение в стек вместо n...
kirbyfan64sos

Ты уверен, что О справится с этим? Я не могу найти способ передать его -42, удовлетворяющий требованию «ваш вывод должен быть приемлемым входом для вашего представления».
manatwork

@manatwork Теперь у меня есть лучшая версия, которая работает -42, но она добавляет скобки вокруг вывода.
фаза

4

R, 39 37 33 байта

function(x)zoo::na.locf(x*(x|NA))

Это безымянная функция, которая принимает вектор и возвращает вектор. Требует установки zooпакета. Обратите внимание, что он не требует zooпривязки к пространству имен, поскольку мы ссылаемся на него напрямую.

Название этой операции в мире статистики - вменение LOCF, где LOCF означает «Последнее наблюдение перенесено». Чтобы сделать это в R, мы можем использоватьna.locf из zooпакета, который заменяет NAзначения последним известным ненулевым NAзначением. Мы просто должны заменить нули на входе NAсначала s.

Для этого мы используем x|NA, который будет, TRUEкогда x != 0и в NAпротивном случае. Если мы умножим это на x, TRUEэлементы будут заменены соответствующими элементами, xи NAs останутся NA, тем самым заменив все нули. Затем это передается, zoo::na.locfчто дает нам именно то, что мы хотим.

Сохранено 4 байта благодаря flodel!


4

Ржавчина, 100 байт

fn f(i:&[i64])->Vec<i64>{let(mut o,mut l)=(i.to_vec(),0);
for x in&mut o{if *x==0{*x=l}else{l=*x}};o}

Наткнулся на этот вызов, подумал, что попробую на моем любимом языке. Попробовал использовать [T]::windows_mut()сначала, прежде чем выяснить, что его не существует . И это могло бы быть на самом деле дольше, чем это. Так или иначе, оказывается, что игра в гольф Rust очень уродлива и очень неконкурентоспособна (особенно со всей этой ужасной эзотерикой!) 1

Новая строка не включена в bytecount; это только там, так что вам не нужно прокручивать вбок. Это не меняет смысла кода.

Ungolfed:

fn cover_zeroes(input: &[i64]) -> Vec<i64> {
    let mut output = input.to_vec();
    let mut last_nonzero = 0;
    for item in &mut output {
        if *item == 0 {
            *item = last_nonzero;
        }
        else {
            last_nonzero = *item;
        }
    }
    output
}

[1] По крайней мере, это не так плохо, как Java.


7
« По крайней мере, это не так плохо, как Java »? Гм ... ;)
Geobits

1
@ Geobits О, верно. Я рассчитывал на то, что вам нужен этот public static void mainшаблон…
Blacklight Shining

3

Млечный Путь 1.2.1 , 33 байта

:y;=<:&{~<?{0b_^;:3≤_;}1-}^<Ω!

Это предполагает, что список целых чисел находится исключительно в стеке.


объяснение

:    : :           :              # duplicate the TOS
 y                                # push the length of the TOS
  ;               ;    ;          # swap the TOS and STOS
   =                              # dump a list to the stack
    < <    <                 <    # rotate the stack leftward
        &{~                }      # while loop
            ?{  _     _ }         # if-else statements
              0     3    1        # push an integer
               b                  # == on the TOS and STOS
                 ^          ^     # pop the TOS without output
                     ≤            # rotate the top N stack elements leftward
                          -       # subtract the TOS from the STOS
                              Ω   # push a list made of the top N stack elements
                               !  # output the TOS

Я уверен, что TOS и STOS означают Top of Stack и Second-to-Top of Stack, верно?
Эддисон Крамп

Да @FlagAsSpam
Зак Гейтс

3

Юлия, 33 байта

g(x,a=0)=[(i!=0&&(a=i);a)for i=x]

Это функция, gкоторая принимает массив и возвращает массив. Мы начинаем временную переменную aв 0. Для каждого элемента iвхода, если iне 0 , то мы относим aк i. Если i0, aне меняется на этой итерации. Мы используем aв качестве значения в этой позиции в выходном массиве.


3

Perl 6 , 21 байт

*.map: {$_=($^a||$_)}

использование:

# store the Whatever lambda as a subroutine
# just so that we don't have to repeat it
my &code = *.map: {$_=($^a||$_)}

say code [1, 0, 2, 0, 7, 7, 7, 0, 5, 0, 0, 0, 9];
# (1 1 2 2 7 7 7 7 5 5 5 5 9)

say [-1, 0, 5, 0, 0, -7].&code;
# (-1 -1 5 5 5 -7)

say ([1, 0, 0, 0, 0, 0],[-1, 0, 5, 0, 0, -7]).map: &code;
# ((1 1 1 1 1 1) (-1 -1 5 5 5 -7))

3

R, 36 байт

function(x)x[cummax(seq(a=x)*(!!x))]

Давайте посмотрим, как это работает, используя x=

c(1, 0, 2, 0, 7, 7, 7, 0, 5, 0, 0, 0, 9)

В качестве примера. Здесь !!xбудет логический (True / False) вектор:

c(T, F, T, F, T, T, T, F, T, F, F, F, T)

Кроме того, seq(a=x)дает вектор индексов, пока x:

c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)

Мы умножаем оба, давая:

c(1, 0, 3, 0, 5, 6, 7, 0, 9, 0, 0, 0, 13)

Мы берем совокупный максимум:

c(1, 1, 3, 3, 5, 6, 7, 7, 9, 9, 9, 9, 13)

Наконец, мы используем этот последний вектор в качестве индексов для извлечения из x:

c(1, 1, 2, 2, 7, 7, 7, 7, 5, 5, 5, 5, 9)


3

Powershell, 32 байта

param($x)$x|%{($t=($_,$t)[!$_])}

$x|%{...}блокирует скрипт для каждого элемента в $x. ($_,$t)является массивом текущего элемента и $t, и [!$_]означает, что мы используем !$_для индексации в массиве. Индекс будет 0(false) для ненулевых элементов и 1(true), когда текущий элемент равен нулю, поэтому $tбудет либо текущий элемент, либо $t. Круглые скобки окружают выражение присваивания, поэтому его значение выводится. Без паратезов это было бы просто «тихим» заданием $t.


@ TimmyD, ты прав, конечно. Я добавил, param($x)что превращает это в программу. Вывод представляет собой набор целых чисел, которые вы можете передать в качестве параметра в программу, например, $a = .\program.ps1 1,2,3,4,0,0,5и затем .\program.ps1 $aработать как положено.
Данко Дурбич

$args|%{($p=($_,$p)[!$_])}- 26 байтов, используя $ args.
TessellatingHeckler

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.