Trier une liste imbriquée

23

Vous devez écrire un programme ou une fonction qui trie une liste imbriquée. Voici les règles de tri d'une liste imbriquée:

Prenons cette liste comme exemple:

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

Chaque élément de cette liste a une "priorité". Un élément compte comme un nombre ou une sous-liste. Tout d'abord, obtenez la priorité de chaque élément à la même profondeur. Si un élément n'est qu'un nombre, sa priorité est la même que le nombre lui-même. Si un élément est une sous-liste, sa priorité est la somme de tous les nombres qu'il contient, à l'exclusion des sous-sous-listes.

Ainsi, les priorités de tous les éléments de profondeur 1 sont:

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

Triez chaque élément par priorité. S'il y a égalité, vous devez conserver le même ordre que la liste d'origine.

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

Répétez l'opération pour chaque sous-liste. Donc sur cette sous-liste

(2, 1, (3, 4))

Nos priorités ressemblent à:

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

Ainsi trié, il ressemble à:

(1, 2, (3, 4))

(3, 4)est déjà trié, nous avons donc terminé. Répétez l'opération pour les (5, 2)résultats (2, 5)et nous avons terminé! Notre liste finale est:

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

Règles:

  • Très douteux, mais juste au cas où Mathematica aurait quelque chose pour cela, aucune intégration de tri de liste imbriquée n'est autorisée. Les fonctions de tri régulières sont autorisées.

  • Les E / S peuvent être dans n'importe quel format raisonnable.

  • Chaque sous-liste contiendra au moins un numéro ou une liste. De plus, les sous-listes peuvent être imbriquées à plusieurs niveaux. Par exemple, dans (1, 2, (((3))))le (((3)))a une priorité de 0, car il ne contient que des sous-listes.

  • Les listes non valides (parenthèses sans correspondance, non-nombres, types de parenthèses incorrects, nombres négatifs, etc.) entraînent un comportement indéfini.

Tester les 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 réponse la plus courte en octets gagne.

DJMcMayhem
la source
Pouvons-nous supposer que les nombres sont des nombres entiers?
isaacg
@isaacg Oui, vous le pouvez.
DJMcMayhem

Réponses:

5

Gelée, 13 octets

fFSµ€Ụị߀µ¹<?

Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça marche

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.

La comparaison ( <) d'un nombre avec lui-même donne 0 (fausse), mais la comparaison d'une liste non vide avec elle-même donne une liste de 0 (véridique), donc <peut être utilisée pour distinguer les nombres des listes.

Dennis
la source
0 est Faux, mais une boîte de 0 est Vrai, mais une boîte vide est Faux. Intéressant sur le fonctionnement de Python. : P
cat
Il me semble que 25 octets (lorsqu'ils sont encodés en UTF-8).
Rotsor
@Rotsor Cela sonne à peu près juste. Cependant, Jelly utilise une page de codes personnalisée qui code les 256 caractères qu'il comprend comme des octets uniques.
Dennis
17

Python 2, 114 101 78 73 62 octets

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

Je savais qu'il y avait une meilleure façon de filtrer les listes.

Trie une liste python (et ses sous-listes) sur place.

https://eval.in/540457 remercie @tac de m'avoir fait savoir que les solutions en place sont acceptables, et @xnor + @feersum pour d'autres optimisations!

Orez
la source
1
Un peu plus d' optimisation: k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
xnor
@xnor Je pense que cette solution n'est pas tout à fait correcte: eval.in/540447 . Pour cet exemple, nous recursons jusqu'à la première sous-liste et en prenons l'initiale z, 5. Ensuite, au conditionnel, nous trions la liste sur laquelle nous itérons (!), Donc quand nous prenons le z suivant, c'est AUSSI 5, conduisant à une somme de 10. Nous trions ensuite la liste externe avec ces clés et obtenons [6, [1, 5]], qui est incorrect comme "S'il y a une égalité, vous devez garder le même ordre que la liste d'origine. " La chose intéressante est que nous appelons sortles deux listes deux fois, donc cela ne se produit que sur des clés égales: si la sous-liste était inférieure, elle serait triée.
Orez
Bonne prise. C'est drôle que l'itération continue avec la liste maintenant triée. Je pense qu'il devrait toujours y avoir un moyen plus court de coller dans la Nonesortie de t.sort(key=k), mais je ne le vois pas.
xnor
Falseest égal à 0 pour les besoins de +et , par extension, sum. Je ne peux pas penser à la façon dont cela économise des octets, cependant.
CalculatorFeline
@CatsAreFluffy list.sortrevient None, non False.
Dennis
4

Lua, 172 octets

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 fonction strie une table Lua (une structure de données qui sert entre autres de liste dans Lua) en place selon les règles.

Trébuchette
la source
J'adore comment type(a)retourne une chaîne
chat
Enfin une réponse en utilisant Lua.
Leaky Nun
3

Mathematica, 50 octets

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

Méthode récursive simple qui utilise SortBy. Ignorez les messages.

LegionMammal978
la source
3

Haskell, 160 151 135 octets

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

Le premier problème concerne les listes imbriquées. Haskell requiert que tous les éléments d'une liste aient le même type; en particulier, un entier et une liste d'entiers ne sont pas du même type. En d'autres termes, une liste imbriquée de variables n'est pas une liste, c'est un rosier!

Donc, tout d'abord, nous devons définir un type de données pour les rosiers:

data T = N Int | T [T]

(Strictement, deriving Shown'est nécessaire que si vous voulez voir les résultats. Mais c'est une technicité.) Avec cette définition en place, nous pouvons écrire une liste telle (1, 2, (3, 4))que

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

qui est considérablement moins lisible. Mais peu importe; c'est une traduction mécanique triviale. Préfixez chaque numéro avec Net chaque sous-arbre avec T.

Maintenant, nous devons calculer les priorités. Ce serait facile si la priorité d'un sous-arbre était simple, la somme de tous les éléments qu'il contient. Ce serait une boucle récursive triviale. Mais comme ce n'est pas le cas, nous devons définir deux fonctions: une qui se reproduit et une qui ne le fait pas.

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

q (N x) = x
q _     = 0

Si nous devions additionner tous les sous-éléments, il qn'aurait pas besoin d'exister, sauvant un grand nombre de caractères. Tant pis!

Edit: En fait, plusieurs commentateurs soulignent que vous pouvez éviter l' qutilisation d' une compréhension de la liste: [ x | N x <- t]. Bon appel, les gars!

(En fait, pil ne devrait pas non plus exister; nous pourrions demander au compilateur de générer automatiquement une Ordinstance pour nous dans une poignée de caractères, et cette implémentation par défaut correspondrait à la spécification.)

Enfin, nous devons récursif sur tous les sous-arbres et les trier:

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

Autrement dit, ftrie un arbre en s’appliquant récursivement à tous les éléments ( map f), puis en appelant la sortByfonction pour trier le niveau supérieur. La première ligne indique que le tri d'un nombre ne fait rien et est nécessaire pour mettre fin à la récursivité.

MathematicalOrchid
la source
2
sortBy (\ x y -> compare (p x) (p y))est juste sortOn p. Utilisez la version infix de carte dans p: sum$q<$>t.
nimi
@nimi Où est sortOndéfini? J'ai toujours voulu savoir ...
MathematicalOrchid
2
vous pouvez toujours raser quelque 16 octets avec l'astuce de compréhension de liste, p(T t)=sum[x|N x<-t]et data T=N Int|T[T]deriving Show. :)
Will Ness
1
avez-vous inclus 2 octets pour chaque nouvelle ligne dans votre décompte? Je pense que nous sommes autorisés à les compter comme célibataires . De plus, il n'y a pas besoin d' $en sum$[x|N x<-t]. Donc, 135-5-1 = 129. :)
Will Ness
2

CLISP, 380 octets

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

Appelez la fonction q avec une liste.

Je suis un noob lisp, s'il vous plaît ne me tuez pas ^^

Joba
la source
Haha, j'espérais que quelqu'un le ferait en lisp!
DJMcMayhem
1

Pyth, 15 octets

L?sIbbossI#NyMb

Suite de tests

Une fonction récursive, qui fonctionne comme suit:

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
la source
1

Java, 219 octets

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

Avec des sauts de ligne:

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

Il y a beaucoup de casting en cours qui augmente vraiment le nombre d'octets. : P

Les valeurs entières sont introduites dans un comparateur et les listes imbriquées sont d'abord triées avant que la somme des seules valeurs entières ne soit donnée au comparateur. Ces valeurs sont la façon dont le comparateur détermine leur position dans la liste lors de son tri.

Essayez-le ici .

TNT
la source
1
Voici la même technique à 154 octetsint 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
Je pense qu'il y a encore beaucoup à faire.
Andreas
Mais il y a des problèmes de couple: vous ne pouvez pas convertir explicitement Objectà intcomme ça, et le défi semble exiger que la liste est sortie.
TNT
Vous enregistrez en fait 1 octet en modifiant l'instance de pour vérifier la liste au lieu de l'entier. Entier est de 7 octets sans accolades, mais la liste est de 6 octets avec.
Blue
@TNT Vous pouvez convertir un objet en primitive en java 1.7 ou supérieur. Bien sûr, si l'objet est nul, vous obtiendrez un npe. Je ne vois aucun problème à trier la liste en place, le défi ne semble pas aborder le problème directement.
Andreas
0

JavaScript (ES6), 86 octets

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

Tout ce tableau vérifiant :-(

Neil
la source
1
map.map.map.map.map.map.map.map.map
cat