Ordina un elenco nidificato


23

È necessario scrivere un programma o una funzione che ordina un elenco nidificato. Ecco le regole per ordinare un elenco nidificato:

Prendiamo questo elenco come esempio:

((5, 2), 2, 7, (2, 1, (3, 4)), 9)

Ogni elemento in questo elenco ha una "priorità". Un elemento conta come un numero o un elenco secondario. Innanzitutto, ottieni la priorità di ciascun elemento alla stessa profondità. Se un elemento è solo un numero, la sua priorità è uguale al numero stesso. Se un elemento è un elenco secondario, la sua priorità è la somma di tutti i numeri in esso contenuti, senza includere alcun elenco secondario secondario.

Quindi, le priorità di tutti gli elementi di profondità 1 sono:

 (  7 )  2  7  (    3       )  9
((5, 2), 2, 7, (2, 1, (3, 4)), 9)

Ordina ogni elemento per priorità. In caso di pareggio, è necessario mantenere lo stesso ordine dell'elenco originale.

 2  (     3      )  (  7 )  7  9
(2, (2, 1, (3, 4)), (5, 2), 7, 9) 

Ripetere l'operazione per ogni elenco secondario. Quindi su questo elenco secondario

(2, 1, (3, 4))

Le nostre priorità sembrano:

 2  1  (  7  )
(2, 1, (3, 4))

Così ordinato, sembra:

(1, 2, (3, 4))

(3, 4)è già in ordine, quindi abbiamo finito. Ripeti per (5, 2)quali risultati (2, 5)e abbiamo finito! Il nostro elenco finale è:

(2, (1, 2, (3, 4)), (2, 5), 7, 9) 

Regole:

  • Altamente dubbio, ma nel caso in cui Mathematica abbia qualcosa per questo, non sono ammessi builtin di ordinamento degli elenchi nidificati. Sono consentite funzioni di ordinamento regolari .

  • L'I / O può essere in qualsiasi formato ragionevole.

  • Ogni elenco secondario conterrà almeno un numero o elenco. Inoltre, le liste secondarie possono essere nidificate a diversi livelli di profondità. Ad esempio, in (1, 2, (((3))))il (((3)))ha una priorità 0, poiché ha solo sottoliste in esso.

  • Gli elenchi non validi (parentesi non corrispondenti, non numeri, tipi di parentesi errati, numeri negativi, ecc.) Comportano un comportamento indefinito.

Test I / O:

(1, 2, 3) ---> (1, 2, 3)

(1, 2, 6, 3, 9, 8) ---> (1, 2, 3, 6, 8, 9)

(4, 3, (2), (1)) ---> ((1), (2), 3, 4)

(4, 3, (2), ((1))) ---> (((1)), (2), 3, 4)

(5, (1, 2, (9, 8))) ---> ((1, 2, (8, 9)), 5)

(3, (1, 2), (2, 1)) ---> (3, (1, 2), (1, 2))

(3, (1, 2, (99)), (2, 1, (34))) ---> (3, (1, 2, (99)), (1, 2, (34)))

(7, 2, (1, (9, 12)), (4, 3, 2, (1, 2))) ---> ((1, (9, 12)), 2, 7, (2, 3, (1, 2), 4))

Vince la risposta più breve in byte.


Possiamo supporre che i numeri siano numeri interi?
Isaacg,

@isaacg Sì, puoi.
DJMcMayhem

Risposte:


5

Gelatina, 13 byte

fFSµ€Ụị߀µ¹<?

Provalo online! o verifica tutti i casi di test .

Come funziona

fFSµ€Ụị߀µ¹<?  Main link. Input: A (list)

   µ€          Apply the chain to the left to each item B in A.
 F             Flatten B.
f              Filter; intersect B with flattened B, yielding a list.
               This returns the numbers in B if B is a list, [B] if B is a number.
  S            Compute the sum of the resulting list.
     Ụ         Sort the indices of A according to the computed sums.
       ߀      Recursively apply the main link to each B in A.
      ị        Retrieve the items of the list (right) at those indices (left).
         µ     Convert the preceding chain into a single link.
            ?  If:
           <     A compared with itself is truthy:
                   Execute the link to the left.
          ¹      Else, apply the identity function to A.

Il confronto ( <) di un numero con se stesso produce 0 (falsy), ma il confronto di un elenco non vuoto con se stesso produce un elenco di 0 (verità), quindi <può essere utilizzato per distinguere i numeri dagli elenchi.


0 è falso, ma una casella di 0 è vera, ma una casella vuota è falsa. Interessante come funziona Python. : P
gatto

A me sembrano 25 byte (se codificati in UTF-8).
Rotsor,

@Rotsor Sembra giusto. Tuttavia, Jelly utilizza una codepage personalizzata che codifica tutti i 256 caratteri che comprende come singoli byte.
Dennis,

17

Python 2, 114 101 78 73 62 byte

k=lambda t:t*(t<[])or t.sort(key=k)or sum(z for z in t if[]>z)

Ho saputo che c'era un modo migliore per filtrare le liste fuori.

Ordina un elenco di Python (e i suoi elenchi secondari) sul posto.

https://eval.in/540457 grazie @tac per avermi fatto sapere che le soluzioni sul posto sono accettabili e @xnor + @feersum per ulteriori ottimizzazioni!


1
Qualche altro ottimizzazione: k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
xnor

@xnor Penso che la soluzione non sia del tutto corretta: eval.in/540447 . Per questo esempio, ricerchiamo fino al primo elenco secondario e prendiamo l'iniziale zda esso, 5. Quindi nel condizionale, ordiniamo l'elenco su cui stiamo iterando (!), Quindi quando prendiamo lo z successivo è ANCHE 5, portando a una somma di 10. Ordiniamo quindi l'elenco esterno con queste chiavi e otteniamo [6, [1, 5]], che è errato come "Se c'è un pareggio, è necessario mantenere lo stesso ordine dell'elenco originale. " La cosa interessante è che chiamiamo sortentrambe le liste due volte, quindi questo accade solo su chiavi uguali: se la lista secondaria fosse inferiore, si riordinerebbe.
Orez,

Buona pesca. È divertente che l'iterazione continui con l'elenco ora ordinato. Sento che dovrebbe esserci ancora un modo più breve di attenersi Noneall'output di t.sort(key=k), ma non lo vedo.
xnor

Falseè 0 ai fini +e per estensione, sum. Tuttavia, non riesco a pensare a come salvare i byte.
CalculatorFeline

@CatsAreFluffy list.sortritorna None, no False.
Dennis,

4

Lua, 172 byte

function p(a)if type(a)~="table"then return a end s(a)local t=0 for i,v in next,a do t=t+p(v)end return t end
function s(t)table.sort(t,function(a,b)return p(a)<p(b)end)end

La funzione sordina una tabella Lua (una struttura di dati che funge da elenco tra le altre cose in Lua) posizionata secondo le regole.


Adoro come type(a)restituisce una stringa
cat

Finalmente una risposta usando Lua.
Leaky Nun,

3

Mathematica, 50 byte

#0/@SortBy[#,Tr@Cases[#,_Integer,{0,1}]&]~Check~#&

Semplice metodo ricorsivo che utilizza SortBy. Ignora i messaggi.


3

Haskell, 160 151 135 byte

import Data.List
data T=N Int|T[T]deriving Show
p(N x)=x
p(T t)=sum$[x|N x<-t]
f(N x)=N x
f(T t)=T$sortBy((.p).compare.p)$map f$t

Il primo problema sono gli elenchi nidificati. Haskell richiede che tutti gli elementi di un elenco abbiano lo stesso tipo; in particolare, un numero intero e un elenco di numeri interi non sono dello stesso tipo. In altre parole, un elenco annidato variabile non è un elenco, è un albero di rose!

Quindi, per prima cosa, dobbiamo definire un tipo di dati per i roseti:

data T = N Int | T [T]

(Rigorosamente, deriving Showè necessario solo se si desidera vedere i risultati. Ma questo è un tecnicismo.) Con questa definizione in atto, possiamo scrivere un elenco (1, 2, (3, 4))come

T [N 1, N 2, T [N 3, N 4]]

che è notevolmente meno leggibile. Ma comunque; è una banale traduzione meccanica. Prefisso ogni numero con Ne ogni sottostruttura con T.

Ora dobbiamo calcolare le priorità. Ciò sarebbe facile se la priorità di una sottostruttura fosse semplice la somma di tutti gli elementi in essa contenuti. Sarebbe un banale ciclo ricorsivo. Ma dal momento che non lo è, dobbiamo definire due funzioni: una che ricorre e una che non lo fa.

p (N x) = x
p (T t) = sum $ map q t

q (N x) = x
q _     = 0

Se dovessimo sommare tutti i sottoelementi, qnon sarebbe necessario esistere, salvando un numero enorme di personaggi. Oh bene!

Edit: In realtà, diversi commentatori sottolineano che si può evitare di qutilizzare una lista di comprensione: [ x | N x <- t]. Buona chiamata, ragazzi!

(In effetti, pnon dovrebbe esistere neanche; potremmo avere il compilatore generare automaticamente Ordun'istanza per noi in una manciata di caratteri, e questa implementazione predefinita corrisponderebbe alle specifiche.)

Infine, dobbiamo ricorsivo su tutti i sottoalberi e ordinarli:

f (N x) = N x
f (T t) = T $ sortBy (\ x y -> compare (p x) (p y)) $ map f $ t

Cioè, fordina un albero applicandosi in modo ricorsivo a tutti gli elementi ( map f) e quindi chiamando la sortByfunzione per ordinare il livello superiore. La prima riga dice che l'ordinamento di un numero non fa nulla ed è necessario per terminare la ricorsione.


2
sortBy (\ x y -> compare (p x) (p y))è giusto sortOn p. Utilizzare la versione infisso di mappa in p: sum$q<$>t.
nimi,

@nimi Dove è sortOndefinito? Ho sempre voluto sapere ...
MathematicalOrchid


2
puoi ancora radere circa 16 byte con il trucco di comprensione dell'elenco p(T t)=sum[x|N x<-t]e data T=N Int|T[T]deriving Show. :)
Will Ness,

1
hai incluso 2 byte per ogni nuova riga nel tuo conteggio? Penso che ci sia permesso di contarli come singoli . Inoltre, non è necessario $in sum$[x|N x<-t]. Quindi, 135-5-1 = 129. :)
Will Ness,

2

CLISP, 380 byte

(defun q(L)(if(null L)L(append(append(q(car(s(cdr L)(car L))))(list(car L)))(q(cadr(s(cdr L)(car L))))))))(defun s(L E)(if(not(atom(car L)))(setq L(cons(q(car L))(cdr L))))(cond((null L)'(nil nil))((<(v(car L))E)(list(cons(car L)(car(s(cdr L)E)))(cadr(s(cdr L)E))))(T(list(car(s(cdr L)E))(cons(car L)(cadr(s(cdr L)E)))))))(defun v(L)(if(atom L)L(apply'+(remove-if-not #'atom L))))

Chiamare la funzione q con un elenco.

Sono un pisolino, per favore non uccidermi ^^


Haha, speravo che qualcuno lo facesse in un attimo!
DJMcMayhem

1

Pyth, 15 byte

L?sIbbossI#NyMb

Suite di test

Una funzione ricorsiva, che funziona come segue:

L?sIbbossI#NyMb
L                  define y(b):
 ?sIb              If b is an integer:          (invariant under the s function)
     b             Return it.
            yMb    Else, apply y recursively to all of the elements of b,
      o            Then sort b by
        sI#N       For each element, the elements of that list that are integers.
                   This is luckily a nop on integers.
       s           Summed.

1

Java, 219 byte

import java.util.*;List f(List l){l.sort(Comparator.comparing(o->{if(o instanceof Integer)return(Integer)o;f((List)o);return((List) o).stream().filter(i->i instanceof Integer).mapToInt(i->(Integer)i).sum();}));return l;}

Con interruzioni di riga:

import java.util.*;
List f(List l){
    l.sort(Comparator.comparing(o -> {
        if (o instanceof Integer)
            return (Integer) o;
        f((List) o);
        return ((List) o).stream().filter(i -> i instanceof Integer).mapToInt(i -> (Integer) i).sum();
    }));
    return l;
}

C'è un sacco di casting in corso che aumenta davvero il conteggio dei byte. : P

I valori interi vengono inseriti in un comparatore e gli elenchi nidificati vengono ordinati per primi prima che la somma dei soli valori interi venga data al comparatore. Questi valori sono il modo in cui il comparatore determina la loro posizione all'interno dell'elenco quando viene ordinato.

Provalo qui .


1
Ecco la stessa tecnica a 154 byteint f(List l){l.sort(Comparator.comparing(o->o instanceof Integer?(int)o:f((List)o)));return l.stream().mapToInt(o->o instanceof Integer?(int)o:0).sum();}
Andreas

Penso che ci sia anche molto altro da spremere.
Andreas,

Ma ci sono un paio di problemi: non è possibile convertire esplicitamente Objectin intquesto modo e la sfida sembra richiedere l'output di un elenco.
TNT,

In realtà, si salva 1 byte modificando l'istanza per verificare l'elenco anziché intero. Il numero intero è di 7 byte senza parentesi graffe, ma List contiene 6 byte.
Blue

@TNT Puoi lanciare un oggetto su una primitiva in java 1.7 o successiva. Naturalmente se l'oggetto è nullo otterrai un npe. Non vedo alcun problema con l'ordinamento dell'elenco in atto, la sfida non sembra parlare direttamente al problema.
Andreas

0

JavaScript (ES6), 86 byte

f=a=>a.map?a.map(f).sort((a,b)=>p(a)-p(b),p=a=>a.map?a.map(a=>t+=a.map?0:a,t=0)|t:a):a

Tutto quel controllo dell'array :-(


1
map.map.map.map.map.map.map.map.map
gatto
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.