Separare un elenco in parti con indicizzazione pari e dispari


26

Ispirato da questa domanda:

Crea una funzione (o un programma completo) che riceve un elenco di numeri e genera l'elenco riorganizzato, in modo che i numeri con indice pari vengano visualizzati per primi, e seguano i numeri con indice dispari. I valori dei numeri stessi non influiscono sull'ordinamento, ma solo sui loro indici. Tutti gli indici sono a base zero.

Per esempio:

Ingresso: [0, 1, 2, 3, 4]

Produzione: [0, 2, 4, 1, 3]

Un altro esempio:

Ingresso: [110, 22, 3330, 4444, 55555, 6]

Produzione: [110, 3330, 55555, 22, 4444, 6]

Usa la rappresentazione più naturale per gli elenchi della tua lingua. Non ci sono limiti alla complessità (ad es. L'allocazione di un elenco temporaneo è OK - non è necessario farlo sul posto).

PS Dovrebbe funzionare per l'elenco vuoto (input vuoto => output vuoto).


Questo è effettivamente l'inverso delle risposte attuali a questa domanda
Peter Taylor,

Possiamo supporre che tutti gli elementi dell'elenco siano positivi o non negativi o qualcosa del genere?
Martin Ender,

@ MartinBüttner Assumi qualcosa di ragionevole, forse anche se sono compresi nell'intervallo 0 ... 255.
Anatolyg,


Possiamo generare un elenco separato da virgole?
Oliver,

Risposte:




16

Pyth, 5

o~!ZQ

Provalo online o esegui una Suite di test

Spiegazione

o~!ZQ    ## implicit: Z = 0; Q = eval(input)
o   Q    ## sort Q using a supplied function
 ~!Z     ## Use the old value of Z, then set Z to be not Z
         ## This assigns a weight to each number in the list, for example given [0,1,2,3,4]
         ## This will give (value, weight) = [(0,0), (1,1), (2,0), (3,1), (4,0)]
         ## The values are sorted by weight and then by index
         ## This happens because Pyth is written in Python, which performs stable sorts

Genio! Bellissimo.
isaacg,

Aspetta, come funziona?
solo il

@justhalf Ho aggiunto qualche altra spiegazione, è chiaro?
FryAmTheEggman,

11

CJam, 7 byte

{2/ze_}

Spinge un blocco (la cosa più vicina a una funzione senza nome) che trasforma l'elemento stack superiore come richiesto.

Provalo qui.

Spiegazione

La spiegazione presuppone che la parte superiore dello stack sia l'array [0 1 2 3 4]. I valori effettivi non influiscono sul calcolo.

2/  e# Split the array into chunks of two: [[0 1] [2 3] [4]]
z   e# Zip/transpose, which works on ragged arrays: [[0 2 4] [1 3]]
e_  e# Flatten the result: [0 2 4 1 3]

9

Labyrinth , 28 25 24 23 22 byte

" >
?!?:|}\{@
@\?"":)!

È stato divertente! :) Questo è di gran lunga il programma Labyrinth più densamente compresso che ho scritto finora. Avevo così tante versioni a 20 e 21 byte che quasi funzionavano che sto ancora dubitando che sia ottimale ...

Questo prende l'input come un elenco di numeri interi positivi (con un delimitatore arbitrario) e stampa il risultato su STDOUT come numeri interi delimitati da avanzamento riga.

La caccia a 20/21 byte: ho controllato tutti i programmi del modulo

" XX
?!?X}\{@
@\?XX)!

dove Xc'è un carattere ragionevole per forza bruta, ma non ha trovato soluzioni valide. Ovviamente ciò non significa che non esiste una soluzione più breve, ma non è possibile forzare i programmi a 20 byte senza una discreta quantità di ipotesi sulla sua struttura.

Spiegazione

(La spiegazione è leggermente obsoleta, ma non sono ancora convinto che la soluzione sia ottimale, quindi aspetterò con l'aggiornamento.)

Quindi, normalmente i programmi Labyrinth dovrebbero apparire come labirinti. Mentre il puntatore dell'istruzione si trova in un corridoio, seguirà quel corridoio. Quando l'IP colpisce qualsiasi tipo di giunzione, la direzione viene determinata in base al valore massimo dello stack principale di Labyrinth (Labyrinth ha due stack, con un numero infinito di zero nella parte inferiore). Ciò significa normalmente che qualsiasi loop non banale sarà piuttosto costoso, perché se si dispone di celle non a parete in tutto il luogo tutto è una giunzione, e nella maggior parte dei casi la parte superiore dello stack non avrà il valore giusto per l'IP per prendere la strada che vorresti che prendesse. Quindi, ciò che fai è allargare i loop in modo che abbiano un intero al centro con solo un punto di entrata e uscita ben definiti ciascuno.

Ma questa volta sono stato davvero fortunato e tutto si è adattato così bene insieme, che ho potuto comprimere tutto in un grosso gruppo. :)

Il flusso di controllo inizia a _sud. La _spinge uno zero nello stack principale. Potrebbe sembrare una no-op, ma ciò aumenta la profondità (non implicita) dello stack di 1cui avremo bisogno in seguito.

?legge un numero intero da STDIN. Se non ci sono più numeri interi da leggere, questo spinge zero. In tal caso, l'IP continua a spostarsi a sud e @termina immediatamente il programma (perché l'elenco di input è vuoto). Altrimenti, l'IP gira verso est.

Ora stiamo entrando in un circuito molto stretto con due punti di uscita:

 !?;
 \?
  ;

!stampa il numero intero su STDOUT, lasciando solo uno zero nello stack. L'IP continua a spostarsi verso est e ?legge il numero intero successivo. Se questo è diverso da zero, prendiamo una destra e ci spostiamo a sud. ?ne legge un altro (il prossimo indice pari). Ancora una volta, se questo è diverso da zero, prendiamo una destra e ci spostiamo a ovest.

Quindi \stampa un avanzamento di riga senza cambiare la pila, quindi prendiamo un altro a destra, spostandoci verso nord. !stampa il successivo numero intero di indice pari. Poiché ora c'è almeno un intero (positivo) indice dispari nello stack, continuiamo a girare a destra e il ciclo si ripete.

Una volta che uno di questi ?colpisce la fine dell'elenco, spingono uno zero e si spostano direttamente sul corrispondente ;, che scarta quello zero.

Nel caso in cui ci fosse un solo elemento nell'elenco, abbiamo finito (perché l'abbiamo stampato subito), quindi l'IP continuerebbe a spostarsi verso est fino al @, terminando di nuovo il programma (stampando un trailing avanzamento linea lungo la strada).

Altrimenti, dobbiamo stampare anche gli interi con indice dispari. In tal caso i due percorsi (dai due punti di uscita del primo anello) si fondono nel mezzo ", girando verso est in entrambi i casi.

_spinge uno zero per evitare di svoltare a sinistra in @, e ;scarta quello zero. Ora entriamo in un nuovo ciclo:

     "}
     ""

L'IP entra nella cella in basso a sinistra, spostandosi verso nord, andando in senso orario attorno al circuito. L' }sposta cima alla pila principale rispetto allo stack ausiliario. Mentre c'è ancora un elemento nello stack, l'IP continua a fare le sue cose. Una volta che tutto è stato spostato nello stack ausiliario (e invertito nel processo), l'IP continua invece a spostarsi verso est, entrando nell'ultimo loop:

       \{@
       #!

\stampa di nuovo un avanzamento riga, {sposta un oggetto dalla pila ausiliaria alla pagina principale. Se quello era ancora un elemento dell'elenco, sarà positivo e l'IP diventerà Sud, dove viene stampato l'elemento !. Quindi #spinge la profondità dello stack (e ora è qui che l'iniziale _è importante, perché ciò #garantisce una profondità dello stack positiva), in modo che l'IP giri ancora a destra, attraverso \e di {nuovo.

Dopo aver stampato tutto, {estrae uno zero dalla parte inferiore dello stack ausiliario, l'IP continua verso est e @termina il programma.


8

MATLAB, 24

@(x)x([1:2:end 2:2:end])

simile a quello di Python.

Grazie @LuisMendo per aver salvato 2 byte!


1
Hey! Piacere di vederti in PPCG!
Luis Mendo,

3
Un po 'più corto:@(x)x([1:2:end 2:2:end])
Luis Mendo,

@LuisMendo Haha Ho un po 'paura del codegolf, ma questo è stato così facile per MATLAB! Grazie per la punta;)
Brain Guider,

6

Haskell , 37 byte

concat.foldr(\x[l,r]->[x:r,l])[[],[]]

Provalo online!

Il foldrcostruisce in modo ricorsivo l'elenco ancora e la lista dispari. La preparazione di un elemento all'elenco viene aggiornata anteponendola all'elenco dispari e chiamandolo il nuovo elenco pari e chiamando il precedente elenco pari il nuovo elenco dispari. Quindi, la coppia [l,r]viene concaternata l++r.

Grazie a Ørjan Johansen per aver salvato 5 byte usando liste a due elementi al posto delle tuple.


42 byte:

f l=[x|p<-[even,odd],(i,x)<-zip[0..]l,p i]

Aggiunge indici all'elenco le filtra quelli pari o dispari.


g(a:_:l)=a:(g l)
g l=l
f l=g l++(g$drop 1 l)

Ancora un altro formato, per 44. La funzione gprende ogni elemento anche indicizzato. Gli indici dispari vengono ottenuti facendo cadere prima un elemento, quindi applicandolo g. Se lfosse garantito non vuoto, potremmo tranquillamente fare solo tailper 41

g(a:_:l)=a:(g l)
g l=l
f l=g l++g(tail l)

1
ancora un'altra variante (39 byte): l#(a:b:c)=a:(l++[b])#c;l#x=x++l;f=([]#)con fessere la funzione principale.
nimi,

@nimi Questa è una bella soluzione, dovresti pubblicarla.
xnor

No, includilo nel tuo post. È solo una combinazione dei tuoi # 2 e # 3.
nimi,

1
Puoi salvare 5 byte sulla tua seconda versione usando liste e concatinvece di tuple e uncurry(++).
Ørjan Johansen,

5

PowerShell v3 +, 75 67 49 47 byte

$l=,@()*2
$args|%{$l[($f=!$f)]+=$_}
$l[0]
$l[1]

Provalo online!

Si aspetta input tramite splatting, come mostrato sul collegamento TIO.

Crea una matrice $lcome una matrice di array, quindi convoglia l'input $argsin un ciclo |%{}. Ogni volta attraverso il ciclo, aggiungiamo un elemento a una delle due matrici $lsecondarie capovolgendo la $fvariabile usando la logica booleana. La prima volta, $fè $null, il !cui è $trueo 1quando si indicizza in un array. Ciò significa che il primo elemento viene inserito nel secondo array di $l, quindi è per questo che $l[1]viene generato per primo.

Puntelli a TessellatingHeckler per l'assistenza golfistica e questa variazione.
-2 byte grazie a mazzy.


Avvertenze

Andando rigorosamente mentre la domanda è scritta, questo è tecnicamente non valido, poiché PowerShell non ha un concetto di "elenchi" come oggetti pseudo-immutabili, solo array o tabelle hash (ovvero dizionari). Quindi, sto trattando la riga della domanda " Usa la rappresentazione più naturale per gli elenchi che il tuo linguaggio ha " come chiedere informazioni sugli array, poiché è il PowerShell più vicino. Inoltre, l'output è un elemento per riga, poiché questo è il modo predefinito di PowerShell per scrivere un array. Ciò significa che viene immesso un input di (0,1,2,3,4)volontà 0\r\n2\r\n4\r\n1\r\n3\r\n.


47 byte - $args+ splatting invece $inpute ,@()*2invece@(),@()
mazzy

4

F #, 79 77 56

fun x->List.foldBack(fun x (l,r)->x::r,l)x ([],[])||>(@)

Basato su una delle risposte di Haskell

fun x->x|>List.indexed|>List.partition(fst>>(&&&)1>>(=)0)||>(@)|>List.map snd

Prima indicizziamo la lista, quindi la partizioniamo con criteri: prima voce (l'indice) andata con 1 uguale a 0.
Questo ci dà una coppia di liste di coppie; il primo elenco conterrà tutti i pari indicizzati e l'altro le probabilità indicizzate.
Da ciò riassembliamo le due liste con l'operatore append e infine scartiamo l'indice.

Modifica: perso uno ovvio non c'è bisogno di nominare arg "xs" (abitudini), quindi può ridurre a un nome di 1 lettera


Ho anche un potenziale 76 byte uno che è sostanzialmente lo stesso ma definito come composizione della funzione. Il problema è che non viene compilato come valore ma funzionerà efficacemente con qualsiasi argomento dell'elenco fornito in modo incerto se va bene o no:

List.indexed>>List.partition(fst>>(&&&)1>>(=)0)>>fun(e,o)->e@o|>List.map snd

Nota: List.indexed è disponibile solo da F # 4.0 nonostante non sia ancora documentato in MSDN


Tecnologia all'avanguardia, fantastico!
Anatolyg

1
@anatolyg È funvero?
Conor O'Brien,

Penso che questo sia simile al codice Perl 6 che ho provato per la prima volta. -> \xs { xs.pairs.classify( *.key%%2, :as( *.value ) ).map( *.value.Slip ) }Supponendo che |>in F # equivale all'incirca all'operatore di alimentazione a destra ==>in Perl 6. Sto anche solo indovinando cosa fst>>(&&&)1>>(=)0fa
Brad Gilbert b2gills

4

JavaScript (ES6), 52 byte

Lo fa anche in un passaggio

x=>x.map((v,i)=>x[(i*=2)>=(z=x.length)?i-z+--z%2:i])


Puoi omettere F=dall'inizio; puoi salvare un byte usando questo:(i*=2)>=(z=x.length)?i-z+--z%2:i
Conor O'Brien del

@ CᴏɴᴏʀO'Bʀɪᴇɴ Bella idea grazie!
George Reith,


3

J, 8 byte

/:0 1$~#

Questo è un verbo monadico (a un argomento), usato come segue:

  (/:0 1$~#) 110 22 3330 4444 55555 6
110 3330 55555 22 4444 6

Spiegazione

/:        Sort the input array according to
  0 1     the array 0 1
     $~   repeated enough times to be of length
       #  length of input

1
Un'alternativa è /:0:`1:\che è anche di 8 byte.
miglia

3

Gelatina , 4 byte

s2ZF

Provalo online!

Basato sulla risposta di Martin CJam

s2ZF - Main link. Argument: L (a list) e.g.  [110, 22, 3330, 4444, 55555, 6]
s2   - Split into chunks of length 2         [[110, 22], [3330, 4444], [55555, 6]]
  Z  - Columns                               [[110, 3330, 55555], [22, 4444, 6]]
   F - Flatten                               [110, 3330, 55555, 22, 4444, 6]

2

Mathematica, 40 byte

#[[;;;;2]]~Join~If[#=={},#,#[[2;;;;2]]]&

{}[[2;;;;2]] genererà un errore.


2

Burlesque, 12 byte

J2ENj[-2EN_+

Utilizzo come in:

blsq ) {0 1 2 3 4}J2ENj[-2EN_+
{0 2 4 1 3}
blsq ) {110 22 3330 4444 55555 6}J2ENj[-2EN_+
{110 3330 55555 22 4444 6}

Spiegazione:

J     -- duplicate
2EN   -- every 2nd element
j     -- swap
[-    -- tail
2EN   -- every 2nd element
_+    -- concatenate parts

Sebbene una volta rilasciato il nuovo aggiornamento, puoi farlo con il nuovo Unmerge integrato (che fa il contrario del merge **integrato):

blsq ) {110 22 3330 4444 55555 6}J2ENj[-2EN**
{110 22 3330 4444 55555 6}

2

Perl, 35 33 byte

perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'

31 byte + 2 byte per -ap. Legge una stringa delimitata da spazi da STDIN:

$ echo 0 1 2 3 4 | perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'
0 2 4 1 3

$ echo 110 22 3330 4444 55555 6 | perl -ape 'push@{$|--},$_ for@F;$_="@0 @1"'
110 3330 55555 22 4444 6

Quando l'input è vuoto, stampa un singolo spazio, che considererei equivalente a un elenco vuoto. In caso contrario, può essere risolto al costo di 4 byte con:

perl -anE 'push@{$|--},$_ for@F;$,=$";say@0,@1'

(richiede Perl 5.10+, stampa una nuova riga finale)

o al costo di 5 byte con:

perl -ape 'push@{$|--},$_ for@F;$_=join$",@0,@1'

(nessuno spazio vuoto finale)

Come funziona

Questa soluzione utilizza il -aflag, che divide l'input negli spazi bianchi e inserisce i risultati nella @Fmatrice.

La vera magia accade nel push:

push@{$|--},$_

La $|variabile viene normalmente utilizzata per forzare il flush dell'output, ma ha un'altra proprietà interessante: quando viene decrementata ripetutamente, il suo valore passa da 0 a 1.

perl -E 'say $|-- for 0..4'
0
1
0
1
0

Sfruttando il fatto che non ci sono restrizioni sugli identificatori specificati tramite il dereferenziamento simbolico , spingiamo alternativamente gli elementi dell'array sugli array @0e sugli @1array, quindi finiamo @0con tutti gli elementi @1con indice pari e con le probabilità. Quindi concateniamo semplicemente gli array stringiti per ottenere il nostro output.


2

C, 70

Niente di speciale, solo una funzione di mappatura dell'indice.

a=0;main(int c,int** v){for(c--;a<c;)puts(v[1+a*2%c+!(a++<c/2|c%2)]);}

Meno golf

a=0;
main(int c, int** v) {
  for(c--; a<c;)
    puts(v[1 + a*2%c + !(a++ < c/2 | c%2) ]);
}

1

Pyth, 8 byte

+%2Q%2tQ

Relativamente semplice


1

Vitsy, 22 byte

Vitsy non è stato davvero fatto per fare questo ...

r '' Vl2 / \ [N {VO] l \ [NVO]
r Invertire lo stack di input numerico implicito.
 '' V Salva il carattere "spazio" come variabile finale globale.
     l2 / \ [....] Ripeti il ​​contenuto tra parentesi per la lunghezza dell'input
                        pila divisa per 2.
          N {VO Emette l'elemento superiore dello stack come numero, quindi sposta
                        la pila una volta a sinistra, spingere uno spazio, emetterlo.
               l \ [...] Per il resto della pila, ripeti più volte ...
                  NVO Emette l'elemento superiore dello stack come un numero separato 
                        da uno spazio.

1

Perl 6 , 25 byte

Questa è la lambda più corta che ho potuto inventare.

{|.[0,2...*],|.[1,3...*]} # 25 byte "Texas" version
{|.[0,2…*],|.[1,3…*]}     # 25 byte "French" version
say {|.[0,2…*],|.[1,3…*]}( ^5 ); # (0 2 4 1 3)␤

say ((0..4),('m'..'q'),(5..9)).map: {|.[0,2…*],|.[1,3…*]}
# ((0 2 4 1 3) (m o q n p) (5 7 9 6 8))␤


# bind it as a lexical sub
my &foo = {|.[0,2…*],|.[1,3…*]}

say foo [110, 22, 3330, 4444, 55555, 6]; # (110 3330 55555 22 4444 6)␤

say [~] foo 'a'..'z' # acegikmoqsuwybdfhjlnprtvxz␤

1

Minkolang 0,12 , 15 byte

$nI2:[i1+g]r$N.

Provalo qui.

Spiegazione

$n                 Read in all of input as numbers
  I2:              The length of the stack divided by 2 (n)
     [             Open for loop that repeats n times
      i1+          Loop counter + 1
         g         Gets the (i+1)th item from the stack and puts it on top
          ]        Close for loop
           r       Reverse the stack (for outputting)
            $N.    Output the whole stack as numbers and stop.

1

R, 49 byte

q<-function(x)c(x[seq(x)%%2==1],x[seq(x)%%2==0])

Chiamalo come q (blah). Oppure, se x contiene già l'elenco da riorganizzare, allora

c(x[seq(x)%%2==1],x[seq(x)%%2==0])

è solo 35 byte.


1

F #, 64

fun x->List.mapi(fun i l->l,i%2)x|>List.sortBy snd|>List.map fst

Ispirato dalla risposta di Sehnsucht (ma non abbastanza rappresentante per commentare).

Mappa ogni valore su una tupla in cui la seconda voce è il modulo dell'indice dell'elenco, ordina per modulo, quindi esegue il mapping al valore originale.


1

Prolog, 103 byte

r([E,O|T],[E|A],[O|B]):-r(T,A,B).
r([],[],[]).
r([E],[E],[]).
p(L):-r(L,A,B),append(A,B,X),write(X).

Esempio

>p([1,2,3,4,5]).
[1,3,5,2,4]

1

corehut bash e GNU, 68 byte

Partiamo dal presupposto che l'elenco è separato da newline e trasmesso sullo standard input.

(paste - <(seq 0 5 9999)|tee x|grep 0$;grep 5$<x)|cut -f1|grep -v ^$

Sfortunatamente questo ignorerà qualsiasi input oltre l'indice 1999, quindi non soddisfa del tutto le specifiche.

Inoltre, blocca un file temporaneo codificato ('x'), che potrebbe essere problematico se eseguito in parallelo e non lo rimuove in seguito. Mi dispiace per quello!


1

PHP, 78 69 byte

PHP può tagliare e affettare, ma non interlacciare array; questo rende un po 'ingombrante:

function(&$a){while($i++<count($a)>>1)$a[]=array_splice($a,$i,1)[0];}

Chiama per riferimento o provalo online .


primo approccio (programmi per 78 byte):

for(;++$i<$argc;)echo",",$argv[$i++];for($i=1;++$i<$argc;)echo",",$argv[$i++];

stampa una virgola iniziale; inserire [!$i]prima del primo $argvper rimuoverlo.

Altre due soluzioni da 78 byte (stampa una virgola iniziale e una virgola finale):

for($n=$argc-2|1;++$i<$argc*2;)$i&1?print",".$argv[$i]:$argv[$n+=2]=$argv[$i];
for($n=$argc-2;++$i<$argc*2;)$i&1?print",".$argv[$i]:$argv[1|$n+=2]=$argv[$i];

Corri con php -nr '<code>' <arguments>o provali online


1

Japt , 3 byte

ñÏu

Provalo

ñÏu     :Implicit input of array
ñ       :Sort by
 Ï      :Passing the 0-based index of each through a function
  u     :  Modulo 2 of index

ó c

Provalo

ó c     :Implicit input of array
ó       :Split into 2 arrays of every 2nd item
  c     :Flatten
        :Implicit output

0

Clojure / ClojureScript, 52 byte

(defn f[l](flatten(map #(take-nth 2 %)[l(rest l)])))

Scritto in un REPL di ClojureScript, dovrebbe essere valido anche Clojure.



0

Hassium , 191 byte

Questo è stato piuttosto lungo :(
Legge l'array da args, quindi eseguilo conhassium file.has 0 1 2 3 4

func main(){a=args;e,o=[]for(c=0;c<a.length;c++)if(c%2==0)e.add(a[c])else o.add(a[c])print("["+(e+o).toString().replace("{", "").replace("}", "").replace("Array", "").replace("  ", "")+"]");}

Esegui e vedi espanso con test case qui

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.