Vẽ một cây từ một mảng


24

Đưa ra một mảng các số nguyên dương có một chữ số lồng nhau (không được bảo đảm duy nhất), xuất ra biểu diễn nghệ thuật ASCII dưới dạng cây, sử dụng các ký tự vẽ hình hộp ┌ ┴ ┐ ─ │ ┬ ┼ . (Chúng được sao chép từ Mã trang 437, nhưng bạn có thể sử dụng bất kỳ đại diện tương đương nào).

Mỗi số nguyên của mảng phải là một lá của cây. Các yếu tố cùng cấp độ sâu trong mảng phải có mặt ở cùng cấp độ của cây. Tất cả các yếu tố phải được phân tách bằng khoảng trắng đủ để phân biệt (tùy thuộc vào bạn để xác định độ rộng, tối thiểu của một khoảng cách giữa).

Ví dụ, mảng đã cho [[1, [2]], [3, [4, 5]]], xuất cây sau

 ┌─┴─┐
┌┴┐ ┌┴─┐
1 │ 3 ┌┴┐
  2   4 5

Đối với mảng [1, 2, 3], cây có thể trông giống như

┌─┼─┐
1 2 3

Nhưng mảng [[1, 2, 3]]sẽ như thế nào

  │
┌─┼─┐
1 2 3

Trong khi mảng [1, [1, [1, [1]]]]có thể trông như

 ┌─┴┐
 1 ┌┴─┐
   1 ┌┴┐
     1 │
       1

Như một ví dụ phức tạp hơn, [1, [[[2, 3], 4], 5]]có thể là

┌┴───┐
1  ┌─┴┐
 ┌─┴┐ 5
┌┴┐ 4
2 3

hoặc một số biến thể khác.


  • Đầu vào và đầu ra có thể được cung cấp bởi bất kỳ phương pháp thuận tiện .
  • Bạn có thể in nó sang STDOUT hoặc trả lại dưới dạng kết quả chức năng.
  • Một chương trình đầy đủ hoặc một chức năng được chấp nhận.
  • Bất kỳ số lượng khoảng trắng ngoại lai nào cũng được chấp nhận, miễn là các ký tự xếp hàng một cách thích hợp.
  • Sơ hở tiêu chuẩn bị cấm.
  • Đây là vì vậy tất cả các quy tắc chơi gôn thông thường đều được áp dụng và mã ngắn nhất (tính bằng byte) sẽ thắng.

[1,[[[2,3],4],5]]có thể là một trường hợp thử nghiệm thú vị vì nó cần phải mở rộng gốc một cách nhân tạo để cây con bên phải không va chạm với cây con bên trái.
Chọc

@Poke Đã thêm làm ví dụ. Có một số biến thể có thể cho trường hợp thử nghiệm đó.
admBorkBork

2
Ví dụ đầu tiên cho trường hợp thử nghiệm đó không thể đúng. Điều đó cho thấy rằng là yếu tố thứ hai bên cạnh 1là một mảng của 3 mặt hàng: [2,3], 4, và 5. Nhưng 4 và 5 không liền kề.
Draco18

4
Điều đó có vẻ như [1, [[[2, 3]], [4], 5]]với tôi.
Neil

Đó (nếu có) của các định dạng đầu vào thay thế sẽ được chấp nhận?
Οurous

Câu trả lời:


12

Trăn 3 , 400 393 390 byte

L=len
S,*K=' ┴┼│123456789'
def T(x):
 try:return[str(x+0)]
 except:
  z=[*map(T,x)];q=max(map(L,z))
  for p in z:p+=[S*L(p[0])]*(q-L(p))
  b=[S.join(a)for a in zip(*z)];t=b[0];l=L(t);s=0;e=L(z);r=[S]*l
  if e<2:return['│'.center(l),*b]
  for i in range(l):
   if t[i]in K:s+=1;r[i]='┬┌┐'[(s<e)-(s>1)]
   elif 0<s<e:r[i]='─'
  c=l//2;r[c]=K[r[c]=='┬'];return[''.join(r),*b]

Trả về một danh sách các chuỗi từ trên xuống dưới.

EDIT 1: Cắt bớt 7 byte bằng cách tránh trùng lặp ┴┼(lưu ròng 2 byte), cắt 0 từ một chuỗi, thay đổi cách chọn ký tự vẽ từ┬┌┐ (sử dụng <thay vì ==) và thay thế L(z)tôi đã bỏ lỡ bằnge

EDIT 2: -2 byte nhờ vào ovs và -1 byte nhờ Kevin Cruijssen

Hãy thử trực tuyến!

Bị đánh cắp

def layer(item):
    if isinstance(item, int):
        return [str(item)]
    else:
        subs = [layer(sub) for sub in item]
        longest = max(map(len, subs))
        for sub in subs:
            sub += [' ' * len(sub[0])] * (longest - len(sub))
        below = [' '.join(l) for l in zip(*subs)]
        top = below[0]
        l = len(top)
        if len(subs) == 1:
            return ['│'.center(l), *below]
        seen = 0
        expected = len(subs)
        builder = [' '] * l
        for i in range(l):
            c = top[i]
            if c in '┴┼│123456789':
                seen += 1
                if seen == 1:
                    builder[i] = '┌'
                elif seen == expected:
                    builder[i] = '┐'
                else:
                    builder[i] = '┬'
            elif 0 < seen < expected:
                builder[i] = '─'
        center = l // 2
        if builder[center] == '┬':
            builder[center] = '┼'
        else:
            builder[center] = '┴'
        return [''.join(builder), *below]

Xây dựng một cây từ lá lên, mỗi lần một lớp.


2
Tôi đã thêm các trường hợp thử nghiệm vào liên kết TIO của bạn Hãy thử trực tuyến!
pizzapants184

Câu trả lời tốt đẹp! Bạn có thể rút ngắn điều này bằng hai byte bằng cách gán không gian cho một biến như thế này : S,*K=' ┴┼│123456789'.
trứng

1
e==1có thể e<2để lưu một byte (tôi không nghĩ nó có thể là 0, vì thách thức nói rằng đầu vào không trống - và max(map(L,z))dù sao thì đầu vào trống cũng đã thất bại trong trường hợp đó.)
Kevin Cruijssen

3

Sạch , 544 506 byte

Các lối thoát được sử dụng để tránh UTF-8 không hợp lệ trên SE / TIO nhưng được tính là một byte vì chúng là chữ hợp lệ

import StdEnv,Data.List;::T=I Int|L[T];$l#m= @l#k=map maxList(transpose m)=flatlines[[last[' ':[(\_|v<0|w<[j]|q>hd w|q<last w|any((==)q)w|q==j='\305'='\302'|q==j='\301'='\304'='\277'='\332'='\263'=toChar v+'0')0\\[v,r,j:w]<-m|r/2==p&&q>=hd w&&q<=last w]]\\q<-[0..k!!3]]\\p<-[0..k!!1]];@(L l)#p=twice(\p=[[v,r+1:[e+sum([2\\[v:_]<-i|0<=v]++zipWith(\c j=j!!2-c!!3)t(takeWhile(\[z:_]=v+z< -1)(tl t)))-x!!1\\e<-x]]\\i<-inits p&t<-tails p&[v,r:x]<-p])(concatMap@l)#g=[g\\[_,2,g:_]<-p]=[[-1,0,(hd g+last g)/2:g]:p];@(I i)=[[i,0,0,0]];

Hãy thử trực tuyến!

Đưa đầu vào theo định dạng L[I 3, L[I 4, I 5], I 2]..

Kết nối các cây từ dưới lên, từ trái sang phải, sau đó điều chỉnh khoảng cách từ phải sang trái.

Được sắp xếp lại, sắp xếp:

import StdEnv, Data.List;
:: T = I Int | L [T];
$ l
    #m = @l
    #k = map maxList (transpose m)
    = flatlines [
        [
            last[
                ' ':
                [
                    if(v < 0)
                        if(w < [j])
                            if(q > hd w)
                                if(q < last w)
                                    if(any ((==) q) w)
                                        (
                                            if(q == j)
                                                '\305'
                                                '\302'
                                        )(
                                            if(q == j)
                                                '\301'
                                                '\304'
                                        )
                                    '\277'
                                '\332'
                            '\263'
                        (toChar v + '0')
                    \\ [v, r, j: w] <- m
                    | r/2 == p && q >= hd w && q <= last w
                ]
            ]
            \\ q <- [0..k!!3]
        ]
        \\p<-[0..k!!1]
    ];
@ (L l)
    #p = twice
        ( \p
            = [
                [
                    v, r + 1:
                    map
                        (
                            (+)
                            (
                                sum [2 \\ [v: _] <- i| 0 <= v]
                                + sum (
                                    zipWith
                                        (
                                            \[_, _, _, c: _] [_, _, j: _] = j - c
                                        )
                                        t
                                        (
                                            takeWhile (\[v: _] = v < 0) (tl t)
                                        )
                                ) * (1 - sign (v + 1))
                                - x!!1
                            )
                        )
                        x
                ]
            \\ i <- inits p
            &  t <- tails p
            &  [v, r: x] <- p
            ]
        )
        (concatMap @ l)
    #g = [g \\ [_, 2, g: _] <- p]
    =[[-1, 0, (hd g + last g)/2: g]: p];
@ (I i) = [[i, 0, 0, 0]];

3

Than , 127 123 byte

↶≔⟦⟦θ⟧⟧ηFη«≔⊟ιζ¿⁼Iζ⪫⟦ζ⟧ω⊞υ⊞OιζFLζ⊞η⁺ι⟦⊖Lζκ§ζκ⟧»Wυ«≔⌊υι≔Φυ¬⁼κιυJ±⊗Lυ⊘⊖LιI⊟ιWι«≔⊟ιζ¿ζ«←§┐┬‹ζ⊟ιW⁼KKψ←─≔⁰ι»¿⊟ι┌¶┴¦│

Hãy thử trực tuyến!Liên kết là phiên bản dài dòng của mã. Giải trình:

Thay đổi hướng vẽ mặc định thành lên vì chúng ta không vẽ bất cứ thứ gì sang phải.

≔⟦⟦θ⟧⟧η

Bước đầu tiên là để chuyển đổi các đại diện mảng lồng nhau thành một đại diện index mà là một danh sách tất cả các mục cùng với các chỉ số của subarrays, ví dụ như cho đầu vào q=[1, [[[2, 3]], [4], 5]]những 5được q[1][2]và do đó danh sách chúng tôi muốn là1, 2 . Chúng tôi bắt đầu với một mục duy nhất để xử lý đó là danh sách chứa danh sách các chỉ số hiện tại (nghĩa là không có từ trước đến nay) và đầu vào ban đầu.

Fη«

Lặp lại các mảng khi chúng tôi xử lý chúng. (Than tiện lợi sẽ tiếp tục lặp lại qua một danh sách nếu bạn nhấn vào nó trong khi lặp.)

≔⊟ιζ

Lấy mảng tiếp theo để xử lý.

¿⁼Iζ⪫⟦ζ⟧ω

Đây thực sự là một vô hướng chứ không phải là một mảng?

⊞υ⊞Oιζ

Nếu vậy, thì danh sách chúng tôi thực sự thuộc về danh sách cuối cùng của danh sách các chỉ số.

FLζ

Mặt khác, lặp qua từng phần tử trong mảng này ...

⊞η⁺ι⟦⊖Lζκ§ζκ⟧»

... và lưu nó với danh sách chỉ mục mới cho đến nay để xử lý thêm. Chỉ mục tối đa của mảng cũng được lưu, được sử dụng để đặc biệt là phần tử cuối cùng của mảng.

Wυ«

Bây giờ chúng tôi đã sẵn sàng để lặp qua danh sách các danh sách chỉ mục. Tuy nhiên, danh sách này không theo thứ tự từ điển, vì vậy chúng tôi không thể lặp lại trực tiếp.

≔⌊υι

Tìm phần tử tiếp theo theo thứ tự từ điển.

≔Φυ¬⁼κιυ

Xóa nó khỏi danh sách.

J±⊗Lυ⊘⊖Lι

Nhảy đến vị trí vô hướng trong đầu ra. Chúng ta có thể tính toán điều này với điều kiện là chúng ta có thể giữ số lượng vô hướng mà chúng ta xuất ra và chúng ta cũng biết số lượng mục trong danh sách chỉ mục của nó.

I⊟ι

Thực tế in vô hướng.

Wι«

Lặp lại các mục trong danh sách chỉ mục. Một lần nữa, đây không phải là phép lặp đơn giản, bởi vì các mục nhập theo cặp và chúng ta cũng cần có thể thoát ra khỏi vòng lặp.

≔⊟ιζ

Trích xuất chỉ mục tiếp theo từ danh sách.

¿ζ«

Nếu đây không phải là yếu tố đầu tiên trong danh sách ...

←§┐┬‹ζ⊟ι

... Sau đó in hoặc tùy thuộc vào việc đây có phải là thành phần cuối cùng trong danh sách ...

W⁼KKψ←─

... và in đủ s để điền vào mục trước đó ở cấp độ này ...

≔⁰ι»

... Và xóa biến để thoát ra khỏi vòng lặp vì chúng ta đã hoàn thành ở đây.

¿⊟ι┌¶┴

Mặt khác, nếu đây là (phần tử đầu tiên của) một danh sách nhiều phần tử, sau đó in ┌┴, để con trỏ ở trên để đối phó với cha mẹ của cấp độ này.

¦│

Mặt khác, nếu đây là danh sách 1 phần tử thì chỉ cần in một và di chuyển lên một dòng để đối phó với cha mẹ của cấp độ này.

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.