Comprimi duplicati adiacenti


22

Sfida

Dato un elenco di numeri interi, restituisce l'elenco di questi numeri interi dopo aver rimosso ripetutamente tutte le coppie di elementi uguali adiacenti.

Si noti che se si dispone di una corsa di lunghezza pari di numeri uguali, uno di essi rimarrà, non facendo parte di una coppia.

Esempio:

[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0]

In primo luogo, si dovrebbe rimuovere 0, 0, 4, 4e 1, 1di ottenere:

[0, 1, 2, 2, 0]

Ora dovresti rimuovere 2, 2:

[0, 1, 0]

E questo è il risultato finale.

Casi test

[] -> []
[1] -> [1]
[1, 1] -> []
[1, 2] -> [1, 2]
[11, 11, 11] -> [11]
[1, 22, 1] -> [1, 22, 1]
[-31, 46, -31, 46] -> [-31, 46, -31, 46]
[1, 0, 0, 1] -> []
[5, 3, 10, 10, 5] -> [5, 3, 5]
[5, 3, 3, 3, 5] -> [5, 3, 5]
[0, -2, 4, 4, -2, 0] -> []
[0, 2, -14, -14, 2, 0, -1] -> [-1]
[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0] -> [0, 1, 0]
[3, 5, 4, 4, 8, 26, 26, 8, 5] -> [3]
[-89, 89, -87, -8, 8, 88] -> [-89, 89, -87, -8, 8, 88]

punteggio

Questo è , quindi vince la risposta più breve in ogni lingua!


Sandbox per coloro che possono vedere i post cancellati
musicman523

Non importa, sono tutti uguali. Il significato di questa frase è che [14, 14, 14]crolla a[14]
musicman523

Ho letto male la sfida, scusa. Pensava di avere per rimuovere tutte le coppie di numeri in aumento del 1 ( 1,2, 11,12, ecc)
Stephen

Possiamo prendere l'input come una stringa delimitata?
Shaggy,

2
Potresti aggiungere un caso di test come -89,89,-87,-8,-88? Sia la mia soluzione Japt (non pubblicata) che la soluzione Retina di Fry falliscono lì, generando --87,8.
Shaggy,

Risposte:


5

Gelatina , 10 byte

Œgœ^/€FµÐL

Provalo online!

Come funziona

Œgœ^/€FµÐL  Main link. Argument: A (array)

       µ    Combine all links to the left into a chain.
Œg              Group all adjacent equal items.
    /€          Reduce each group by...
  œ^                symmetric multiset difference.
                In each step, this maps ([], n) to [n] and ([n], n) to [], so the
                group is left with a single item if its length is odd, and no items
                at all if its length if even.
      F         Flatten the resulting array of singleton and empty arrays.
        ÐL  Apply the chain until the results are no longer unique. Return the last
            unique result.

L'utilizzo invece di Fti farebbe supportare anche gli elenchi nel tuo elenco.
Erik the Outgolfer,

No, œ^si affida alla promozione da intero a array qui. Poiché gli array 1D non vengono promossi in array 2D, non funzionerà per nulla tranne che per un array di numeri.
Dennis,

Eh ... voglio dire che avresti potuto usare ŒgWẎ$œ^/$€ẎµÐL... oh aspetta, è troppo ingenuo. : P
Erik the Outgolfer,

4

Retina ,17 15 byte

+m`^(.+)¶\1$¶?

Provalo online!

Salvato 2 byte grazie a Neil e Martin!

Sostituisce ogni coppia di numeri con nulla. Questo processo viene eseguito fino a quando non vengono apportate modifiche.


Ha trovato una soluzione identica in Japt prima di individuarlo. Sfortunatamente, entrambi falliamo su input come -89 89 -87 -88 -88, quali output --87.
Shaggy,

1
@Shaggy Grazie, l'ho corretto aggiungendo un controllo di confine e usando _per indicare i negativi, come è comune in alcune lingue.
FryAmTheEggman,

Da allora ho scoperto che anche questo fallirà _89 89 _87 _8 _88, emettendo _89 89 _87 8. Siamo spiacenti: \
Shaggy il

@Shaggy Non essere dispiaciuto! Grazie per aver trovato il problema! Ho aggiunto un altro controllo al contorno per risolvere quel caso.
FryAmTheEggman,

1
@FryAmTheEggman Non sono sicuro se questo è ciò che intendeva Neil, ma puoi anche usare mper trasformare le \bs in ^e $.
Martin Ender,

3

Mathematica 29 byte

Questo rimuove ripetutamente coppie di uguali elementi adiacenti, a_,a_fino a quando non ne rimane più nessuno.

#//.{b___,a_,a_,c___}:>{b,c}&

3

Python 2 , 57 byte

r=[]
for x in input():r+=x,;r[-2:]*=r[-2:-1]!=[x]
print r

Provalo online!

Costruisce in modo iterativo l'elenco di output aggiungendo l'elemento successivo, quindi tagliando la fine se l'elemento accodante è uguale a quello precedente. Controllare il penultimo elemento r[-2:-1]!=[x]risulta scomodo perché è possibile che l'elenco abbia solo la lunghezza 1.


Risposta fantastica, ben fatta :)
musicman523

2

Gelatina , 15 byte

Œr;ṪḂ$$€x/€FµÐL

Provalo online!

Spiegazione

Œr;ṪḂ$$€x/€FµÐL  Main Link
Œr               Run-length encode
  ;              Concatenate (?)
       €         For each element
   ṪḂ$$          Is the last element odd?
          €      For each element    // Non-breaking alternative
        x/       Reduce by repeating // for run-length decode
           F     Flatten
            µ    (New monadic link)
             ÐL  Repeat until results are no longer unique

-1 byte grazie alle miglia e risolto :)


@FryAmTheEggman Fixed; Grazie!
HyperNeutrino,

Non sono sicuro se lanciare un errore e lasciare vuoto l'output sia considerata una soluzione corretta. Si programmano lanci ValueError: not enough values to unpack (expected 2, got 0)per test case [1,2,2,1]. Si noti inoltre che l'output vuoto è diverso da []ed 2è diverso da [2].

13 byte con Œr;ṪḂ$$€ŒṙµÐL. Per evitare l'errore, sostituirlo Œṙcon x/€Fpoiché la decodifica di lunghezza di esecuzione genera un errore quando viene fornito un elenco vuoto. Per vedere l'output come un elenco, il viraggio ŒṘlo mostrerà.
miglia,

@ThePirateBay La rappresentazione di Jelly di un elenco vuoto è - vuota, di un elemento - solo quell'elemento e di più elementi - un elenco tra parentesi e separato da virgole. L'invio è di un link (funzione) non di un programma completo (proprio come un lambda sarebbe in Python) - per vedere un punto di vista più "normale" ÇŒṘnel piè di pagina per chiamare l'ultimo link ( Ç) e stampare una rappresentazione Python ( ŒṘ) . Tuttavia, l'errore potrebbe non essere accettabile.
Jonathan Allan,

@JonathanAllan. Ok, ho capito che la rappresentazione in formato stringa di Jelly di un elenco è accettabile. Il punto principale del mio primo commento è menzionare che l'errore viene generato quando l'elenco diventa vuoto.

2

JavaScript (ES6), 54 53 byte

Salvato 1 byte grazie a @ThePirateBay

f=a=>1/a.find(q=>q==a[++i],i=-2)?f(a,a.splice(i,2)):a

Ingenua soluzione ricorsiva, può essere migliorabile.


Puoi controllare l'elemento corrente e precedente invece di quello attuale e successivo, in modo da poterlo sostituire i=0con i=-2e i-1con il iquale è -1 byte in totale.

@ guest44851 Grazie, ma ... non significa che dovrei cambiarlo in i+1? (L'ho provato prima con lo spostamento ++anche io e non sono riuscito a capirlo, anche se ho avuto solo un minuto per farlo)
ETHproductions

Puoi vedere che funziona correttamente .

@ThePirateBay A ragione, hai ragione! Ma come?
ETHproductions

2

Python 2 , 73 byte

Dato che non ho abbastanza reputazione per commentare: ho appena cambiato la risposta di @officialaimm per usare r! = [] Invece di len (r) per salvare un byte. Soluzione molto intelligente per te, @officialaimm!

r=[]                            # create list that will hold final results. A new list is important because it needs to be removable.
for i in input():               
 if r!=[]and r[-1]==i:r.pop()   # Ensure that we have at least 1 char added to the list (r!=[])... or that the last character of our final result isn't the current character being scanned. If that is, well, remove it from the final list because we do not want it anymore
 else:r+=[i]                    # Shorthand for r.append(i). This adds i to the final result
print r

Provalo online!

È, ancora una volta, troppo tardi ... perché sono ancora alzato?



2

MATL , 7 byte

t"Y'oY"

Per alcuni dei casi di test in cui il risultato è vuoto, il programma esce con un errore, ma in ogni caso produce l'output corretto (vuoto).

Provalo online! O verificare i casi di test con output non vuoto .

Spiegazione

t     % Implicit input. Duplicate
"     % For each (i.e. do as many times as input size)
  Y'  %   Run-length encode. Gives array of values and array of run lengths
  o   %   Parity, element-wise. Reduces run-lengths to either 0 or 1
  Y"  %   Run-length decode. Gives array of values appearing 0 or 1 times;
      %   that is, removes pairs of consecutive values
      % Implicit end. Implicit display

Considera l'input

0 0 0 1 2 4 4 2 1 1 0

Ogni iterazione rimuove le coppie di coppie consecutive. La prima iterazione riduce l'array a

0 1 2 2 0

I due valori 2che ora sono adiacenti non erano adiacenti nell'array iniziale. Ecco perché è necessaria una seconda iterazione, che fornisce:

0 1 0

Ulteriori iterazioni lasceranno questo invariato. Il numero di iterazioni richieste è limitato dalla dimensione dell'input.

Un risultato intermedio vuoto causa l' Y"errore nella funzione di decodifica di lunghezza ( ) nella versione corrente della lingua; ma l'uscita è vuota come richiesto.


Potresti aggiungere una spiegazione? Mi piacerebbe capire come mi hai battuto così profondamente. : P
Dennis,

@Dennis Certo! Ho dimenticato. Fatto :-)
Luis Mendo, il

1
Ah, RLE spinge due array. Questo è utile
Dennis,

2

Codice macchina x86 (modalità protetta a 32 bit), 36 byte

52
8B 12
8D 44 91 FC
8B F9
8D 71 04
3B F0
77 10
A7
75 F9
83 EF 04
4A
4A
A5
3B F8
75 FB
97
EB E7
58
89 10
C3

I byte precedenti del codice macchina definiscono una funzione che accetta un array come input, comprime i duplicati adiacenti sul posto e ritorna al chiamante senza restituire un risultato. Segue la __fastcallconvenzione di chiamata , passando rispettivamente i due parametri nei registri ECXe EDX.

Il primo parametro ( ECX) è un puntatore al primo elemento nella matrice di numeri interi a 32 bit (se la matrice è vuota, può puntare ovunque nella memoria). Il secondo parametro ( EDX) è un puntatore a un numero intero a 32 bit che contiene la lunghezza dell'array.

La funzione modificherà gli elementi dell'array sul posto, se necessario, e aggiornerà anche la lunghezza per indicare la nuova lunghezza dell'array compresso. Questo è un metodo un po 'insolito per prendere input e restituire output, ma in realtà non hai altra scelta nel linguaggio assembly. Come in C, le matrici sono effettivamente rappresentate nella lingua come un puntatore al primo elemento e una lunghezza . L'unica cosa un po 'strana qui è prendere la lunghezza per riferimento , ma se non lo facessimo, non ci sarebbe modo di accorciare l'array. Il codice funzionerebbe bene, ma l'output conterrebbe immondizia, perché il chiamante non avrebbe saputo dove interrompere la stampa di elementi dall'array compresso.

Mnemonici di assemblaggio non golfati:

; void __fastcall CollapseAdjacentDuplicates(int * ptrArray, int * ptrLength);
; ECX = ptrArray              ; ECX = fixed ptr to first element
; EDX = ptrLength
   push  edx                  ; save pointer to the length
   mov   edx, [edx]           ; EDX = actual length of the array
   lea   eax, [ecx+edx*4-4]   ; EAX = fixed ptr to last element 

FindAdjacentPairs:
   mov   edi, ecx             ; EDI = ptr to element A
   lea   esi, [ecx+4]         ; ESI = ptr to element B
FindNext:
   cmp   esi, eax             ; is ptr to element B at end?
   ja    Finished             ; if we've reached the end, we're finished
   cmpsd                      ; compare DWORDs at ESI and EDI, set flags, and increment both by 4
   jne   FindNext             ; keep looping if this is not a pair

; Found an adjacent pair, so remove it from the array.
   sub   edi, 4               ; undo increment of EDI so it points at element A
   dec   edx                  ; decrease length of the array by 2
   dec   edx                  ;  (two 1-byte DECs are shorter than one 3-byte SUB)
RemoveAdjacentPair:
   movsd                      ; move DWORD at ESI to EDI, and increment both by 4
   cmp   edi, eax             ; have we reached the end?
   jne   RemoveAdjacentPair   ; keep going until we've reached the end
   xchg  eax, edi             ; set new end by updating fixed ptr to last element
   jmp   FindAdjacentPairs    ; restart search for adjacent pairs from beginning

Finished:
   pop   eax                  ; retrieve pointer to the length
   mov   [eax], edx           ; update length for caller
   ret

L'implementazione è stata ispirata dalla mia risposta C ++ 11 , ma meticolosamente riscritta nell'assemblaggio, ottimizzando le dimensioni. Il montaggio è un linguaggio golfistico molto migliore. :-)

Nota: Poiché questo codice utilizza le istruzioni di stringa, è non dare per scontato che la bandiera direzione è chiara ( DF== 0). Questo è un presupposto ragionevole nella maggior parte degli ambienti operativi, poiché l'ABI richiede in genere che DF sia chiaro. Se ciò non può essere garantito, è necessario inserire CLDun'istruzione da 1 byte ( 0xFC) nella parte superiore del codice.

Inoltre, come notato, presuppone la modalità protetta a 32 bit, in particolare un modello di memoria "piatto", in cui il segmento aggiuntivo ( ES) è uguale al segmento dati ( DS).


1

Lotto, 133 byte

@set s=.
:l
@if "%1"=="%2" (shift/1)else set s=%s% %1
@shift/1
@if not "%1"=="" goto l
@if not "%s:~2%"=="%*" %0%s:~1%
@echo(%*

Ho impostato s .perché Batch viene confuso se ci sono solo duplicati. Devo anche usare in shift/1modo da poter usare %0%s:~1%per impostare la lista degli argomenti sul nuovo array e loop.


Devo chiedere ... perché? Buona risposta ... ma perché?
Zacharý,

@ Zacharý Perché è lì.
Neil,

1
@ Zacharý In parte, un buon motivo per giocare a golf in lingue diverse da quelle di golf è perché questo potrebbe effettivamente essere utile . Nessuno accenderà un interprete Jelly nella vita reale per farlo, ma potrebbe essere necessario farlo in un file batch!
Cody Gray,

Oh. ciò ha senso.
Zacharý,

1

Gelatina , 12 byte

ŒgṁLḂ$$€ẎµÐL

Un collegamento monadico che prende e restituisce elenchi di numeri.

Provalo online! o vedere una suite di test

Come?

ŒgṁLḂ$$€ẎµÐL - Link: list
         µÐL - perform the chain to the left until no changes occur:
Œg           -   group runs (yield a list of lists of non-zero-length equal runs)
      $€     -   last two links as a monad for €ach run:
     $       -     last two links as a monad:
   L         -       length (of the run)
    Ḃ        -       modulo 2 (1 if odd, 0 if even)
  ṁ          -     mould (the run) like (1 or 0) (yields a list of length 1 or 0 lists)
        Ẏ    -   tighten (make the list of lists into a single list)

ṁLḂ$$€è equivalente al ḣLḂ$$€quale è equivalente al ṫḊ¿€3$quale è possibile sostituire ṫḊ¿€3qui per formare una coppia diade / nilad.
Erik the Outgolfer,

Ciò non funziona, ad esempio, con un input con una corsa di lunghezza 4. Qual è l'input per il dequeue ad ogni iterazione del ciclo while?
Jonathan Allan,

Dovresti essere lasciato con un elenco con 0 o 1 elementi. Se len (x) == 1, quindi tornerà []mentre se len (x) == 0 tornerà 0, essendo entrambi i valori falsy. L'ingresso a è ovviamente il valore corrente e avrà il valore corrente come argomento sinistro e 3come destro. Se len (x) == 4, allora sarebbe lo stesso ṫ3ṫ3o ṫ5lasciandoti con [].
Erik the Outgolfer,

Vedo cosa dovrebbe fare, ma xnella tua descrizione c'è davvero il valore attuale? Prova questo per dimensioni.
Jonathan Allan,

Ad essere sincero, non so se questo è il codice o un bug :)
Jonathan Allan,


1

05AB1E , 15 byte

[γʒgÉ}€нÐγ‚€gË#

Provalo online!

Spiegazione

[γʒgÉ}€нÐγ‚€gË#
[               # Start infinite loop
 γ              # Group Array into consecutive equal elements
  ʒgÉ}          # Keep the subarrays with an uneven amount of elements
      €н        # Keep only the first element of each subarray
        Ð       # Triplicate the result on the stack
         γ      # Group the top element into consecutive equal elements
          ‚     # Wrap the top two items of the stack in an array
           €g   # Get the length of each subarray
             Ë# # Break if they are equal
                # Implicit print          

1

05AB1E , 13 byte

[DγʒgÉ}€нDŠQ#

Provalo online!

Spiegazione:

[DγʒgÉ}€нDŠQ# Implicit input
[             Start infinite loop
 D            Duplicate
  γ           Split into chunks of equal elements
   ʒ  }       Filter by
    g           Length
     É          Odd? (0=falsy 1=truthy)
       €      Foreach command
        н     Head
         D    Duplicate
          Š   Push c, a, b
           Q  Equal? (0=falsy 1=truthy)
            # Break if true (i.e. equal to 1)


1

Python 2 , 74 70 66 byte

  • Grazie @SteamyRoot per 4 byte: ranzichélen(r) è sufficiente per verificare il vuoto dell'elenco / stack.
  • Grazie @ovs per 4 byte: meglio se condizione [i]==r[-1:]

Python 2 , 66 byte

r=[]
for i in input():
 if[i]==r[-1:]:r.pop()
 else:r+=[i]
print r

Provalo online!


1
Se lo scopo di len(r)è solo quello di verificare se l'elenco è vuoto o no, dovresti essere in grado di sostituirlo con solo r, penso?
SteamyRoot,

Oh si grazie.
officialaimm,


@ovs Grazie mille, è fantastico! (y)
officialaimm,

1
Versione alternativa di 66 byte , anche se richiede solo tre righe.
Jonathan Frech,

0

Clojure, 100 byte

#(loop[i % j[]](if(= i j)i(recur(mapcat(fn[p](repeat(mod(count p)2)(last p)))(partition-by + i))i)))

Non sono sicuro se questo è il più breve possibile.


0

Bash, 82 byte

cat>b
while cat b>a
perl -pe 's/(\d+) \1( |$)//g' a>b
! diff a b>c
do :
done
cat a

Probabilmente c'è una via d'uscita da tutte quelle cose cat, ma non lo so.


0

Buccia , 10 byte

ωoṁS↑o%2Lg

Provalo online!

Spiegazione

ωoṁS↑o%2Lg
ω           Repeat until fixed point
 o          the following two functions:
         g   a) group adjacent elements
  ṁ          b) map over groups and concatenate:
        L     length of group
     o%2      mod 2
   S↑         take that many elements of group

0

PHP, 81 byte

    function f(&$a){for($i=count($a);--$i;)$a[$i]-$a[$i-1]||array_splice($a,$i-1,2);}

funzione, chiama per riferimento o provalo online .

non riesce per input vuoto; inserire $i&&o $a&&prima --$idi risolvere.


0

V , 10 byte

òͨ.«©î±î*

Provalo online!

Compressa Regex: :%s/\(.\+\)\n\1\n*. La newline opzionale è in modo che funzioni anche alla fine del file. Se suppongo che ci sia una nuova riga dopo la fine sarebbe di 8 byte ... ma sembra un tratto


0

dc , 84 78 byte

[L.ly1-dsy0<A]sA[LtLtS.ly1+sy]sP[dStrdStr!=Pz1<O]sO[0syzdsz1<Oly0<Azlz>M]dsMxf

Provalo online!

Disimballando un po ', fuori servizio in qualche tentativo di chiarezza:

  • [0syzdsz1<Olydsx0<Alx1+lz>M]dsMxfLa macro principale Mreimposta il contatore ysu 0, recupera il numero di elementi nello stack, lo memorizza nel registro z, quindi esegue la macro Ose nello stack sono presenti almeno due elementi. Una volta Oterminato, carica il contatore ye lo copia nel registro xprima di verificare che ysia diverso da zero (il che significa che lo stack .ha dati). In questo caso, esegue la macro A. Infine controlla se la dimensione dello stack originale è più grande della dimensione dello stack corrente e in tal caso si esegue nuovamente. Una volta terminato, stampa la pila con f.
  • [dStrdStr!=Pz1<O]sOLa macro Omemorizza temporaneamente i primi due elementi nella pila in pila t. Quindi confronta i primi due elementi ed esegue la macro Pse non sono uguali. Infine controlla se ci sono almeno due elementi nello stack e si esegue se stesso.
  • [LtLtS.ly1+sy]sPLa macro Pprende i due oggetti dallo stack t, rimette quello superiore nello stack principale e spinge il successivo nello stack .. Quindi incrementa il contatore y.
  • [L.ly1-dsy0<A]sALa macro Aprende lo stack .e lo trasforma nello stack principale. Lo fa, riducendo il contatore yfino a quando non c'è più niente da spingere.

Modificato per una spiegazione e per golfare 6 byte mentre stavo inutilmente memorizzando le dimensioni dello stack.


0

C ++ 11, 161 byte

#include<vector>
#include<algorithm>
using V=std::vector<int>;void f(V&v){V::iterator i;while((i=std::adjacent_find(v.begin(),v.end()))!=v.end())v.erase(i,i+2);}

Il codice precedente definisce una funzione, fche accetta un std::vector<int>riferimento, la modifica in posizione per comprimere i duplicati adiacenti in base alla specifica, quindi restituisce.

Provalo online!

Prima di controllare il conteggio dei byte, ho pensato che fosse un codice piuttosto snello. Oltre 150 byte, tuttavia, non è così buono! O non sono molto bravo a giocare a golf, o C ++ non è un linguaggio di golf molto buono ...

Ungolfed:

#include <vector>
#include <algorithm>

using V = std::vector<int>;

void f(V& v)
{
   V::iterator i;

   // Use std::adjacent_find to search the entire vector for adjacent duplicate elements.
   // If an adjacent pair is found, this returns an iterator to the first element of the
   // pair so that we can erase it. Otherwise, it returns v.end(), and we stop.
   while ((i=std::adjacent_find(v.begin(), v.end())) != v.end())
   {
        v.erase(i, i+2);   // erase this adjacent pair
   }
}

Il C ++ non è il miglior linguaggio per giocare a golf. Bel uso di std::adjacent_find! Mi chiedo se è stato implementato questa funzione da soli se sarebbe stato più breve, dal momento che è possibile rimuovere #include <algorithm>così
musicman523

@ musicman523 Il mio primo tentativo lo ha implementato manualmente, anche se ho usato un algoritmo un po 'diverso. Stavo adattando l'implementazione di std::uniqueper fare ciò di cui avevo bisogno. Ma ci vuole molto codice per fare tutta la logica, e quando mi sono imbattuto std::adjacent_find, era abbastanza ovvio che era un vincitore in termini di dimensioni del codice.
Cody Gray,

0

PHP, 74 byte

function c(&$a){foreach($a as$k=>$v)$a[$k+1]===$v&&array_splice($a,$k,2);}

La funzione c chiama per riferimento per ridurre l'array. Provalo online .

È interessante notare che questo funziona in Php5.6 ma non 7.


0

R , 57 54 byte

l=rle(scan());while(any(x<-!l$l%%2))l=rle(l$v[!x]);l$v

Provalo online!

utilizza una codifica di lunghezza per rimuovere le coppie.




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.