Mantener nonzeros y sus vecinos

26

Tomado de esta pregunta en Stack Overflow. Gracias también a @miles y @Dada por sugerir entradas de prueba que abordan algunos casos de esquina.

El reto

Dada una matriz de valores enteros, elimine todos los ceros que no estén flanqueados por algún valor distinto de cero.

De manera equivalente, una entrada debe mantenerse si es un valor distinto de cero o si es un cero que está inmediatamente cerca de un valor distinto de cero.

Las entradas que se mantienen deben mantener en la salida el orden que tenían en la entrada.

Ejemplo

Dado

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

Los valores que deben eliminarse están marcados con x:

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

y entonces la salida debería ser

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

Reglas

La matriz de entrada puede estar vacía (y luego la salida también debería estar vacía).

Los formatos de entrada y salida son flexibles como de costumbre: matriz, lista, cadena o cualquier cosa que sea razonable.

Código de golf, el menos mejor.

Casos de prueba

[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]
Luis Mendo
fuente
¿Puedo usar en _2lugar de -2? Muchos idiomas usan ese formato.
Leaky Nun
Vamos a tener -0?
Leaky Nun
@LeakyNun 1 Sí 2 No
Luis Mendo
¿Los números alguna vez tendrán ceros a la izquierda? Al igual que [010 0 0 01 1]?
FryAmTheEggman
@FryAmTheEggman Nope
Luis Mendo

Respuestas:

16

JavaScript (ES6), 35 bytes

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

Funciona también en flotantes para dos bytes adicionales.

Neil
fuente
10

Python, 50 bytes

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

Una función recursiva que toma una tupla. Incluye el primer elemento si hay un valor distinto de cero entre los dos primeros elementos o el valor anterior almacenado desde la última vez. Luego, elimina el primer elemento y vuelve a aparecer. El elemento anterior se almacena en la lista singleton p, que se empaqueta automáticamente en la lista y comienza como vacío (gracias a Dennis por 3 bytes con esto).


55 bytes:

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

Genera todos los fragmentos de longitud 3 de la lista, primero coloca ceros al inicio y al final, y toma los elementos medios de aquellos que no son todos cero.

Un enfoque iterativo resultó más largo (58 bytes)

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

Esto no funciona exactamente porque b,*lnecesita Python 3, pero Python 3 inputda una cadena. La inicialización también es fea. Tal vez un enfoque recursivo similar funcionaría.

Desafortunadamente, el método de indexación de

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

no funciona porque l[-1:2]interpreta -1como el final de la lista, no un punto antes de su inicio.

xnor
fuente
10

Haskell, 55 48 bytes

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

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

scanrreconstruye la lista de entrada xcon un adicional 0al principio y al final. En cada paso, modelamos 3 elementos y mantenemos el medio si hay al menos un elemento distinto de cero.

Gracias @xnor por 7 bytes cambiando de zip3a scanr.

nimi
fuente
Sería bueno hacerlo h x=[snd t|t<-zip3(0:x)x$tail x++[0],(0,0,0)/=t], pero supongo que no hay una forma corta de obtener el segundo elemento de una tupla de 3.
xnor
Resulta más corto para llegar a los triples de un scande un zip3: h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]].
xnor
8

Matlab, 29 27 bytes

La entrada debe consistir en una 1*nmatriz (donde n=0sea ​​posible). (Lanzará un error para las 0*0matrices).

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

La convolución es la clave del éxito.

falla
fuente
's'en lugar de 'same'<- :-D
Luis Mendo
Ese truco funciona muchas veces con builtins =)
flawr
He visto ese truco, incluso para preguntas que no son de golf, con la bandera 'UniformOutpout'(comprensiblemente). Pero no sabía sobre esto
Luis Mendo el
1
¿Podrías usar en ~~alugar de a.*a?
feersum
2
@feersum Matlab lamentablemente se niega a convolucionar logicalmatrices. Esto a menudo es un problema para las incorporaciones que no están escritas en Matlab. De lo contrario, las matrices lógicas se comportan de manera muy parecida a las numéricas. Podría funcionar en el pensamiento de Octave, pero no lo tengo instalado en este momento.
flawr
6

J, 17 14 bytes

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

Guardado 3 bytes con ayuda de @ 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

Explicación

#~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

Pruébalo aquí

millas
fuente
¿ 0<Funcionaría en lugar de 0~:?
Zgarb
@Zgarb Los infijos de tamaño 3 pueden ser positivos o negativos después de procesados.
millas
Ah, me olvidé de los valores negativos.
Zgarb
6

MATL , 8 bytes

tg3:Z+g)

La salida es una cadena con números separados por espacios. Una matriz vacía en la salida se muestra como nada (ni siquiera una nueva línea).

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

El código convierte la entrada al tipo lógico, es decir, las entradas distintas de cero se convierten en true(o 1) y las entradas de cero se convierten en false(o 0). Esto luego está relacionado con el núcleo [1 2 3]. Un valor distinto de cero provoca un resultado distinto de cero en esa posición y en sus posiciones vecinas. La conversión a truevalores lógicos da valores que deben mantenerse, por lo que indexar la entrada con eso produce la salida deseada.

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
Luis Mendo
fuente
5

Jolf, 14 bytes

Ahora que lo pienso, Jolf es el Java de los lenguajes de golf. suspiros Pruébalo aquí.

ψxd||H.nwS.nhS

Explicación

ψ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
Conor O'Brien
fuente
5

Python 3, 55 bytes

lambda s:[t[1]for t in zip([0]+s,s,s[1:]+[0])if any(t)]
RootTwo
fuente
1
Guau. No sé si vio a @xnor responder antes de esto, pero tiene exactamente el mismo código, con la única diferencia de ser el nombre de la lambda. Si usaste su código, dale crédito, si no, ¡qué loca coincidencia!
Theo
No miró el código de nadie.
RootTwo
3
@ T.Lukin En realidad no es raro encontrar el mismo código. Puede ver que esto suceda en Anarchy Golf, donde el código está oculto hasta la fecha límite, y varias personas convergen en la misma solución como esta .
xnor
4

Jalea , 9 bytes

0,0jo3\Tị

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo 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.
Dennis
fuente
4

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

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

Necesita la bandera -p para ejecutarse. Toma una lista de números como imput. Por ejemplo :

perl -pe 's/([^1-9]0 |^)\K0 ?(?=0|$)//&&redo' <<< "0 0 0 8 0 1 0 0
0 0 0
-5 0 5"
Dada
fuente
Me sale 5si ingreso 50 0.
feersum
@feersum arreglado, gracias
Dada
4

Haskell, 48 bytes

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

Mira el elemento anterior p, el primer elemento hy el elemento posterior (si lo hay), y si alguno no es cero, antepone el primer elemento h.

La condición any(/=0)$p:h:take 1tes larga, en particular la take 1t. Buscaré una forma de acortarlo, tal vez por coincidencia de patrones.

xnor
fuente
4

Retina , 42 35 33 bytes

7 bytes gracias a Martin Ender.

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

 +

^ | PS

La última línea es necesaria.

Verifique todas las cajas de prueba a la vez.(Ligeramente modificado para ejecutar todos los casos de prueba a la vez).

Parece el lenguaje perfecto para hacer esto ... todavía fue derrotado por la mayoría de las respuestas.

Monja permeable
fuente
Acabo de deshacerme de los corchetes del formato de E / S.
Martin Ender el
3

Mathematica, 43 bytes

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

C, 96 bytes

Llame f()con un puntero a la lista de enteros y un puntero al tamaño de la lista. La lista y el tamaño se modifican en el lugar.

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;}

Pruébalo con ideone .

owacoder
fuente
El estilo del parámetro K&R suele ser más corto, pero no aquí: f(int*p,int*n)guarda un byte. O defínalo scomo un tercer parámetro (eso no se pasa. Está bastante bien).
ugoren
3

Brachylog , 44 38 bytes

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

Pruébalo en línea!

Este lenguaje es bueno para probar cosas, que es lo que usaremos.

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
Monja permeable
fuente
2

Matlab con caja de herramientas de procesamiento de imágenes, 27 bytes

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

Esta es una función anónima.

Ejemplo 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
Luis Mendo
fuente
1
Pensé en eso imerodetambién, pero mis versiones seguían siendo más largas que la actual, buen trabajo =)
error
2

Bash + GNU utils, 25

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

Acepta entradas como una lista separada por una nueva línea.

Ideone : con código de controlador de prueba agregado para ejecutar todos los casos de prueba juntos mediante la conversión a / desde espacios separados y separados por líneas nuevas.

Trauma digital
fuente
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((+))

Banco de pruebas.

Cheddar no tiene filtro, por lo que el filtrado se realiza envolviendo los elementos que queremos y transformando los elementos que no queremos en matrices vacías, y luego concatena todo.

Por ejemplo, se [0,0,0,8,0,1,0,0]convierte [[],[],[0],[8],[0],[1],[0],[]], y luego la matriz concatenada sería [0,8,0,1,0].

Monja permeable
fuente
.reduce((+))->.sum
Downgoat
@Downgoat ¿Cuándo lo arreglaste?
Leaky Nun
Oh, lo siento, no importa. Pensé que estabas sumando la matriz. no unirse a las matrices
Downgoat
1

APL, 14 bytes

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

Prueba:

      {⍵/⍨×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

Explicación:

  • 0,⍵,0: agregue un cero al principio y al final de ⍵
  • ×3∨/: encuentre el signo del MCD de cada grupo de tres números adyacentes (de lo contrario, será 0 si todos son cero y 1).
  • ⍵/⍨: seleccione todos los elementos de ⍵ para los que el resultado fue 1.
marinus
fuente
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 donde es debido, esto es esencialmente un puerto de la respuesta superior ES6 de Neil.

También es mi primera presentación de PCG. Hurra.

to_json
fuente
1

Brain-Flak 142 bytes

Pruébalo en línea!

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

Explicación

(<()>)                    #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
Asistente de trigo
fuente
El enlace esta vacio. Puede pegar el código y la entrada, presione "guardar" y use el enlace resultante
Luis Mendo
@LuisMendo Lamentablemente, no puedo usar tryitonline, así que simplemente me vinculé a la url.
Wheat Wizard
¿Por qué no puedes acceder a tryitonline?
DJMcMayhem
@DJMcMayhem No tenía JavaScript en mi navegador. <s> Lo arreglaré ahora. </s> Veo que ya lo has hecho, gracias.
Wheat Wizard