Yuvalanmış bir listeyi sıralama


23

İç içe geçmiş bir liste sıralayan bir program veya işlev yazmalısınız. İşte iç içe geçmiş bir listeyi sıralamak için kurallar:

Bu listeyi örnek olarak alalım:

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

Bu listedeki her eleman bir "önceliğe" sahiptir. Bir öğe bir sayı veya alt liste olarak sayılır. İlk önce, her elemanın önceliğini aynı derinlikte alın. Bir eleman sadece bir sayı ise, önceliği sayının kendisiyle aynıdır. Bir öğe bir alt liste ise, önceliği, herhangi bir alt listeyi içermeyen, içindeki tüm sayıların toplamıdır .

Dolayısıyla, derinlik 1'in tüm elemanlarının öncelikleri şunlardır:

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

Her elemanı önceliğe göre sıralayın. Bir kravat varsa, orijinal listeyle aynı sırayı korumalısınız.

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

Her alt liste için tekrarlayın. Yani bu alt listede

(2, 1, (3, 4))

Önceliklerimiz şuna benziyor:

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

Yani sıralı, benziyor:

(1, 2, (3, 4))

(3, 4)zaten sıralı, bu yüzden bitti. (5, 2)Hangi sonuç için tekrarlayın (2, 5)ve bittik! Son listemiz:

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

Kurallar:

  • Çok şüpheli, ancak Mathematica'nın bunun için bir şeye sahip olması durumunda, yuvalanmış liste sıralama yapılarına izin verilmez. Düzenli sıralama işlevleri vardır izin verdi.

  • G / Ç herhangi bir makul biçimde olabilir.

  • Her alt liste en az bir numara veya liste içerecektir. Ayrıca, alt listeler birkaç düzeyde derinlere yuvalanabilir. Örneğin, o sadece sublists sahip olduğundan, 0 bir önceliğe sahiptir. (1, 2, (((3))))(((3)))

  • Geçersiz listeler (eşleştirilmemiş parantezler, sayısız, yanlış parantez türleri, negatif sayılar vb.) Tanımsız davranışa neden olur.

Test G / Ç:

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

Bayt cinsinden en kısa cevap kazanır.


Sayıların tamsayı olduğunu varsayabilir miyiz?
isaacg,

@isaacg Evet, yapabilirsiniz.
DJMcMayhem

Yanıtlar:


5

Jöle, 13 bayt

fFSµ€Ụị߀µ¹<?

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

Nasıl çalışır

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.

Karşılaştırma ( <) kendisi ile bir sayı verir 0 (falsy), ancak kendisi ile boş olmayan bir liste karşılaştıran bir listesini verir 0 , yani 'in (truthy) <listeleri numaraları ayırt etmek için kullanılabilir.


0 Yanlış, ancak 0'lık bir kutu Doğru, ancak boş bir kutu Yanlış. Python'un çalışma şekli ilginç. : P
kedi

Bana 25 bayt (UTF-8 ile kodlandığında) gibi görünüyor.
Rotsor

@Rotsor Bu doğru geliyor. Ancak Jelly, tek bayt olarak anladığı 256 karakterin tümünü kodlayan özel kod sayfası kullanır .
Dennis,

17

Python 2, 114 101 78 73 62 bayt

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

Ben biliyordum dışarı filtre listeleri için daha iyi bir yolu yoktu.

Yerinde bir python listesi (ve alt listelerini) sıralar.

https://eval.in/540457 teşekkürler, yerinde çözümlerin kabul edilebilir olduğunu bildirmek için @tac ve daha fazla optimizasyon için @xnor + @feersum!


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

@ xnor Bu çözüm oldukça doğru değil düşünüyorum: eval.in/540447 . Bu örnek için, ilk zalt listeye geri dönüyoruz ve ilkini ondan alıyoruz, 5. Sonra şartlı olarak, yinelemekte olduğumuz listeyi (!) Sıralıyoruz, bir sonraki z'yi aldığımızda ALSO 5, 10'luk bir sonuç veririz. Sonra dış listeyi bu tuşlarla sıralar ve [6, [1, 5]] değerini alırız. Bu, "Bir kravat varsa, orijinal listeyle aynı sırayı tutmalısınız. " İlginç olan sort, iki listeyi de iki kere çağırmamızdır , bu nedenle bu sadece eşit anahtarlarda olur: alt liste daha az olsaydı, geri dönerdi.
Orez

İyi yakalama. Yinelemenin şimdi sıralanan listeyle devam etmesi komik. Hala içinde sopa daha kısa bir yol olması gerektiğini gibi hissediyorum Noneçıkışında t.sort(key=k), ancak bunu göremiyorum.
Xnor

False0 için +ve uzatma amacıyla sum. Ancak, bunun baytları nasıl kurtardığını düşünemiyorum.
Hesap MakinesiFeline

@CatsAreFluffy list.sortgeri dönüyor None, değil False.
Dennis,

4

Lua, 172 bayt

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

İşlev s, kurallara uygun olarak bir Lua tablosu (Lua'daki diğer şeylerin bir listesi olarak hizmet veren bir veri yapısı) sıralar.


type(a)Bir dize döndürür nasıl seviyorum
kedi

Sonunda Lua kullanarak bir cevap.
Leaky Nun

3

Mathematica, 50 bayt

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

Kullanan basit özyinelemeli yöntem SortBy. Mesajları yoksay.


3

Haskell, 160 151 135 bayt

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

İlk sorun iç içe listeler. Haskell, bir listenin tüm elemanlarının aynı tipte olmasını gerektirir; özellikle, bir tamsayı ve bir tamsayı listesi aynı tip değildir. Başka bir deyişle, değişken iç içe liste bir liste değildir, gül ağacıdır!

İlk önce, gül ağaçları için bir veri türü tanımlamamız gerekir:

data T = N Int | T [T]

(Kesinlikle, deriving Showsadece sonuçları görmek istiyorsanız gereklidir . Ancak bu bir tekniktir.) Bu tanım yerinde olduğunda, şöyle bir liste yazabiliriz (1, 2, (3, 4)).

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

bu oldukça az okunabilir. Fakat herneyse; önemsiz, mekanik bir çeviri. Her sayıyı Nve her alt ağacı kullanarak önek girin T.

Şimdi öncelikleri hesaplamamız gerekiyor. Bir alt ağacın önceliği içerdiği tüm unsurların toplamı basit olsaydı bu kolay olurdu . Bu önemsiz bir özyinelemeli döngü olurdu. Fakat öyle olmadığından, iki işlevi tanımlamamız gerekir : biri işe yarayan, diğeri olmayan.

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

q (N x) = x
q _     = 0

Eğer tüm alt toplamları toplarsak, qçok fazla sayıda karakter kazandırarak var olmamız gerekmeyecekti. Oh iyi!

Düzenleme: Aslında birkaç commentors sen önleyebilirsiniz işaret qlistesi kavrayışa: [ x | N x <- t]. İyi arama beyler!

(Aslında, pikisinin de var olması gerekmeyecekti; derleyicinin Ordbizim için bir örneği otomatik olarak bir avuç karakterde otomatik olarak üretmesini sağlayabilirdik ve bu varsayılan uygulama, spesifikasyonlarla eşleşecekti.)

Son olarak, tüm alt ağaçlarda özyinelemeli ve bunları sıralamalıyız:

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

Yani, ftekrarlayan bir şekilde kendisini tüm öğelere uygulayarak bir ağaç sıralar ( map f) ve daha sonra sortByüst seviyeyi sıralamak için işlevi çağırarak . İlk satır, bir sayıyı sıralamanın hiçbir şey yapmadığını ve özyinelemeyi sonlandırmak için gerekli olduğunu söylüyor.


2
sortBy (\ x y -> compare (p x) (p y))sadece sortOn p. Haritanın infix versiyonunu p: 'de kullanın sum$q<$>t.
nimi,

@nimi Nerede sortOntanımlanır? Her zaman bilmek istemişimdir ...
MathematicalOrchid


2
Hala liste anlama hile ile bazı 16 bayt tıraş, olabilir p(T t)=sum[x|N x<-t]ve data T=N Int|T[T]deriving Show. :)
Ness

1
Sayınıza her yeni satır için 2 bayt eklediniz mi? Onları bekar olarak saymamıza izin verildiğini düşünüyorum . Ayrıca gerek yoktur $içinde sum$[x|N x<-t]. Öyleyse 135-5-1 = 129. :)
Will Ness

2

CLISP, 380 bayt

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

Q fonksiyonunu bir liste ile çağırın.

Ben lisp noob, lütfen beni öldürme ^^


Haha, birinin lisp'te yapmasını umuyordum!
DJMcMayhem

1

Pyth, 15 bayt

L?sIbbossI#NyMb

Test odası

Aşağıdaki gibi çalışan özyinelemeli bir işlev:

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 bayt

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

Satır sonları ile:

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

Bayt sayımını gerçekten etkileyen çok sayıda döküm var. : P

Tamsayı değerleri bir Karşılaştırıcıya beslenir ve önce yuvalanmış listeler, Karşılaştırıcıya yalnızca tamsayı değerlerinin toplamından önce sıralanır. Bu değerler, Karşılaştırıcı sıralandığında listedeki konumlarını nasıl belirlediğidir.

Burada dene .


1
İşte 154 byte aynı tekniğiint 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

Ben de sıkılacak daha çok şey olduğunu düşünüyorum.
Andreas

Açıkça dönüştürmek olamaz: Ama birkaç konular Objectiçin intböyle ve meydan okuma listesi çıkışı gerektirir gibi görünüyor.
TNT

Aslında, Tamsayı yerine List'i kontrol etmek için instanceof değerini değiştirerek 1 bayttan tasarruf ediyorsunuz. Tamsayı küme parantezleri olmadan 7 bayt, ancak Liste de bununla 6 bayttır.
Blue

@TNT Bir Nesneyi java 1.7 veya daha yüksek sürümlerde bir ilkel görüntüye alabilirsiniz. Tabii ki, nesne null ise bir npe alırsınız. Listeyi sıralamakta herhangi bir sorun görmüyorum, zorluk doğrudan konu ile konuşmuyor gibi görünüyor.
Andreas

0

JavaScript (ES6), 86 bayt

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

Tüm bu dizi kontrol :-(


1
map.map.map.map.map.map.map.map.map
kedi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.