Sắp xếp một danh sách lồng nhau


23

Bạn phải viết một chương trình hoặc hàm sắp xếp danh sách lồng nhau. Dưới đây là các quy tắc để sắp xếp danh sách lồng nhau:

Hãy lấy danh sách này làm ví dụ:

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

Mỗi yếu tố trong danh sách này có một "ưu tiên". Một phần tử được tính là một số hoặc một danh sách con. Đầu tiên, có được sự ưu tiên của từng yếu tố ở cùng độ sâu. Nếu một phần tử chỉ là một số, thì mức độ ưu tiên của nó giống với chính số đó. Nếu một phần tử là một danh sách con, mức độ ưu tiên của nó là tổng của tất cả các số trong đó, không bao gồm bất kỳ danh sách phụ nào.

Vì vậy, các ưu tiên của tất cả các yếu tố của độ sâu 1 là:

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

Sắp xếp từng yếu tố theo mức độ ưu tiên. Nếu có cà vạt, bạn phải giữ nguyên thứ tự như danh sách ban đầu.

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

Lặp lại cho mỗi danh sách phụ. Vì vậy, trong danh sách phụ này

(2, 1, (3, 4))

Các ưu tiên của chúng tôi trông như:

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

Sắp xếp như vậy, có vẻ như:

(1, 2, (3, 4))

(3, 4)đã được sắp xếp, vậy là xong. Lặp lại cho (5, 2)kết quả (2, 5)và chúng tôi đã hoàn tất! Danh sách cuối cùng của chúng tôi là:

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

Quy tắc:

  • Rất đáng nghi ngờ, nhưng chỉ trong trường hợp Mathematica có một cái gì đó cho điều này, không có nội dung sắp xếp danh sách lồng nhau nào được phép. Chức năng phân loại thường xuyên được cho phép.

  • I / O có thể ở bất kỳ định dạng hợp lý.

  • Mỗi danh sách phụ sẽ chứa ít nhất một số hoặc danh sách. Ngoài ra, danh sách con có thể được lồng nhiều cấp độ sâu. Ví dụ: trong (1, 2, (((3))))đó (((3)))có mức độ ưu tiên là 0, vì nó chỉ có danh sách con trong đó.

  • Danh sách không hợp lệ (dấu ngoặc đơn không trùng khớp, không phải số, loại dấu ngoặc sai, số âm, v.v.) dẫn đến hành vi không xác định.

Kiểm tra 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))

Câu trả lời ngắn nhất trong byte thắng.


Chúng ta có thể giả sử các số là số nguyên?
isaacg 22/03/2016

@isaacg Vâng, bạn có thể.
DJMcMayhem

Câu trả lời:


5

Thạch, 13 byte

fFSµ€Ụị߀µ¹<?

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Làm thế nào nó hoạt động

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.

So sánh ( <) một số với chính nó mang lại 0 (giả mạo), nhưng so sánh một danh sách không trống với chính nó mang lại một danh sách 0 (s thật), vì vậy <có thể được sử dụng để phân biệt các số từ danh sách.


0 là Sai, nhưng hộp 0 là Đúng, nhưng hộp trống là Sai. Thật thú vị khi Python hoạt động. : P
mèo

Hình như là 25 byte (khi được mã hóa bằng UTF-8) với tôi.
Rotsor

@Rotsor Nghe có vẻ đúng. Tuy nhiên, Jelly sử dụng trang mã tùy chỉnh mã hóa tất cả 256 ký tự mà nó hiểu là các byte đơn.
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)

Tôi biết có một cách tốt hơn để lọc danh sách.

Sắp xếp một danh sách python (và danh sách con của nó) tại chỗ.

https://eval.in/540456 cảm ơn @tac đã cho tôi biết các giải pháp tại chỗ có thể chấp nhận được và @xnor + @feersum để tối ưu hóa hơn nữa!


1
Một số tối ưu hóa hơn : k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
xnor

@xnor Tôi nghĩ rằng giải pháp đó không hoàn toàn chính xác: eval.in/540447 . Trong ví dụ này, chúng tôi lặp lại danh sách con đầu tiên và lấy chữ cái đầu tiên ztừ nó, 5. Sau đó, trong điều kiện, chúng tôi sắp xếp danh sách chúng tôi đang lặp lại (!), Vì vậy khi chúng tôi lấy z tiếp theo, C ALNG 5, dẫn đến tổng số 10. Sau đó, chúng tôi sắp xếp danh sách bên ngoài bằng các khóa này và nhận [6, [1, 5]], không chính xác là "Nếu có một ràng buộc, bạn phải giữ nguyên thứ tự như danh sách ban đầu. " Điều thú vị là chúng tôi gọi sortcả hai danh sách hai lần, vì vậy điều này chỉ xảy ra trên các khóa bằng nhau: nếu danh sách phụ ít hơn thì nó sẽ sắp xếp lại.
Orez

Nắm bắt tốt. Thật buồn cười khi việc lặp lại tiếp tục với danh sách được sắp xếp. Tôi cảm thấy như vẫn còn một cách ngắn hơn để bám vào Noneđầu ra t.sort(key=k), nhưng tôi không thấy nó.
xnor

Falselà 0 cho các mục đích +và bởi phần mở rộng , sum. Mặc dù vậy, không thể nghĩ làm thế nào để tiết kiệm byte.
Máy

@CatsAreFluffy list.sorttrả lại None, không 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

Hàm ssắp xếp một bảng Lua (một cấu trúc dữ liệu đóng vai trò là một danh sách trong số những thứ khác trong Lua) theo đúng quy tắc.


Tôi thích cách type(a)trả về một chuỗi
con mèo

Cuối cùng một câu trả lời bằng Lua.
Leaky Nun

3

Toán học, 50 byte

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

Phương pháp đệ quy đơn giản mà sử dụng SortBy. Bỏ qua các tin nhắn.


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

Vấn đề đầu tiên là danh sách lồng nhau. Haskell yêu cầu tất cả các yếu tố của một danh sách có cùng loại; đặc biệt, một số nguyên và danh sách các số nguyên không cùng loại. Nói cách khác, một danh sách lồng nhau không phải là một danh sách, đó là một cây hoa hồng!

Vì vậy, trước tiên, chúng ta phải xác định loại dữ liệu cho cây hoa hồng:

data T = N Int | T [T]

(Nghiêm túc, deriving Showchỉ cần thiết nếu bạn muốn xem kết quả. Nhưng đó là một kỹ thuật.) Với định nghĩa này, chúng ta có thể viết một danh sách (1, 2, (3, 4))như

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

đó là đáng kể ít đọc hơn. Nhưng sao cũng được; đó là một bản dịch cơ học tầm thường. Tiền tố mỗi số với Nvà mỗi cây con với T.

Bây giờ chúng ta cần tính toán các ưu tiên. Điều này sẽ dễ dàng nếu mức độ ưu tiên của cây con đơn giản là tổng của tất cả các yếu tố mà nó chứa. Đó sẽ là một vòng lặp đệ quy tầm thường. Nhưng vì không phải vậy, chúng ta cần xác định hai hàm: một hàm đệ quy và một hàm không.

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

q (N x) = x
q _     = 0

Nếu chúng ta tổng hợp tất cả các phần phụ, thì qsẽ không cần tồn tại, tiết kiệm một số lượng lớn các ký tự. Ồ tốt

Chỉnh sửa: Trên thực tế, một số bình luận chỉ ra rằng bạn có thể tránh qsử dụng một sự hiểu biết danh sách : [ x | N x <- t]. Gọi tốt nhé các bạn!

(Trên thực tế, pcũng không cần tồn tại; chúng ta có thể có trình biên dịch tự động tạo một Ordthể hiện cho chúng ta trong một số ký tự và cách triển khai mặc định này sẽ khớp với thông số kỹ thuật.)

Cuối cùng, chúng ta cần đệ quy trên tất cả các cây con và sắp xếp chúng:

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

Đó là, fsắp xếp một cây bằng cách áp dụng đệ quy chính nó cho tất cả các phần tử ( map f), sau đó gọi sortByhàm để sắp xếp mức cao nhất. Dòng đầu tiên nói rằng việc sắp xếp một số không làm gì cả và cần phải chấm dứt đệ quy.


2
sortBy (\ x y -> compare (p x) (p y))chỉ là sortOn p. Sử dụng phiên bản infix của bản đồ trong p: sum$q<$>t.
nimi

@nimi Được sortOnđịnh nghĩa ở đâu? Tôi đã luôn muốn biết ...
Toán học,


2
bạn vẫn có thể loại bỏ 16 byte bằng thủ thuật hiểu danh sách p(T t)=sum[x|N x<-t]data T=N Int|T[T]deriving Show. :)
Will Ness

1
bạn đã bao gồm 2 byte cho mỗi dòng mới trong số của bạn chưa? Tôi nghĩ chúng ta được phép coi họ là người độc thân . Ngoài ra, không có nhu cầu $trong sum$[x|N x<-t]. Vậy, 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))))

Gọi hàm q với một danh sách.

Tôi là một người không tốt, xin đừng giết tôi ^^


Haha, tôi đã hy vọng ai đó sẽ làm điều đó trong lisp!
DJMcMayhem

1

Bình thường, 15 byte

L?sIbbossI#NyMb

Bộ kiểm tra

Một hàm đệ quy, hoạt động như sau:

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

Với ngắt dòng:

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ó rất nhiều sự đúc đang diễn ra mà thực sự làm tăng số byte. : P

Các giá trị số nguyên được đưa vào Bộ so sánh và các danh sách lồng nhau được sắp xếp trước khi tổng các giá trị nguyên được đưa cho Bộ so sánh. Các giá trị này là cách Trình so sánh xác định vị trí của chúng trong danh sách khi nó được sắp xếp.

Hãy thử nó ở đây .


1
Đây là kỹ thuật tương tự ở 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

Tôi nghĩ rằng có nhiều hơn để ép, quá.
Andreas

Nhưng có một vài vấn đề: bạn không thể chuyển đổi rõ ràng Objectthành intnhư thế và thách thức dường như đòi hỏi một danh sách là đầu ra.
TNT

Bạn thực sự tiết kiệm 1 byte bằng cách thay đổi thể hiện để kiểm tra Danh sách thay vì Số nguyên. Integer là 7 byte w / o ngoặc nhọn, nhưng List là 6 byte với nó.
Blue

@TNT Bạn có thể truyền Object thành nguyên thủy trong java 1.7 trở lên. Tất nhiên, nếu đối tượng là null, bạn sẽ nhận được một số npe. Tôi không thấy bất kỳ vấn đề nào với việc sắp xếp danh sách tại chỗ, thách thức dường như không nói trực tiếp đến vấn đề.
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

Tất cả các kiểm tra mảng :-(


1
map.map.map.map.map.map.map.map.map
mèo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.