배열에서 나무 그리기


24

단일 숫자 양의 정수로 중첩되거나 비어 있지 않은 배열이 제공 될 경우 (고유 보장되지 않음) 상자 그리기 문자를 사용하여 ASCII 아트 표현을 트리로 출력하십시오 ┌ ┴ ┐ ─ │ ┬ ┼. (이것들은 코드 페이지 437에서 복사되었지만 동등한 표현을 사용할 수 있습니다).

배열의 모든 정수는 나무의 잎이어야합니다. 배열에서 같은 수준의 요소는 같은 수준의 트리에 있어야합니다. 모든 요소는 구별하기에 충분한 공백으로 구분해야합니다 (최대 1 개의 공백 사이의 간격을 결정하는 것은 사용자에게 달려 있습니다).

예를 들어 주어진 array [[1, [2]], [3, [4, 5]]]이면 다음 트리를 출력하십시오.

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

배열의 [1, 2, 3]경우 나무는 다음과 같이 보일 수 있습니다.

┌─┼─┐
1 2 3

그러나 배열 [[1, 2, 3]]은 다음과 같습니다

  │
┌─┼─┐
1 2 3

배열 [1, [1, [1, [1]]]]은 다음과 같이 보일 수 있지만

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

더 복잡한 예를 들어, [1, [[[2, 3], 4], 5]]

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

또는 다른 여러 변형.


  • 입력 및 출력은 편리한 방법 으로 제공 할 수 있습니다 .
  • STDOUT에 인쇄하거나 함수 결과로 리턴 할 수 있습니다.
  • 전체 프로그램 또는 기능이 허용됩니다.
  • 문자가 적절하게 정렬되는 한 외부 공백은 허용됩니다.
  • 표준 허점 은 금지되어 있습니다.
  • 이것은 이므로 모든 일반적인 골프 규칙이 적용되며 가장 짧은 코드 (바이트)가 이깁니다.

[1,[[[2,3],4],5]]루트가 인위적으로 확장되어 오른쪽 하위 트리가 왼쪽 하위 트리와 충돌하지 않기 때문에 흥미로운 테스트 사례가 될 수 있습니다.
Poke

@Poke 예를 들어 추가되었습니다. 해당 테스트 사례에 대해 몇 가지 가능한 변형이 있습니다.
AdmBorkBork

2
해당 테스트 사례의 첫 번째 예는 맞지 않습니다. 이것은 옆에있는 s 번째 요소 1가 3 개의 항목으로 구성된 배열임을 나타냅니다.[2,3] , 4그리고 5. 그러나 4와 5는 인접하지 않습니다.
Draco18s

4
그것은 [1, [[[2, 3]], [4], 5]]나에게 보인다 .

이러한 대체 입력 형식 중 어떤 것이 허용됩니까?
Οurous

답변:


12

파이썬 (3) , 400 (393) 390 바이트

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]

문자열 목록을 위에서 아래로 반환합니다.

편집 1 : ┴┼(2 바이트의 순 저장) 중복을 피하고 한 문자열에서 0을 잘라 내고 그리기 문자 선택 방법을 변경하고 ┬┌┐( <대신 사용 ==) 7L(z) 내가 부재중e

편집 2 : ovs 덕분에 -2 바이트, Kevin Cruijssen 덕분에 -1 바이트

온라인으로 사용해보십시오!

언 골프

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]

한 번에 한 층씩 나뭇잎에서 나무를 만듭니다.


2
테스트 사례를 TIO 링크에 추가 했습니다. 온라인에서 사용해보십시오!
pizzapants184

좋은 대답입니다! 다음과 같이 변수에 공백을 할당하여이를 2 바이트로 줄일 수 있습니다 S,*K=' ┴┼│123456789'.
ovs

1
e==1할 수있다 e<2(나는 도전은 입력이 아닌 비어있는 상태 때문에, 이제까지 0이 될 수 있다고 생각하지 않습니다 - 빈 입력이 이미에 실패했을 바이트를 저장합니다 max(map(L,z)). 어쨌든 경우)
케빈 Cruijssen

3

청소 , 544 506 바이트

이스케이프는 SE / TIO에서 유효하지 않은 UTF-8을 피하기 위해 사용되지만 유효한 리터럴이므로 1 바이트로 계산됩니다.

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

온라인으로 사용해보십시오!

형식으로 입력을받습니다 L[I 3, L[I 4, I 5], I 2]..

나무를 아래에서 위로, 왼쪽에서 오른쪽으로 연결 한 다음 거리를 오른쪽에서 왼쪽으로 조정합니다.

아름답게 정리 된 :

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

, 127123 바이트

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

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. 설명:

오른쪽에 아무것도 그리지 않기 때문에 기본 그리기 방향을 위로로 변경하십시오.

≔⟦⟦θ⟧⟧η

첫 번째 단계는 함께 서브 어레이의 인덱스를 가진 모든 항목들의리스트가 인덱스 표시에 중첩 배열 표현으로 변환하는 예에서는 입력 q=[1, [[[2, 3]], [4], 5]]5되고 q[1][2], 따라서 우리가 원하는 목록이며1, 2 입니다. 처리 할 단일 항목으로 시작하여 현재 색인 목록 (즉 지금까지는 없음)과 원래 입력 목록을 포함하는 목록입니다.

Fη«

처리 할 때 배열을 반복합니다. 편리하게 숯은 반복하는 동안 목록을 누르면 목록을 계속 반복합니다.

≔⊟ιζ

처리 할 다음 배열을 가져옵니다.

¿⁼Iζ⪫⟦ζ⟧ω

이것이 실제로 배열이 아닌 스칼라입니까?

⊞υ⊞Oιζ

그렇다면 우리가 실제로 가지고있는리스트는 인덱스리스트의 최종리스트에 속합니다.

FLζ

그렇지 않으면이 배열의 각 요소를 반복합니다.

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

... 추가 처리를 위해 지금까지 새 색인 목록으로 저장하십시오. 또한 배열의 마지막 요소를 특수하게 사용하는 데 사용되는 배열의 최대 인덱스도 저장됩니다.

Wυ«

이제 색인 목록을 반복 할 준비가되었습니다. 그러나 목록은 사전 순이 아니므로 직접 반복 할 수 없습니다.

≔⌊υι

사전 식 순서로 다음 요소를 찾으십시오.

≔Φυ¬⁼κιυ

목록에서 제거하십시오.

J±⊗Lυ⊘⊖Lι

출력에서 스칼라의 위치로 이동하십시오. 출력하는 스칼라 수를 계산할 수 있고 인덱스 목록의 항목 수도 알고 있으면이를 계산할 수 있습니다.

I⊟ι

실제로 스칼라를 인쇄하십시오.

Wι«

색인 목록의 항목을 반복하십시오. 다시 말하지만, 이는 항목이 쌍을 이루고 루프에서 벗어날 수 있어야하기 때문에 간단한 반복이 아닙니다.

≔⊟ιζ

목록에서 다음 색인을 추출하십시오.

¿ζ«

이것이 목록의 첫 번째 요소가 아닌 경우 ...

←§┐┬‹ζ⊟ι

... 그런 다음 목록의 마지막 요소인지 여부에 따라 인쇄 하거나 ...

W⁼KKψ←─

... 이 레벨에서 이전 항목까지 채울 수 있도록 충분한 s를 인쇄하십시오 .

≔⁰ι»

... 여기서 루프에서 빠져 나올 변수를 지우십시오.

¿⊟ι┌¶┴

그렇지 않으면 이것이 다중 요소 목록의 첫 번째 요소 인 ┌┴경우을 인쇄 하고이 레벨의 상위를 처리하기 위해 커서를 위에 둡니다 .

¦│

그렇지 않으면 이것이 1 요소 목록이라면 a를 인쇄 하고이 레벨의 부모를 처리하기 위해 줄을 위로 이동하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.