Mantenha nonzeros e seus vizinhos


26

Retirado desta pergunta no Stack Overflow. Agradecemos também a @miles e @Dada por sugerirem entradas de teste que abordam alguns casos de canto.

O desafio

Dada uma matriz de valores inteiros, remova todos os zeros que não são flanqueados por algum valor diferente de zero.

De maneira equivalente, uma entrada deve ser mantida se for diferente de zero ou se for um zero imediatamente próximo a um valor diferente de zero.

As entradas mantidas devem manter na saída a ordem em que estavam na entrada.

Exemplo

Dado

[2 0 4 -3 0 0 0 3 0 0 2 0 0]

os valores que devem ser removidos são marcados com um x:

[2 0 4 -3 0 x 0 3 0 0 2 0 x]

e assim a saída deve ser

[2 0 4 -3 0 0 3 0 0 2 0]

Regras

A matriz de entrada pode estar vazia (e a saída também deve estar vazia).

Os formatos de entrada e saída são flexíveis, como de costume: matriz, lista, sequência ou qualquer coisa que seja razoável.

Código de golfe, o menor número possível.

Casos de teste

[2 0 4 -3 0 0 0 3 0 0 2 0 0] -> [2 0 4 -3 0 0 3 0 0 2 0]
[] -> []
[1] -> [1]
[4 3 8 5 -6] -> [4 3 8 5 -6]
[4 3 8 0 5 -6] -> [4 3 8 0 5 -6]
[0] -> []
[0 0] -> []
[0 0 0 0] -> []
[0 0 0 8 0 1 0 0] -> [0 8 0 1 0]
[-5 0 5] -> [-5 0 5]
[50 0] -> [50 0]

Posso usar em _2vez de -2? Muitos idiomas usam esse formato.
Freira vazada

Teremos -0?
Freira vazada

@LeakyNun 1 Sim 2 Não
Luis Mendo

Os números terão zeros à esquerda? Gosta [010 0 0 01 1]?
FryAmTheEggman

@FryAmTheEggman Nope
Luis Mendo

Respostas:


16

JavaScript (ES6), 35 bytes

a=>a.filter((e,i)=>e|a[i-1]|a[i+1])

Também funciona em carros alegóricos para dois bytes extras.


10

Python, 50 bytes

f=lambda l,*p:l and l[:any(l[:2]+p)]+f(l[1:],l[0])

Uma função recursiva que leva uma tupla. Inclui o primeiro elemento se houver um valor diferente de zero entre os dois primeiros ou o valor anterior armazenado da última vez. Em seguida, remove o primeiro elemento e se repete. O elemento anterior é armazenado na lista singleton p, que é compactada automaticamente para listar e começa como vazia (graças a Dennis por 3 bytes com isso).


55 bytes:

lambda l:[t[1]for t in zip([0]+l,l,l[1:]+[0])if any(t)]

Gera todos os pedaços de tamanho 3 da lista, primeiro colocando zeros no início e no final e pega os elementos intermediários daqueles que nem todos são zero.

Uma abordagem iterativa ficou mais longa (58 bytes)

a=0;b,*l=input()
for x in l+[0]:a|b|x and print(b);a,b=b,x

Isso não funciona exatamente porque b,*lprecisa do Python 3, mas o Python 3 inputfornece uma string. A inicialização também é feia. Talvez uma abordagem recursiva semelhante funcione.

Infelizmente, o método de indexação de

lambda l:[x for i,x in enumerate(l)if any(l[i-1:i+2])]

não funciona porque l[-1:2]interpreta -1como o final da lista, não um ponto antes do início.


10

Haskell, 55 48 bytes

h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]]

Exemplo de uso: h [0,0,0,8,0,1,0,0]-> [0,8,0,1,0].

scanrreconstrói a lista de entrada xcom um adicional 0no início e no final. Em cada etapa, combinamos 3 elementos e mantemos o do meio, se houver pelo menos um elemento diferente de zero.

Obrigado @xnor por 7 bytes, alternando de zip3para scanr.


Seria bom fazer isso h x=[snd t|t<-zip3(0:x)x$tail x++[0],(0,0,0)/=t], mas acho que não há uma maneira curta de obter o segundo elemento de uma tupla de três.
Xnor

Acontece mais curto para obter os triplos fora de um scando que um zip3: h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]].
Xnor

8

Matlab, 29 27 bytes

A entrada deve consistir em uma 1*nmatriz (sempre que n=0possível). (Irá gerar um erro para 0*0matrizes.)

@(a)a(conv(a.*a,1:3,'s')>0) 

Convolução é a chave do sucesso.


's'em vez de 'same'<- :-D
Luis Mendo

Esse truque funciona um monte de vezes com builtins =)
flawr

Eu já vi esse truque, mesmo para perguntas que não são de golfe, com a bandeira 'UniformOutpout'(compreensivelmente). Mas eu não sabia sobre este
Luis Mendo

1
Você poderia usar em ~~avez de a.*a?
feersum

2
@feersum O Matlab infelizmente se recusa a envolver logicalmatrizes. Isso geralmente é um problema para os built-ins que não são escritos no próprio Matlab. Caso contrário, as matrizes lógicas se comportam muito como as numerosas. Pode funcionar no pensamento da Oitava, mas não o tenho instalado no momento.
flawr

6

J, 17 14 bytes

#~0<3+/\0,~0,|

Salvou 3 bytes com a ajuda do @ Zgarb.

Uso

   f =: #~0<3+/\0,~0,|
   f 2 0 4 _3 0 0 0 3 0 0 2 0 0
2 0 4 _3 0 0 3 0 0 2 0
   f ''

   f 0 0 0 8 0 1 0 0
0 8 0 1 0

Explicação

#~0<3+/\0,~0,|  Input: array A
             |  Get the absolute value of each in A
           0,   Prepend a 0
        0,~     Append a 0
    3  \        For each subarray of size 3, left to right
     +/           Reduce it using addition to find the sum
  0<            Test if each sum is greater than one
                (Converts positive values to one with zero remaining zero)
#~              Select the values from A using the previous as a mask and return

Experimente aqui.


Iria 0<trabalhar no lugar de 0~:?
Zgarb 09/08/19

@ Zgarb Os infixes do tamanho 3 podem ser positivos ou negativos após o processamento.
milhas

Ah, eu esqueci os valores negativos.
Zgarb 9/08/16

6

MATL , 8 bytes

tg3:Z+g)

Saída é uma sequência com números separados por espaços. Uma matriz vazia na saída é exibida como nada (nem mesmo uma nova linha).

Experimente online! Ou verifique todos os casos de teste .

Explicação

O código converte a entrada no tipo lógico, ou seja, entradas diferentes de zero se tornam true(ou 1) e zero entradas se tornam false(ou 0). Isso é convolvido com o kernel [1 2 3]. Um valor diferente de zero causa um resultado diferente de zero nessa posição e em suas posições vizinhas. A conversão para lógico fornece truevalores que devem ser mantidos; portanto, indexar a entrada com isso produz a saída desejada.

t    % Input array implicitly. Duplicate
g    % Convert to logical: nonzero becomes true, zero becomes false
3:   % Push array [1 2 3]
Z+   % Convolution, keeping size of first input
g    % Convert to logical
)    % Index into original array. Implicitly display

5

Jolf, 14 bytes

Agora que penso nisso, Jolf é o Java das linguagens de golfe. suspiros Experimente aqui.

ψxd||H.nwS.nhS

Explicação

ψxd||H.nwS.nhS
ψxd             filter input over this function
   ||           or with three args
     H           the element
      .nwS       the previous element
          .nhS   or the next element

5

Python 3, 55 bytes

lambda s:[t[1]for t in zip([0]+s,s,s[1:]+[0])if any(t)]

1
Uau. Não sei se você viu a resposta @xnor antes disso, mas você tem exatamente o mesmo código, com a única diferença sendo o nome da lambda. Se você usou o código dele, dê crédito a ele, se não, que coincidência louca!
Theo

Não olhou para o código de ninguém.
RootTwo

3
@ T.Lukin Na verdade, não é incomum criar o mesmo código. Você pode ver isso acontecer no Anarchy Golf, onde o código fica oculto até o prazo final, e várias pessoas convergem para a mesma solução como esta .
Xnor

4

Geléia , 9 bytes

0,0jo3\Tị

Experimente online! ou verifique todos os casos de teste .

Como funciona

0,0jo3\Tị  Main link. Argument: A (array)

0,0        Yield [0, 0].
   j       Join, separating with A. This prepends and appends a 0 to A.
    o3\    Reduce each group of three adjacent integers by logical OR.
       T   Truth; get the indices of all truthy results.
        ị  At-index; retrieve the elements of A at those indices.

4

Perl, 34 + 1 ( -psinalizador) = 35 bytes

s/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo

Precisa de sinalizador -p para executar. Leva uma lista de número como imput. Por exemplo :

perl -pe 's/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo' <<< "0 0 0 8 0 1 0 0
0 0 0
-5 0 5"

Eu recebo 5se eu inserir 50 0.
feersum

@feersum corrigido, obrigado
Dada

4

Haskell, 48 bytes

p%(h:t)=[h|any(/=0)$p:h:take 1t]++h%t
p%e=e
(0%)

Examina o elemento anterior p, o primeiro elemento he o elemento depois (se houver) e se algum for diferente de zero, precede o primeiro elemento h.

A condição any(/=0)$p:h:take 1té longa, em particular a take 1t. Vou procurar uma maneira de reduzi-lo, talvez por correspondência de padrões.


4

Retina , 42 35 33 bytes

7 bytes graças a Martin Ender.

(? <= ^ | \ b0) 0 (? = $ | 0)

 +

^ | $

A última linha é necessária.

Verifique todos os casos de teste de uma só vez. (Ligeiramente modificado para executar todos os casos de teste de uma vez.)

Parece que a linguagem perfeita para fazer isso ... ainda foi derrotada pela maioria das respostas.


Eu apenas abandonava os colchetes no formato de E / S.
Martin Ender

3

Mathematica, 43 bytes

ArrayFilter[If[#.#>0,#[[2]],Nothing]&,#,1]&

3

C, 96 bytes

Ligue f()com um ponteiro para a lista de números inteiros e um ponteiro para o tamanho da lista. A lista e o tamanho são modificados no local.

i,t,e,m;f(int*p,int*n){int*s=p;for(i=m=e=0;i++<*n;s+=t=m+*s||i<*n&&p[1],e+=t,m=*p++)*s=*p;*n=e;}

Experimente em ideone .


O estilo de parâmetro K&R geralmente é mais curto, mas não aqui - f(int*p,int*n)salva um byte. Ou defina scomo um terceiro parâmetro (isso não é passado. É meio que OK).
precisa saber é o seguinte

3

Braquilog , 44 38 bytes

,0gL:?:Lc:1fzbh.
~c[A:.:B],[0:0:0]'.l3

Experimente online!

Essa linguagem é boa para provar as coisas, e é isso que vamos usar.

Predicado 0 (predicado principal)

,0gL:?:Lc:1fzbh.
 0gL               [0] = L    (assignment works both ways)
   L:?:Lc          [L:input:L] = temp
         :1f       find all solutions of predicate 1 with temp as input
            zbh.   then transpose and take the middle row and assign to output

Predicado 1 (predicado auxiliar)

~c[A:.:B],[0:0:0]'.l3
~c[A:.:B]                 input is in the form of [A:output:B]
         ,                and
          [0:0:0]'.       output is not [0:0:0]
                  .l3     and length of output is 3

2

Matlab com Image Processing Toolbox, 27 bytes

@(a)a(~imerode(~a,~~(1:3)))

Esta é uma função anônima.

Exemplo de uso:

>> @(a)a(~imerode(~a,~~(1:3)))
ans = 
    @(a)a(~imerode(~a,~~(1:3)))
>> ans([0 0 0 8 0 1 0 0])
ans =
     0     8     0     1     0

1
Pensei imerodetambém, mas minhas versões manteve ser mais longo do que o meu atual, bom trabalho =)
flawr

2

Utilitários Bash + GNU, 25

grep -vC1 ^0|grep -v \\-$

Aceita entrada como uma lista separada por nova linha.

Ideona - com o código do driver de teste adicionado para executar todos os casos de teste juntos, convertendo para / do espaço e da nova linha.


2

Cheddar , 78 bytes

a->([[]]+a.map((e,i)->e|(i?a[i-1]:0)|(i-a.len+1?a[i+1]:0)?[e]:[])).reduce((+))

Suíte de teste.

O Cheddar não tem filtro; portanto, a filtragem é feita envolvendo os elementos que queremos e transformando os elementos que não queremos em matrizes vazias e concatenando tudo.

Por exemplo, [0,0,0,8,0,1,0,0]torna-se [[],[],[0],[8],[0],[1],[0],[]]e, em seguida, a matriz concatenada seria [0,8,0,1,0].


.reduce((+))->.sum
Downgoat 9/08/16

@Downgoat Quando você resolveu isso?
Freira vazada

oh, desculpe deixa pra lá. Eu pensei que você estava somando a matriz. Não juntar as matrizes
Downgoat

1

APL, 14 bytes

{⍵/⍨×3∨/0,⍵,0}

Teste:

      {⍵/⍨×3∨/0,⍵,0}2 0 4 ¯3 0 0 0 3 0 0 2 0 0
2 0 4 ¯3 0 0 3 0 0 2 0

Explicação:

  • 0,⍵,0: adicione um zero no início e no final de ⍵
  • ×3∨/: encontre o sinal do MDC de cada grupo de três números adjacentes (será 0 se todos forem zero e 1 caso contrário).
  • ⍵/⍨: selecione todos os itens de ⍵ para os quais o resultado foi 1.

1

Ruby 2.x, 63 bytes

f=->(x){x.select.with_index{|y,i|x[i-1].to_i|y|x[i+1].to_i!=0}}

Crédito, onde é devido, este é essencialmente um porto da resposta ES6 superior de Neil.

É também a minha primeira submissão pcg. yay.


1

Brain-Flak 142 bytes

Experimente online!

(<()>)(()){{}([]<([]){{}({}<>)<>({}<>)<>({}<>)<>(<>({}<>)<>({}<>)<>({})<>){{}((<()>))}{}{}([][()])}{}{}<>{}([]){{}({}<>)<>([])}{}<>>[[]])}{}{}

Explicação

(<()>)                    #Pad the top with an extra zero
(()){{}([]<...>[[]])}{}   #Until the stack height remains the same
 ([]){{}...([][()])}{}    #Until the stack height is one
  ({}<>)<>                #Move the top three to the other stack
  ({}<>)<>
  ({}<>)<>
  (...)                   #Push the sum of the top three
   <>({}<>)               #Move the second and third back
   <>({}<>)
   <>({})<>               #Leave the top of the stack
  {{}...}{}               #If the sum is not zero
   ((<()>))               #Add a buffer to the top of the stack
  {}                      #Pop the buffer/middle value
 {}                       #Remove extra zero
 <>                       #Switch to the off stack
 {}                       #Remove extra zero
 ([]){{}({}<>)<>([])}{}<> #Move the entire off stack back

O link está vazio. Você pode colar código e entrada, pressionar "salvar" e usar o link resultante
Luis Mendo

@LuisMendo Infelizmente eu não posso usar a tryitonline, então acabei de vincular o URL.
Wheat Wizard

Por que você não pode acessar a tryitonline?
DJMcMayhem

@DJMcMayhem Eu não tinha javascript no meu navegador. <s> Vou consertar agora. </s> Vejo que você já fez isso, obrigado.
Assistente de trigo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.