Mantieni i nonzeros e i loro vicini


26

Tratto da questa domanda in Stack Overflow. Grazie anche a @miles e @Dada per aver suggerito input di test che risolvono alcuni casi angolari.

La sfida

Data una matrice di valori interi, rimuovere tutti gli zeri che non sono affiancati da un valore diverso da zero.

Equivalentemente, una voce dovrebbe essere mantenuta se è un valore diverso da zero o se è uno zero immediatamente vicino a un valore diverso da zero.

Le voci che vengono conservate dovrebbero mantenere nell'output l'ordine che avevano nell'input.

Esempio

Dato

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

i valori che devono essere rimossi sono contrassegnati con un x:

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

e quindi l'output dovrebbe essere

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

Regole

L'array di input potrebbe essere vuoto (e quindi anche l'output dovrebbe essere vuoto).

I formati di input e output sono flessibili come al solito: array, elenco, stringa o qualsiasi cosa sia ragionevole.

Codice golf, il meno migliore.

Casi test

[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 usare _2invece di -2? Molte lingue usano quel formato.
Leaky Nun,

Avremo -0?
Leaky Nun,

@LeakyNun 1 Sì 2 No
Luis Mendo

I numeri avranno mai zeri iniziali? Come [010 0 0 01 1]?
FryAmTheEggman,

@FryAmTheEggman Nope
Luis Mendo,

Risposte:


16

JavaScript (ES6), 35 byte

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

Funziona anche su float per due byte extra.


10

Python, 50 byte

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

Una funzione ricorsiva che richiede una tupla. Include il primo elemento se esiste un valore diverso da zero tra i primi due elementi o il valore precedente memorizzato dall'ultima volta. Quindi, rimuove il primo elemento e ricorre. L'elemento precedente è memorizzato nella lista singleton p, che si comprime automaticamente nella lista e inizia come vuota (grazie a Dennis per 3 byte con questo).


55 byte:

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

Genera tutti i blocchi di lunghezza 3 dell'elenco, inserendo prima gli zeri all'inizio e alla fine e acquisisce gli elementi medi di quelli che non sono tutti zero.

Un approccio iterativo si è rivelato più lungo (58 byte)

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

Non funziona esattamente perché b,*lrichiede Python 3, ma Python 3 inputfornisce una stringa. Anche l'inizializzazione è brutta. Forse un simile approccio ricorsivo avrebbe funzionato.

Sfortunatamente, il metodo di indicizzazione di

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

non funziona perché l[-1:2]interpreta -1la fine dell'elenco, non un punto prima del suo inizio.


10

Haskell, 55 48 byte

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

Esempio di utilizzo: h [0,0,0,8,0,1,0,0]-> [0,8,0,1,0].

scanrricostruisce l'elenco di input xcon un ulteriore 0all'inizio e alla fine. In ogni passaggio, modelliamo 3 elementi e manteniamo quello centrale se c'è almeno un elemento diverso da zero.

Grazie @xnor per 7 byte passando da zip3a scanr.


Sarebbe bello da fare h x=[snd t|t<-zip3(0:x)x$tail x++[0],(0,0,0)/=t], ma immagino che non ci sia un modo breve per ottenere effettivamente il secondo elemento di una 3-tupla.
xnor

Risulta più breve per ottenere le triple di un scandi un zip3: h x=[b|a:b:c:_<-scanr(:)[0]$0:x,any(/=0)[a,b,c]].
xnor

8

Matlab, 29 27 byte

L'input deve essere costituito da una 1*nmatrice (dove n=0possibile). (Verrà generato un errore per le 0*0matrici.)

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

La convoluzione è la chiave del successo.


's'anziché 'same'<- :-D
Luis Mendo l'

Questo trucco funziona molte volte con builtins =)
flawr

Ho visto quel trucco, anche per le domande sul non golf, con la bandiera 'UniformOutpout'(comprensibilmente). Ma non sapevo di questo
Luis Mendo l'

1
Potresti usare al ~~aposto di a.*a?
feersum

2
Purtroppo, @feersum Matlab si rifiuta di intrecciare logicalarray. Questo è spesso un problema per i built-in che non sono scritti in Matlab stesso. Altrimenti le matrici logiche si comportano in modo molto simile a quelle numeriche. Potrebbe funzionare secondo Octave, ma al momento non è installato.
flawr

6

J, 17 14 byte

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

Salvato 3 byte con l'aiuto di @ 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

Spiegazione

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

Provalo qui.


Funzionerebbe 0<al posto di 0~:?
Zgarb,

@Zgarb Gli infissi di dimensione 3 possono essere positivi o negativi dopo l'elaborazione.
miglia

Ah, mi sono dimenticato dei valori negativi.
Zgarb,

6

MATL , 8 byte

tg3:Z+g)

L'output è una stringa con numeri separati da spazi. Un array vuoto nell'output viene visualizzato come nulla (nemmeno una nuova riga).

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Il codice converte l'input in tipo logico, ovvero voci non zero diventano true(o 1) e zero voci diventano false(o 0). Questo è quindi complicato dal kernel [1 2 3]. Un valore diverso da zero provoca un risultato diverso da zero in quella posizione e nelle posizioni adiacenti. La conversione in logica fornisce truevalori che devono essere mantenuti, quindi indicizzare l'input con quello produce l'output desiderato.

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 byte

Ora che ci penso, Jolf è il Java dei linguaggi del golf. sospiri Provalo qui.

ψxd||H.nwS.nhS

Spiegazione

ψ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 byte

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

1
Wow. Non so se hai visto @xnor rispondere prima, ma hai lo stesso codice esatto, con l'unica differenza che è il nome del lambda. Se hai usato il suo codice, dagli credito, in caso contrario, che folle coincidenza!
Theo

Non ha guardato il codice di nessuno.
Root Due

3
@ T.Lukin In realtà non è raro trovare lo stesso codice. Puoi vederlo accadere su Anarchy Golf, dove il codice è nascosto fino alla scadenza e più persone convergono sulla stessa soluzione come questa .
xnor

4

Gelatina , 9 byte

0,0jo3\Tị

Provalo online! o verifica tutti i casi di test .

Come funziona

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 (-p flag) = 35 byte

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

Ha bisogno di -p flag per funzionare. Prende un elenco di numeri come imput. Per esempio :

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

Ottengo 5se inserisco 50 0.
feersum

@feersum risolto, grazie
Dada

4

Haskell, 48 byte

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

Guarda l'elemento precedente p, il primo elementoh e l'elemento dopo (se presente), e se ce ne sono di zero, antepone il primo elemento h.

La condizione any(/=0)$p:h:take 1tè lunga, in particolare il take 1t. Cercherò un modo per accorciarlo, forse abbinando i motivi.


4

Retina , 42 35 33 byte

7 byte grazie a Martin Ender.

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

 +

^ | $

L'ultima riga è necessaria.

Verifica tutti i test in una volta. (Leggermente modificato per eseguire contemporaneamente tutti i test.)

Sembra il linguaggio perfetto per farlo in ... ancora sconfitto dalla maggior parte delle risposte.


Avrei semplicemente abbandonato le parentesi dal formato I / O.
Martin Ender,

3

Mathematica, 43 byte

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

3

C, 96 byte

Chiamare f()con un puntatore all'elenco di numeri interi e un puntatore alla dimensione dell'elenco. L'elenco e le dimensioni vengono modificati sul posto.

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

Provalo su ideone .


Lo stile del parametro K&R è spesso più breve, ma non qui: f(int*p,int*n)salva un byte. Oppure definisci scome un terzo parametro (che non viene passato. È un po 'OK).
Ugoren,

3

Brachylog , 44 38 byte

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

Provalo online!

Questo linguaggio è buono come prova delle cose, che è quello che useremo.

Predicato 0 (predicato principale)

,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

Predicato 1 (predicato ausiliario)

~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 con Image Processing Toolbox, 27 byte

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

Questa è una funzione anonima.

Esempio di utilizzo:

>> @(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
Ci ho pensato imerodeanche io , ma le mie versioni continuavano ad essere più lunghe di quella attuale, bel lavoro =)
flawr

2

Utilità Bash + GNU, 25

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

Accetta input come un elenco separato da nuova riga.

Ideone - con il codice del driver di prova aggiunto per eseguire tutti i testcase insieme convertendo in / da spazio separato e newline-separato.


2

Cheddar , 78 byte

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

Suite di test.

Cheddar non ha filtri, quindi il filtraggio viene eseguito avvolgendo gli elementi che vogliamo e trasformando gli elementi che non vogliamo in array vuoti, quindi concatenando tutto.

Ad esempio, [0,0,0,8,0,1,0,0]diventa [[],[],[0],[8],[0],[1],[0],[]], e quindi sarebbe l'array concatenato [0,8,0,1,0].


.reduce((+))->.sum
Downgoat

@Downgoat Quando l'hai risolto?
Leaky Nun,

oh, scusa non importa. Pensavo stessi sommando l'array. non unendo gli array
Downgoat

1

APL, 14 byte

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

Test:

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

Spiegazione:

  • 0,⍵,0: aggiungi uno zero all'inizio e alla fine di ⍵
  • ×3∨/: trova il segno del GCD di ogni gruppo di tre numeri adiacenti (questo sarà 0 se sono tutti zero e 1 altrimenti).
  • ⍵/⍨: seleziona tutti gli elementi da ⍵ per i quali il risultato è stato 1.

1

Ruby 2.x, 63 byte

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

Il credito è dovuto, questo è essenzialmente un porto della risposta ES6 superiore di Neil.

È anche il mio primo invio di pcg. Sìì.


1

Brain-Flak 142 byte

Provalo online!

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

Spiegazione

(<()>)                    #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

Il link è vuoto Puoi incollare il codice e inserire, premere "salva" e utilizzare il link risultante
Luis Mendo

@LuisMendo Purtroppo non posso usare tryitonline, quindi mi sono appena collegato all'URL.
Mago del grano

Perché non riesci ad accedere a tryitonline?
DJMcMayhem

@DJMcMayhem Non avevo JavaScript nel mio browser. <s> Lo riparerò ora. </s> Vedo che l'hai già fatto grazie.
Mago del grano
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.