Ordenar una lista anidada

23

Debe escribir un programa o función que clasifique una lista anidada. Estas son las reglas para ordenar una lista anidada:

Tomemos esta lista como ejemplo:

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

Cada elemento en esta lista tiene una "prioridad". Un elemento cuenta como un número o una sublista. Primero, obtenga la prioridad de cada elemento a la misma profundidad. Si un elemento es solo un número, su prioridad es la misma que el número mismo. Si un elemento es una sublista, su prioridad es la suma de todos los números que contiene, sin incluir ninguna sublista.

Entonces, las prioridades de todos los elementos de la profundidad 1 son:

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

Ordenar cada elemento por prioridad. Si hay un empate, debe mantener el mismo orden que la lista original.

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

Repita para cada sublista. Entonces en esta sublista

(2, 1, (3, 4))

Nuestras prioridades se ven así:

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

Así ordenado, se ve así:

(1, 2, (3, 4))

(3, 4)ya está ordenado, así que hemos terminado. Repita para (5, 2)que resultados (2, 5)y hemos terminado! Nuestra lista final es:

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

Reglas:

  • Muy dudoso, pero solo en caso de que Mathematica tenga algo para esto, no se permite la creación de listas anidadas. Funciones de ordenación regulares están permitidos.

  • Las E / S pueden estar en cualquier formato razonable.

  • Cada sublista contendrá al menos un número o lista. Además, las sublistas se pueden anidar en varios niveles de profundidad. Por ejemplo, en (1, 2, (((3))))el (((3)))tiene una prioridad de 0, ya que sólo tiene sublistas en ella.

  • Las listas no válidas (paréntesis no coincidentes, no números, tipos de paréntesis incorrectos, números negativos, etc.) dan como resultado un comportamiento indefinido.

Prueba de E / S:

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

La respuesta más corta en bytes gana.

DJMcMayhem
fuente
¿Podemos suponer que los números son enteros?
isaacg
@isaacg Sí, puedes.
DJMcMayhem

Respuestas:

5

Jalea, 13 bytes

fFSµ€Ụị߀µ¹<?

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

Cómo funciona

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.

Al comparar ( <) un número consigo mismo se obtiene 0 (falso), pero al comparar una lista no vacía consigo mismo se obtiene una lista de 0 (verdadero), por lo que <se puede utilizar para distinguir números de listas.

Dennis
fuente
0 es falso, pero un cuadro de 0 es verdadero, pero un cuadro vacío es falso. Interesante cómo funciona Python. : P
gato
A mí me parece 25 bytes (cuando está codificado en UTF-8)
Rotsor
@Rotsor Eso suena bien. Sin embargo, Jelly usa una página de códigos personalizada que codifica los 256 caracteres que entiende como bytes individuales.
Dennis
17

Python 2, 114 101 78 73 62 bytes

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

Yo sabía que había una mejor manera de listas de filtros fuera.

Ordena una lista de Python (y sus sublistas) en el lugar.

https://eval.in/540457 ¡ gracias @tac por informarme que las soluciones en el lugar son aceptables, y @xnor + @feersum por más optimizaciones!

Orez
fuente
1
Un poco más de optimización: k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
xnor
@xnor Creo que la solución no es del todo correcta: eval.in/540447 . Para este ejemplo, recurrimos a la primera sublista y tomamos la inicial zde ella, 5. Luego, en el condicional, clasificamos la lista sobre la que estamos iterando (!), Entonces cuando tomamos la siguiente z es TAMBIÉN 5, conduciendo a una suma de 10. Luego ordenamos la lista externa con estas teclas y obtenemos [6, [1, 5]], que es incorrecto como "Si hay un empate, debe mantener el mismo orden que la lista original. " Lo interesante es que llamamos sorta ambas listas dos veces, por lo que esto solo ocurre en claves iguales: si la sublista fuera menor, se ordenaría de nuevo.
Orez
Buena atrapada. Es curioso que la iteración continúe con la lista ahora ordenada. Siento que todavía debería haber una forma más corta de pegarse en la Nonesalida de t.sort(key=k), pero no lo estoy viendo.
xnor
Falsees 0 para los fines de +y por extensión, sum. Sin embargo, no puedo pensar en cómo eso ahorra bytes.
CalculatorFeline
@CatsAreFluffy list.sortregresa None, no False.
Dennis
4

Lua, 172 bytes

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 función sclasifica una tabla Lua (una estructura de datos que sirve como una lista entre otras cosas en Lua) en su lugar de acuerdo con las reglas.

Trebuchette
fuente
Me encanta cómo type(a)devuelve una cadena
gato
Finalmente una respuesta usando Lua.
Leaky Nun
3

Mathematica, 50 bytes

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

Método recursivo simple que utiliza SortBy. Ignora los mensajes.

LegionMammal978
fuente
3

Haskell, 160 151 135 bytes

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

El primer problema son las listas anidadas. Haskell requiere que todos los elementos de una lista tengan el mismo tipo; en particular, un entero y una lista de enteros no son del mismo tipo. En otras palabras, una lista anidada de variables no es una lista, ¡es un rosal!

Primero, tenemos que definir un tipo de datos para rosales:

data T = N Int | T [T]

(Estrictamente, deriving Showsolo es necesario si desea ver los resultados. Pero eso es un tecnicismo). Con esta definición, podemos escribir una lista (1, 2, (3, 4))como

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

que es considerablemente menos legible. Pero lo que sea; Es una traducción trivial y mecánica. Prefije cada número con Ny cada subárbol con T.

Ahora necesitamos calcular prioridades. Esto sería fácil si la prioridad de un subárbol fuera simple la suma de todos los elementos que contiene. Eso sería un bucle recursivo trivial. Pero como no lo es, necesitamos definir dos funciones: una que se repite y otra que no.

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

q (N x) = x
q _     = 0

Si tuviéramos que sumar todos los subelementos, entonces qno necesitaría existir, salvando una gran cantidad de caracteres. ¡Oh bien!

Editar: En realidad, varios comentaristas señalan que se puede evitar qel uso de una lista por comprensión: [ x | N x <- t]. Buena llamada, chicos!

(De hecho, ptampoco necesitaría existir; podríamos hacer que el compilador genere automáticamente una Ordinstancia para nosotros en un puñado de caracteres, y esta implementación predeterminada coincidiría con la especificación).

Finalmente, tenemos que recurrir a todos los subárboles y ordenarlos:

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

Es decir, fclasifica un árbol aplicándose recursivamente a todos los elementos ( map f) y luego llamando a la sortByfunción para ordenar el nivel superior. La primera línea dice que ordenar un número no hace nada y es necesario para terminar la recursión.

Orquídea matemática
fuente
2
sortBy (\ x y -> compare (p x) (p y))es justo sortOn p. Utilice la versión infija del mapa en p: sum$q<$>t.
nimi
@nimi ¿Dónde se sortOndefine? Siempre quise saber ...
MathematicalOrchid
2
todavía se puede afeitarse unos 16 bytes con el truco lista por comprensión, p(T t)=sum[x|N x<-t]y data T=N Int|T[T]deriving Show. :)
Will Ness
1
¿ha incluido 2 bytes por cada nueva línea en su recuento? Creo que se nos permite contarlos como solteros . Además, no hay necesidad de $entrar sum$[x|N x<-t]. Entonces, 135-5-1 = 129. :)
Will Ness
2

CLISP, 380 bytes

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

Llame a la función q con una lista.

Soy un novato lisp, por favor no me mates ^^

Joba
fuente
Jaja, ¡esperaba que alguien lo hiciera en ceceo!
DJMcMayhem
1

Pyth, 15 bytes

L?sIbbossI#NyMb

Banco de pruebas

Una función recursiva, que funciona de la siguiente manera:

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.
isaacg
fuente
1

Java, 219 bytes

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 saltos de línea:

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

Hay una gran cantidad de casting que realmente acumula el recuento de bytes. :PAGS

Los valores enteros se introducen en un Comparador, y las listas anidadas se ordenan primero antes de que la suma de solo los valores enteros se den al Comparador. Estos valores son cómo el Comparador determina su posición dentro de la lista cuando se ordena.

Probarlo aquí .

TNT
fuente
1
Aquí está la misma técnica a 154 bytesint 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
Creo que también hay mucho más que exprimir.
Andreas
Pero hay un par de problemas: no se puede convertir explícitamente Objecta intesa manera, y el desafío parece requerir que una lista es la salida.
TNT
En realidad, guarda 1 byte cambiando la instancia de para verificar Lista en lugar de Entero. El entero es de 7 bytes sin llaves, pero la lista tiene 6 bytes.
Azul
@TNT Puede lanzar un Objeto a una primitiva en Java 1.7 o superior. Por supuesto, si el objeto es nulo, obtendrás un npe. No veo ningún problema para ordenar la lista en su lugar, el desafío no parece hablar directamente del problema.
Andreas
0

JavaScript (ES6), 86 bytes

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

Toda esa comprobación de matriz :-(

Neil
fuente
1
map.map.map.map.map.map.map.map.map
gato