Arbres binaires
Un arbre binaire est un arbre avec des nœuds de trois types:
- nœuds terminaux, qui n'ont pas d'enfants
- nœuds unaires, qui ont chacun un enfant
- nœuds binaires, qui ont chacun deux enfants
Nous pouvons les représenter avec la grammaire suivante, donnée en BNF (forme Backus – Naur):
<e> ::=
<terminal>
| <unary>
| <binary>
<terminal> ::=
"0"
<unary> ::=
"(1" <e> ")"
<binary> ::=
"(2" <e> " " <e> ")"
Dans cette grammaire, les nœuds sont donnés en précommande et chaque nœud est représenté par un chiffre qui est le nombre d'enfants qu'il a.
Numéros Motzkin
Les nombres de Motzkin ( OEIS ) ( Wikipedia ) ont de nombreuses interprétations, mais une interprétation est que le n
nombre de Motzkin est le nombre d'arbres binaires distincts avec des n
nœuds. Un tableau des nombres Motzkin commence
N Motzkin number M(N)
1 1
2 1
3 2
4 4
5 9
6 21
7 51
8 127
...
par exemple, M(5)
est 9, et les neuf arbres binaires distincts avec 5 nœuds sont
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)
Tâche
Prenez un seul entier positif n
en entrée et sortez tous les arbres binaires distincts avec des n
nœuds.
Exemples n
de 1 à 5 avec parenthèses incluses pour plus de lisibilité
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)
Contribution
L'entrée sera un entier positif.
Production
La sortie doit être une représentation intelligible des arbres binaires distincts avec autant de nœuds. Il n'est pas obligatoire d'utiliser la chaîne exacte donnée par la grammaire BNF ci-dessus: il suffit que la syntaxe utilisée donne une représentation non ambiguë des arbres. Par exemple, vous pouvez utiliser []
au lieu de ()
, un niveau supplémentaire de crochets [[]]
au lieu de[]
, des parenthèses externes sont présentes ou manquantes, des virgules supplémentaires ou aucune virgule, des espaces supplémentaires, des parenthèses ou aucune parenthèse, etc.
Tous ces éléments sont équivalents:
(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
Également une variation proposée par @xnor dans un commentaire. Puisqu'il existe un moyen de traduire cela dans un format qui peut être compris, il est acceptable.
[[[]][]] is (2 (1 0) 0)
Pour rendre cela plus facile à comprendre convertir certains des []
à ()
comme si
[([])()]
Maintenant, si vous commencez par
[]
puis insérez un binaire qui a besoin de deux expressions que vous obtenez
[()()] which is 2
puis pour le premier () insérer un unaire qui a besoin d'une expression que vous obtenez
[([])()] which is 21
mais puisque []
ou ()
sans crochets intérieurs peut représenter 0 qui n'a plus besoin d'expressions, vous pouvez l'interpréter comme
2100
Notez que les réponses devraient fonctionner théoriquement avec une mémoire infinie, mais manqueront évidemment de mémoire pour une entrée finie dépendante de l'implémentation.
Variations de sortie
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)
Un endroit possible pour vérifier les arbres en double
Un endroit pour vérifier un doublon est avec M (5).
Cet arbre a été généré deux fois pour M (5) à partir de M (4) arbres
(2 (1 0) (1 0))
le premier en ajoutant une branche unaire à
(2 (1 0) 0)
et deuxièmement en ajoutant une branche unaire à
(2 0 (1 0))
Comprendre BNF
La BNF est composée de règles simples:
<symbol> ::= expression
où à gauche se trouve un nom de symbole entouré <>
.
À droite, l'expression de construction du symbole. Certaines règles utilisent d'autres règles dans la construction, par exemple
<e> ::= <terminal>
e
peut être un terminal
et certaines règles ont des caractères qui sont utilisés dans la construction du symbole, par exemple
<terminal> ::= "0"
terminal
est juste le caractère zéro.
Certaines règles ont plusieurs façons de les construire, par exemple
<e> ::=
<terminal>
| <unary>
| <binary>
Un e
peut être un <terminal>
ou un <unary>
ou un <binary>
.
Et certaines règles sont une séquence de parties, par exemple
<unary> ::= "(1" <e> ")"
A unary
est les caractères (1
suivis de ce qui peut être construit pour e
suivi de )
.
Vous commencez toujours par la règle de départ, qui pour cela <e>
.
Quelques exemples simples:
La séquence la plus simple est juste 0
. Nous commençons donc avec la règle de départ <e>
et voyons qu'il y a trois choix:
<terminal>
| <unary>
| <binary>
alors prenez le premier <terminal>
. Maintenant, un terminal n'a pas le choix et l'est 0
. Remplacez donc <terminal>
par 0
dans la <e>
règle et vous avez terminé.
Ensuite, le suivant est (1 0)
. Commencez avec <e>
et utilisez la règle <unary>
qui a
"(1" <e> ")"
Maintenant, cela nécessite un <e>
donc nous revenons à <e>
et faisons un choix de l'un des trois, cette fois en choisissant, <terminal>
ce qui donne 0
. Le remplacement 0
en (1 <e> )
donne (1 0)
, et il est remplacé en <unary>
si <e>
est (1 0)
.