Classificar uma lista aninhada

23

Você deve escrever um programa ou função que classifique uma lista aninhada. Aqui estão as regras para classificar uma lista aninhada:

Vamos tomar esta lista como um exemplo:

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

Cada elemento nesta lista tem uma "prioridade". Um elemento conta como um número ou uma sub-lista. Primeiro, obtenha a prioridade de cada elemento na mesma profundidade. Se um elemento é apenas um número, sua prioridade é a mesma que o próprio número. Se um elemento é uma sub- lista, sua prioridade é a soma de todos os números , sem incluir nenhuma sub-sublista.

Portanto, as prioridades de todos os elementos da profundidade 1 são:

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

Classifique cada elemento por prioridade. Se houver um empate, você deve manter a mesma ordem que a lista original.

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

Repita para todas as sub-listas. Então nesta sublist

(2, 1, (3, 4))

Nossas prioridades se parecem com:

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

Tão ordenados, parece com:

(1, 2, (3, 4))

(3, 4)já está classificado, então terminamos. Repita para (5, 2)que resultados (2, 5)e pronto! Nossa lista final é:

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

Regras:

  • Altamente duvidoso, mas, no caso de o Mathematica ter algo para isso, não é permitido nenhum built-in de classificação de lista aninhada. Funções de classificação regulares são permitidas.

  • A E / S pode estar em qualquer formato razoável.

  • Cada sublist conterá pelo menos um número ou lista. Além disso, sublistas podem ser aninhados em vários níveis de profundidade. Por exemplo, (1, 2, (((3))))na (((3)))tem uma prioridade de 0, uma vez que tem apenas sublists nele.

  • Listas inválidas (parênteses não correspondentes, não números, tipos de colchetes incorretos, números negativos, etc.) resultam em comportamento indefinido.

E / S de teste:

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

A resposta mais curta em bytes vence.

DJMcMayhem
fonte
Podemos assumir que os números são inteiros?
Isaacg
@isaacg Sim, você pode.
DJMcMayhem

Respostas:

5

Gelatina, 13 bytes

fFSµ€Ụị߀µ¹<?

Experimente online! ou verifique todos os casos de teste .

Como 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.

Comparando ( <) um número com ele próprio produz 0 (Falsas), mas comparando uma lista não-vazia com si produz uma lista de 0 's (truthy), de modo que <pode ser utilizado para distinguir os números de listas.

Dennis
fonte
0 é False, mas uma caixa de 0s é True, mas uma caixa vazia é False. Interessante como o Python funciona. : P
cat
Parece 25 bytes (quando codificado em UTF-8) para mim.
Rotsor 26/03
@ Rotsor Isso parece certo. No entanto, o Jelly usa uma página de código personalizada que codifica todos os 256 caracteres que entende como bytes únicos.
26516 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)

Eu sabia que havia uma maneira melhor de filtrar as listas.

Classifica uma lista python (e suas sublistas) no local.

https://eval.in/540457 obrigado @tac por me informar que as soluções no local são aceitáveis ​​e @xnor + @feersum para otimizações adicionais!

Orez
fonte
1
Alguns mais otimização: k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
Xnor
@ xnor Acho que a solução não está correta: eval.in/540447 . Neste exemplo, recuamos para a primeira sublist e pegamos a inicial zdela, 5. Em seguida, na condicional, classificamos a lista sobre a qual estamos iterando (!); Portanto, quando pegamos o próximo z, é TAMBÉM 5, levando a uma soma de 10. Em seguida, classificamos a lista externa com essas chaves e obtemos [6, [1, 5]], que está incorreto como "Se houver um empate, você deve manter a mesma ordem que a lista original. " O interessante é que chamamos sortas duas listas duas vezes, então isso só acontece com chaves iguais: se a sub-lista fosse menor, ela retornaria.
Orez 22/03
Boa pegada. É engraçado que a iteração continue com a lista agora classificada. Eu sinto que ainda deve haver uma maneira mais curta de manter a Nonesaída t.sort(key=k), mas não estou vendo.
Xnor
Falseé 0 para os propósitos +e por extensão sum,. Não consigo pensar em como isso salva bytes, no entanto.
CalculatorFeline
@CatsAreFluffy list.sortretorna None, não 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

A função sclassifica uma tabela Lua (uma estrutura de dados que serve como uma lista entre outras coisas em Lua) de acordo com as regras.

Trebuchette
fonte
Eu amo como type(a)retorna uma string
cat
Finalmente, uma resposta usando Lua.
gotejante Nun
3

Mathematica, 50 bytes

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

Método recursivo simples que usa SortBy. Ignore as mensagens.

LegionMammal978
fonte
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

O primeiro problema são listas aninhadas. Haskell requer que todos os elementos de uma lista tenham o mesmo tipo; em particular, um número inteiro e uma lista de números inteiros não são do mesmo tipo. Em outras palavras, uma lista aninhada por variáveis não é uma lista, é uma roseira!

Então, primeiro, precisamos definir um tipo de dados para as roseiras:

data T = N Int | T [T]

(Estritamente, deriving Showsó é necessário se você quiser ver os resultados. Mas isso é um detalhe técnico.) Com essa definição, podemos escrever uma lista (1, 2, (3, 4))como

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

o que é consideravelmente menos legível. Mas de qualquer forma; é uma tradução mecânica e trivial. Prefixe cada número comN e cada subárvore com T.

Agora precisamos calcular prioridades. Isso seria fácil se a prioridade de uma subárvore fosse simples a soma de todos os elementos que ela contém. Isso seria um loop recursivo trivial. Mas, como não é, precisamos definir duas funções: uma que se repete e outra que não.

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

q (N x) = x
q _     = 0

Se somarmos tudo subelementos, qnão seria necessário existir, economizando um grande número de caracteres. Ah bem!

Edit: Na verdade, vários comentaristas apontam que você pode evitar q utilizando uma compreensão da lista: [ x | N x <- t]. Boa ligação, pessoal!

(De fato, ptambém não precisaria existir; poderíamos ter o compilador para gerar automaticamente uma Ordinstância para nós em alguns caracteres, e essa implementação padrão corresponderia às especificações.)

Por fim, precisamos recursivamente sobre todas as subárvores e classificá-las:

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

Ou seja, fclassifica uma árvore aplicando-se recursivamente a todos os elementos ( map f) e, em seguida, chamando a sortByfunção para classificar o nível superior. A primeira linha diz que classificar um número não faz nada e é necessário encerrar a recursão.

MathematicsOrchid
fonte
2
sortBy (\ x y -> compare (p x) (p y))é justo sortOn p. Use a versão infix do mapa em p: sum$q<$>t.
nimi
@nimi Onde é sortOndefinido? Eu sempre quis saber ...
MathematicalOrchid
2
você ainda pode cortar cerca de 16 bytes com o truque de compreensão de lista, p(T t)=sum[x|N x<-t]e data T=N Int|T[T]deriving Show. :)
Will Ness
1
você incluiu 2 bytes para cada nova linha em sua contagem? Acho que podemos contá-los como solteiros . Além disso, não há necessidade de $entrar sum$[x|N x<-t]. Então 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))))

Chame a função q com uma lista.

Eu sou um lisp noob, por favor, não me mate ^^

Joba
fonte
Haha, eu estava esperando que alguém fizesse isso em lisp!
DJMcMayhem
1

Pitão, 15 bytes

L?sIbbossI#NyMb

Suíte de teste

Uma função recursiva, que funciona da seguinte maneira:

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

Com quebras de linha:

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

Há muitas transmissões em andamento que realmente aumentam a contagem de bytes. : P

Os valores inteiros são alimentados em um comparador e as listas aninhadas são classificadas primeiro antes que a soma apenas dos valores inteiros seja fornecida ao comparador. Esses valores são como o Comparador determina sua posição na lista quando é classificado.

Experimente aqui .

TNT
fonte
1
Aqui está a mesma técnica em 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
Eu acho que há muito mais para apertar também.
Andreas
Mas existem algumas questões: você não pode converter explicitamente Objectpara intisso, e o desafio parece exigir que uma lista seja exibida.
TNT
Na verdade, você salva 1 byte alterando a instanceof para verificar a Lista em vez de Inteiro. Inteiro tem 7 bytes sem chaves, mas List possui 6 bytes.
Azul
@TNT Você pode converter um Objeto em um primitivo em java 1.7 ou superior. Obviamente, se o objeto for nulo, você receberá um npe. Não vejo nenhum problema em classificar a lista, o desafio não parece falar diretamente sobre o 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 essa verificação de matriz :-(

Neil
fonte
1
map.map.map.map.map.map.map.map.map
cat