Diziden ağaç çizme


24

Muhtemelen iç içe geçmiş, boş olmayan, tek basamaklı pozitif tamsayılar dizisi verildiğinde (benzersiz garanti edilmez), ASCII-art gösterimini kutu çizim karakterlerini kullanarak bir ağaç olarak çıktılayın ┌ ┴ ┐ ─ │ ┬ ┼ . (Bunlar Kod Sayfa 437'den kopyalanmıştır, ancak herhangi bir eşdeğer gösterimini kullanabilirsiniz).

Dizinin her tamsayısı ağacın bir yaprağı olmalıdır. Dizideki derinlemesine aynı düzeyde olan elementler ağacın aynı seviyesinde bulunmalıdır. Tüm elemanlar, ayırt edilebilecek kadar boşlukla ayrılmalıdır (aralarında ne kadar geniş, en az bir boşluk olduğunu belirlemek size bağlıdır).

Örneğin, verilen dizi [[1, [2]], [3, [4, 5]]]aşağıdaki ağacı çıkarır

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

Dizi [1, 2, 3]için ağaç benzeyebilirdi

┌─┼─┐
1 2 3

Ancak dizi [[1, 2, 3]]benziyordu

  │
┌─┼─┐
1 2 3

Dizi [1, [1, [1, [1]]]]gibi gözükse de

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

Daha karmaşık bir örnek olarak, [1, [[[2, 3], 4], 5]]olabilir

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

veya başka birkaç varyasyon.


  • Giriş ve çıkış uygun herhangi bir yöntemle verilebilir .
  • STDOUT'a yazdırabilir veya işlev sonucu olarak geri döndürebilirsiniz.
  • Tam bir program veya bir işlev kabul edilebilir.
  • Karakterler uygun şekilde hizalandığı sürece herhangi bir miktarda boş boşluk kabul edilebilir.
  • Standart boşluklar yasaktır.
  • Bu olduğundan, tüm normal golf kuralları geçerlidir ve en kısa kod (bayt cinsinden) kazanır.

[1,[[[2,3],4],5]]sağ alt ağaç sol alt ağaçla çakışmayacak şekilde kökün yapay olarak uzatılması gerektiğinden ilginç bir test durumu olabilir.
Poke

@Poke Örnek olarak eklenmiştir. Bu test durumu için birkaç olası varyasyon vardır.
AdmBorkBork

2
Bu sınama durumu için ilk örnek doğru olamaz. Bu, bir sonraki ikinci elemanı s önermektedir 1: 3 öğeleri bir dizi [2,3], 4ve 5. Ancak 4 ve 5 bitişik değildir.
Draco18,

4
Bu [1, [[[2, 3]], [4], 5]]bana benziyor .
Neil

Bu alternatif giriş biçimlerinden hangisi (varsa) kabul edilebilir?
Euro

Yanıtlar:


12

Python 3 , 400 393 390 bayt

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]

Yukarıdan aşağıya dizelerin bir listesini döndürür.

DÜZENLEME 1: ┴┼(Bir bayt net kayıt 2) yinelenen kaçınarak , bir dizeden 0 keserek, çizim karakterlerinin nasıl seçileceğini değiştirerek ┬┌┐( <yerine kullanın ==) değiştirerek 7 bayt kırpılmışL(z) kaçırdığıme

EDIT 2: -2 bayt ovs ve -1 bayt sayesinde Kevin Cruijssen

Çevrimiçi deneyin!

Ungolfed

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]

Her seferinde bir katman olan yapraklardan bir ağaç oluşturur.


2
Test vakalarını TIO bağlantınıza ekledim Çevrimiçi deneyin!
pizzapants184

Güzel cevap! Böyle bir değişkene boşluk atayarak iki bit olarak bu kısaltabilirsiniz: S,*K=' ┴┼│123456789'.
ovs

1
e==1e<2Bir bayt tasarruf etmek olabilir ( max(map(L,z))
Zorluk

3

Temiz , 544 506 bayt

Kaçışlar, SE / TIO'da geçersiz UTF-8'i önlemek için kullanılır, ancak geçerli değişmezler olduğu gibi bir bayt olarak sayılır.

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

Çevrimiçi deneyin!

Biçiminde giriş alır L[I 3, L[I 4, I 5], I 2]..

Ağaçları aşağıdan yukarıya, soldan sağa bağlar, sonra mesafeleri sağdan sola ayarlar.

Seçilmiş, sırala:

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

Kömür , 127 123 bayt

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

Çevrimiçi deneyin!Bağlantı, kodun ayrıntılı bir versiyonudur. Açıklama:

Sağa doğru bir şey çizmediğimiz için varsayılan çizim yönünü değiştirin.

≔⟦⟦θ⟧⟧η

İlk adım araya altdizilimlerden göstergeleri ile tüm girişlerin bir listesi bir dizin temsil içine yuvalanmış dizi temsilini dönüştürmek kadar, mesela girişi için olan bu nedenle istediğimiz listesidir veq=[1, [[[2, 3]], [4], 5]]5q[1][2]1, 2 . Mevcut endekslerin bir listesini (yani şimdiye kadar yok) ve orijinal girişi içeren bir liste olan tek bir giriş ile başlıyoruz.

Fη«

Biz onları işlerken diziler üzerinde döngü. (Yinelemeye zorlarsanız, Kömür Kömür bir liste üzerinde yinelenmeye devam eder.)

≔⊟ιζ

İşlenecek bir sonraki diziyi alın.

¿⁼Iζ⪫⟦ζ⟧ω

Bu aslında bir dizi yerine skaler mi?

⊞υ⊞Oιζ

Eğer öyleyse, o zaman yaptığımız liste aslında endeks listelerinin son listesine aittir.

FLζ

Aksi takdirde, bu dizideki her öğenin üzerine döngü ...

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

... ve daha sonraki işlemler için şimdiye kadar yeni dizin listesiyle kaydedin. Dizinin son öğesini özel olarak kullanmak için kullanılan dizinin maksimum dizini de kaydedilir.

Wυ«

Şimdi dizin listelerinin listesine geçmeye hazırız. Bununla birlikte, liste sözlüksel düzende değildir, bu yüzden doğrudan yineleyemiyoruz.

≔⌊υι

Sözlüksel sıradaki bir sonraki öğeyi bulun.

≔Φυ¬⁼κιυ

Listeden kaldırın.

J±⊗Lυ⊘⊖Lι

Çıktıdaki skaların konumuna atlayın. Bunu, hesapladığımız skaler sayısının sayısını tutabildiğimiz ve hesaplanan giriş sayısını bildiğimiz için hesaplayabiliriz.

I⊟ι

Aslında skaler yazdırın.

Wι«

Dizin listesindeki girişlerin üzerinden geçin. Yine, bu basit bir yineleme değildir, çünkü girdiler çiftler halinde gelir ve ayrıca döngüden kopabilmemiz gerekir.

≔⊟ιζ

Bir sonraki dizini listeden çıkarın.

¿ζ«

Bu, listedeki ilk öğe değilse ...

←§┐┬‹ζ⊟ι

... ardından yazdır veya listedeki son öğe olup olmadığına bağlı olarak ...

W⁼KKψ←─

... ve bu seviyedeki önceki girişleri dolduracak kadar s yazdırın ...

≔⁰ι»

... ve burada yaptığımızdan beri döngüden ayrılma değişkenini temizleyin.

¿⊟ι┌¶┴

Aksi halde eğer bu (ilk eleman) bir çok elemanlı listeden ┌┴ibaretse, imleci bu seviyenin ebeveyni ile başa çıkmak için üzerine bırakarak yazdırın .

¦│

Aksi takdirde, bu 1 öğeli bir liste ise, yalnızca a işaretini alın ve bu seviyenin ebeveyni ile ilgilenmek için bir satır yukarı kaydırın.

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.