Binäre Bäume
Ein binärer Baum ist ein Baum mit drei Knotentypen:
- Endknoten, die keine Kinder haben
- unäre Knoten, die jeweils ein Kind haben
- Binärknoten, die jeweils zwei untergeordnete Knoten haben
Wir können sie mit der folgenden Grammatik darstellen, die in BNF (Backus-Naur-Form) angegeben ist:
<e> ::=
<terminal>
| <unary>
| <binary>
<terminal> ::=
"0"
<unary> ::=
"(1" <e> ")"
<binary> ::=
"(2" <e> " " <e> ")"
In dieser Grammatik sind die Knoten in vorrangiger Reihenfolge angegeben, und jeder Knoten wird durch eine Ziffer dargestellt, die die Anzahl der Kinder angibt, die er hat.
Motzkin-Zahlen
Motzkin-Zahlen ( OEIS ) ( Wikipedia ) haben viele Interpretationen, aber eine Interpretation ist, dass die n
th Motzkin-Zahl die Anzahl der verschiedenen Binärbäume mit n
Knoten ist. Eine Tabelle mit Motzkin-Nummern beginnt
N Motzkin number M(N)
1 1
2 1
3 2
4 4
5 9
6 21
7 51
8 127
...
zB M(5)
9, und die neun verschiedenen Binärbäumen mit 5 Knoten
1 (1 (1 (1 (1 0))))
2 (1 (1 (2 0 0)))
3 (1 (2 0 (1 0)))
4 (1 (2 (1 0) 0))
5 (2 0 (1 (1 0)))
6 (2 0 (2 0 0))
7 (2 (1 0) (1 0))
8 (2 (1 (1 0)) 0)
9 (2 (2 0 0) 0)
Aufgabe
Nehmen Sie eine einzelne positive Ganzzahl n
als Eingabe und geben Sie alle unterschiedlichen Binärbäume mit n
Knoten aus.
Beispiele für n
1 bis 5 mit Klammern zur besseren Lesbarkeit
0
(1 0)
(1 (1 0))
(2 0 0)
(1 (1 (1 0)))
(1 (2 0 0))
(2 0 (1 0))
(2 (1 0) 0)
(1 (1 (1 (1 0))))
(1 (1 (2 0 0)))
(1 (2 0 (1 0)))
(1 (2 (1 0) 0))
(2 0 (1 (1 0)))
(2 0 (2 0 0))
(2 (1 0) (1 0))
(2 (1 (1 0)) 0)
(2 (2 0 0) 0)
Eingang
Die Eingabe ist eine positive ganze Zahl.
Ausgabe
Die Ausgabe sollte eine verständliche Darstellung der verschiedenen Binärbäume mit so vielen Knoten sein. Es ist nicht obligatorisch, die exakte Zeichenfolge zu verwenden, die in der obigen BNF-Grammatik angegeben ist: Es reicht aus, wenn die verwendete Syntax eine eindeutige Darstellung der Bäume ergibt. ZB können Sie []
anstelle von ()
eine zusätzliche Ebene von Klammern [[]]
verwenden []
, äußere Klammern sind vorhanden oder fehlen, zusätzliche Kommas oder keine Kommas, zusätzliche Leerzeichen, Klammern oder keine Klammern usw.
Alle diese sind gleichwertig:
(1 (2 (1 0) 0))
[1 [2 [1 0] 0]]
1 2 1 0 0
12100
(1 [2 (1 0) 0])
.:.--
*%*55
(- (+ (- 1) 1))
-+-11
Auch eine Variation von @xnor in einem Kommentar. Da es eine Möglichkeit gibt, dies in ein verständliches Format zu übersetzen, ist dies akzeptabel.
[[[]][]] is (2 (1 0) 0)
Um dies verständlicher zu machen, konvertieren einige der so []
zu ()
mögen
[([])()]
Beginnen Sie jetzt mit
[]
Fügen Sie dann eine Binärdatei ein, die zwei Ausdrücke benötigt, die Sie erhalten
[()()] which is 2
und dann füge für first () einen Unary ein, der einen Ausdruck benötigt, den du bekommst
[([])()] which is 21
aber da []
oder ()
ohne innere Klammer 0 darstellen kann, was keine weiteren Ausdrücke erfordert, können Sie es als interpretieren
2100
Beachten Sie, dass Antworten theoretisch mit unbegrenztem Speicher funktionieren sollten, bei einer implementierungsabhängigen endlichen Eingabe jedoch offensichtlich nicht genügend Speicher vorhanden ist.
Variationen der Ausgabe
BNF xnor Christian Ben
b(t, b(t, t)) [{}{{}{}}] (0(00)) (1, -1, 1, -1)
b(t, u(u(t))) [{}{(())}] (0((0))) (1, -1, 0, 0)
b(u(t), u(t)) [{()}{()}] ((0)(0)) (1, 0, -1, 0)
b(b(t, t), t) [{{}{}}{}] ((00)0) (1, 1, -1, -1)
b(u(u(t)), t) [{(())}{}] (((0))0) (1, 0, 0, -1)
u(b(t, u(t))) [({}{()})] ((0(0))) (0, 1, -1, 0)
u(b(u(t), t)) [({()}{})] (((0)0)) (0, 1, 0, -1)
u(u(b(t, t))) [(({}{}))] (((00))) (0, 0, 1, -1)
u(u(u(u(t)))) [(((())))] ((((0)))) (0, 0, 0, 0)
Ein möglicher Ort, um nach doppelten Bäumen zu suchen
Ein Ort, um nach einem Duplikat zu suchen, ist mit M (5).
Dieser eine Baum wurde zweimal für M (5) aus M (4) Bäumen generiert
(2 (1 0) (1 0))
die erste durch Hinzufügen eines unären Zweigs zu
(2 (1 0) 0)
und zweitens durch Hinzufügen eines unären Zweigs zu
(2 0 (1 0))
BNF verstehen
BNF besteht aus einfachen Regeln:
<symbol> ::= expression
wo auf der linken Seite ist ein Symbolname umgeben von <>
.
Rechts ist der Ausdruck für die Konstruktion des Symbols. Einige Regeln verwenden andere Regeln in der Konstruktion, z
<e> ::= <terminal>
e
kann sein a terminal
und einige Regeln haben Zeichen, die bei der Konstruktion des Symbols verwendet werden, z
<terminal> ::= "0"
terminal
ist nur das Zeichen Null.
Einige Regeln können auf mehrere Arten erstellt werden, z
<e> ::=
<terminal>
| <unary>
| <binary>
An e
kann a <terminal>
oder a <unary>
oder a sein <binary>
.
Und einige Regeln sind eine Folge von Teilen, z
<unary> ::= "(1" <e> ")"
A unary
sind die Zeichen, denen (1
folgt, wofür konstruiert werden kann, e
gefolgt von )
.
Sie beginnen immer mit der Startregel, die dafür gilt <e>
.
Einige einfache Beispiele:
Die einfachste Folge ist gerade 0
. Wir beginnen also mit der Startregel <e>
und stellen fest, dass es drei Möglichkeiten gibt:
<terminal>
| <unary>
| <binary>
also nimm den ersten <terminal>
. Jetzt hat ein Terminal keine Auswahl mehr und ist 0
. So ersetzen Sie <terminal>
mit 0
in der <e>
Regel und Sie sind fertig.
Dann ist der nächste (1 0)
. Beginnen Sie mit <e>
und verwenden Sie die Regel, <unary>
die hat
"(1" <e> ")"
Nun, das braucht eine, <e>
also kehren wir zurück <e>
und treffen eine Wahl von einer der drei, diesmal eine Wahl, <terminal>
die gibt 0
. Ersetzen 0
in (1 <e> )
gibt (1 0)
, und dies wird ersetzt in <unary>
so <e>
ist (1 0)
.
quelle
Antworten:
Haskell, 68 Bytes
Endknoten werden durch
0
unäre bzw. binäre Knoten dargestellt(e)
.(ee)
, so sind die beiden Drei-Knoten-Bäume als(00)
und gegeben((0))
.Beispiele:
quelle
CJam (37 Bytes)
Online-Demo . Beachten Sie, dass dies nicht sehr effizient ist und Sie wahrscheinlich nicht versuchen möchten, die Eingabe
5
online zu berechnen .Dissektion folgt.
quelle
Pyth (
242119 Bytes)Dies basiert auf meiner Python 3-Lösung .
Es ist mein erstes Mal, dass ich Pyth benutze, also ist dies wahrscheinlich immer noch golffähig.
Beispiel , Ausgabe bei Eingabe ist
4
:1 repräsentiert einen binären Knoten, 0 repräsentiert einen unären Knoten und -1 repräsentiert einen Endknoten. Am Ende jedes Baums befindet sich ein impliziter Endknoten.
Erklärung :
quelle
Brainfuck, 107 Bytes
Formatiert:
Probieren Sie es online aus
Die Eingabe wird als Byte genommen , und der Baum
12100
wird wie folgt dargestellt\x01\x02\x03\x02
: Zurückkonvertieren, Übersetzentr/\x01\x02\x03/012/
, Umkehren der Zeichenfolge und Hinzufügen eines Finales0
. Bäume werden durch getrennt\xfe
. (Die Ausgabe kann leichter lesbar gemacht werden, indem z. B. das erste-
in-36
und das.
in geändert werden+47.-47
, wobei-36
dies eine Zeichenfolge mit 36-
Zeichen usw. bedeutet.)Dieser Ansatz nutzt die Eigenschaft (die auch Ben Frankel verwendet hat): Unter Berücksichtigung der möglichen Knoten als
-1, 0, 1
und ohne Berücksichtigung des-1
Endknotens stellt eine Liste einen gültigen Baum dar, wenn und nur wenn (1) alle Präfixe der Liste eine nicht negative Summe haben, und (2) die Summe der gesamten Liste ist gleich0
. Die erste Bedingung wird beim Generieren von Zwischenknoten beibehalten, sodass am Ende nur die zweite Bedingung überprüft werden muss.Das Band ist in 5-Knoten-Zellen unterteilt.
wo
i
ist der Index (absteigend von links nach rechts),d
ist die Teilsumme undx
ist das Element.Skizze des Kontrollflusses:
Beachten Sie, dass ein Wert manchmal als einer oder zwei Werte größer als der tatsächliche (konzeptionelle) Wert gespeichert oder initialisiert und nach Bedarf angepasst wird.
quelle
Python 3 (
138134128121119 Byte)Beispielausgabe für
n=5
:1 repräsentiert einen binären Knoten, 0 repräsentiert einen unären Knoten und -1 repräsentiert einen Endknoten. Am Ende jedes Baums befindet sich ein impliziter Endknoten.
Das Programm beginnt zu lange zu dauern
n=17
.quelle
JavaScript (Firefox 30-57), 79 Byte
Dabei steht es
-1
für ein Terminal,0
einen unären Knoten und1
einen binären Knoten. Fängt an,m=14
auf meinem PC langsam zu werden . Arbeitet rekursiv vom Ende des Baums zurück.l
wird durch die Tatsache begrenzt, dass am Ende möglicherweise nur noch 1 Knoten übrig ist.n
wird durch die Notwendigkeit begrenzt, dass genügend nicht berücksichtigte Knoten vorhanden sein müssen, um seine untergeordneten Knoten zu sein.quelle
Prolog,
149144138137131107 BytesUnd um die Lösungen zu zählen
quelle
Python, 71 Bytes
Dies stellt Bäume als verschachtelte Tupel dar, z. B.
((((),), ()),)
, die((())())
durch Entfernen von Kommas, Leerzeichen und dem äußersten Rand umgewandelt werden können()
.Eine frühere 76-Byte-Version:
quelle
CJam, 38 Bytes
Verwendet einen anderen Ansatz als Peter Taylors CJam-Antwort.
Die Ausgabe wird ungefähr so aussehen
1110120020102100
. Jeder Baum ist eine Gruppe vonn
Ziffern (wobein
die eingegebene Nummer ist).Die Grundidee ist , dass wir jede mögliche Folge von Ziffern zu erzeugen
0
,1
und2
, und dann nur diejenigen herauszufiltern , die wohlgeformt sind Bäume.quelle