Einen Baum aus einem Array zeichnen

24

Geben Sie bei einem möglicherweise verschachtelten, nicht leeren Array von positiven einstelligen Ganzzahlen (nicht garantiert eindeutig) die ASCII-Art-Darstellung als Baum aus, und verwenden Sie dabei die Zeichen in der Box ┌ ┴ ┐ ─ │ ┬ ┼ . (Diese wurden aus Codepage 437 kopiert, Sie können jedoch eine beliebige entsprechende Darstellung verwenden.)

Jede Ganzzahl des Arrays sollte ein Blatt des Baums sein. Elemente der gleichen Ebene tief im Array sollten auf der gleichen Ebene der Struktur vorhanden sein. Alle Elemente sollten durch genügend Leerzeichen voneinander getrennt sein (Sie können bestimmen, wie breit mindestens ein Leerzeichen dazwischen sein muss).

Geben Sie beispielsweise für ein bestimmtes Array [[1, [2]], [3, [4, 5]]]den folgenden Baum aus

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

Für array könnte [1, 2, 3]der Baum so aussehen

┌─┼─┐
1 2 3

Aber das Array [[1, 2, 3]]würde so aussehen

  │
┌─┼─┐
1 2 3

Während das Array [1, [1, [1, [1]]]]aussehen könnte

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

Als komplizierteres Beispiel [1, [[[2, 3], 4], 5]]könnte es sein

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

oder mehrere andere Variationen.


  • Die Ein- und Ausgabe kann auf jede bequeme Weise erfolgen .
  • Sie können es an STDOUT drucken oder als Funktionsergebnis zurückgeben.
  • Es ist entweder ein vollständiges Programm oder eine Funktion zulässig.
  • Beliebige Leerzeichen sind zulässig, sofern die Zeichen richtig ausgerichtet sind.
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Byte) gewinnt.
AdmBorkBork
quelle
[1,[[[2,3],4],5]]Dies könnte ein interessanter Testfall sein, da die Wurzel künstlich erweitert werden muss, damit der rechte Teilbaum nicht mit dem linken Teilbaum kollidiert.
Poke
@Poke Als Beispiel hinzugefügt. Für diesen Testfall gibt es mehrere mögliche Varianten.
AdmBorkBork
2
Das erste Beispiel für diesen Testfall kann nicht richtig sein. Das legt nahe , dass das zweite Element s neben dem 1eine Anordnung von 3 Artikel ist: [2,3], 4, und 5. Aber 4 und 5 sind nicht benachbart.
Draco18s
4
Das sieht [1, [[[2, 3]], [4], 5]]für mich so aus.
Neil
Welches (wenn überhaupt) dieser alternativen Eingabeformate wäre akzeptabel?
Am

Antworten:

12

Python 3 , 400 393 390 Bytes

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]

Gibt eine Liste von Zeichenfolgen von oben nach unten zurück.

BEARBEITEN 1: 7 Bytes gekürzt, indem Duplikationen vermieden ┴┼( Nettoersparnis von 2 Bytes), 0 aus der einen Zeichenfolge herausgeschnitten, die Auswahl der Zeichnungszeichen geändert ┬┌┐(Verwendung <statt ==) und ein L(z)fehlendes ersetzt wurdene

EDIT 2: -2 Bytes dank Ovs und -1 Bytes dank Kevin Cruijssen

Probieren Sie es online!

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]

Baut einen Baum aus den Blättern, eine Schicht nach der anderen.

Beefster
quelle
2
Ich habe die Testfälle zu Ihrem TIO-Link hinzugefügt. Probieren Sie es online aus!
Pizzapants184
Gute Antwort! Sie können dies durch zwei Bytes verkürzen , indem der Raum auf eine Variable wie diese Zuordnung: S,*K=' ┴┼│123456789'.
Ovs
1
e==1kann sein e<2, ein Byte zu speichern (ich glaube nicht, dass es jemals 0 sein kann, da die Abfrage angibt, dass die Eingabe nicht leer ist - und leere Eingaben max(map(L,z))in diesem Fall ohnehin schon fehlgeschlagen wären.)
Kevin Cruijssen,
3

Sauber , 544 506 Bytes

Escapes werden verwendet, um ungültiges UTF-8 unter SE / TIO zu vermeiden, werden jedoch als ein Byte gezählt, da sie gültige Literale sind

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

Probieren Sie es online!

Übernimmt Eingaben im Format L[I 3, L[I 4, I 5], I 2]..

Verbindet die Bäume von links nach rechts von unten nach oben und passt dann die Abstände von rechts nach links an.

Prettified, Art von:

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]];
Οurous
quelle
3

Kohle , 127 123 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

Ändern Sie die Standardzeichnungsrichtung in "Hoch", da wir nichts nach rechts zeichnen.

≔⟦⟦θ⟧⟧η

Der erste Schritt besteht darin, die verschachtelte Array-Darstellung in eine Index-Darstellung umzuwandeln, die eine Liste aller Einträge zusammen mit den Indizes der Subarrays darstellt, z. B. für die Eingabe q=[1, [[[2, 3]], [4], 5]]das 5ist q[1][2]und damit die gewünschte Liste 1, 2. Wir beginnen mit einem einzelnen zu verarbeitenden Eintrag, der eine Liste enthält, die die aktuellen Indizes (dh bisher keine) und die ursprüngliche Eingabe enthält.

Fη«

Durchlaufen Sie die Arrays, während wir sie verarbeiten. (Günstigerweise durchläuft Charcoal weiterhin eine Liste, wenn Sie diese während der Iteration aufrufen.)

≔⊟ιζ

Holen Sie sich das nächste zu verarbeitende Array.

¿⁼Iζ⪫⟦ζ⟧ω

Ist das eigentlich eher ein Skalar als ein Array?

⊞υ⊞Oιζ

Wenn ja, dann gehört die Liste, die wir hatten, tatsächlich auf die endgültige Liste der Indexlisten.

FLζ

Andernfalls durchlaufen Sie jedes Element in diesem Array ...

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

... und speichern Sie es mit seiner neuen Indexliste zur weiteren Bearbeitung. Der maximale Index des Arrays wird ebenfalls gespeichert, um den Sonderfall des letzten Elements des Arrays zu definieren.

Wυ«

Jetzt können wir die Liste der Indexlisten durchlaufen. Die Liste ist jedoch nicht lexikografisch geordnet, sodass wir sie nicht direkt durchlaufen können.

≔⌊υι

Finden Sie das nächste Element in lexikografischer Reihenfolge.

≔Φυ¬⁼κιυ

Entfernen Sie es aus der Liste.

J±⊗Lυ⊘⊖Lι

Springe zur Position des Skalars in der Ausgabe. Wir können dies berechnen, indem wir die Anzahl der von uns ausgegebenen Skalare zählen und die Anzahl der Einträge in der Indexliste kennen.

I⊟ι

Tatsächlich drucken Sie den Skalar.

Wι«

Durchlaufen Sie die Einträge in der Indexliste. Auch dies ist keine einfache Iteration, da die Einträge paarweise erfolgen und wir auch in der Lage sein müssen, aus der Schleife auszubrechen.

≔⊟ιζ

Extrahieren Sie den nächsten Index aus der Liste.

¿ζ«

Wenn dies nicht das erste Element in der Liste ist ...

←§┐┬‹ζ⊟ι

... dann drucken oder je nachdem, ob dies das letzte Element in der Liste ist ...

W⁼KKψ←─

... und drucke genug s, um den vorherigen Eintrag auf dieser Ebene zu füllen ...

≔⁰ι»

... und lösche die Variable, um aus der Schleife auszubrechen, da wir hier fertig sind.

¿⊟ι┌¶┴

Andernfalls, wenn dies (das erste Element von) einer Liste mit mehreren Elementen ist, drucken Sie die aus ┌┴, und lassen Sie den Cursor über der Liste , um die übergeordnete Ebene dieser Ebene zu behandeln.

¦│

Andernfalls, wenn es sich um eine 1-Element-Liste handelt, drucken Sie einfach ein und bewegen Sie sich eine Zeile nach oben, um sich mit dem übergeordneten Element dieser Ebene zu befassen.

Neil
quelle