Я решил проблему, которую вы описываете, и это было больше работы, чем я ожидал (хотя и меньше 1500 байт кода). Основная модель - работать снизу вверх, чтобы получить подчеркивания, а затем снизу вниз, чтобы получить отступы. Вот схема функций, которые я определил для ее решения:
def height_tree(node):
Рекурсивно, сначала глубина. Простой код для расчета высоты дерева. Это необходимо только следующей функции, чтобы различать узел типа [a]
, у которого нет дочерних элементов, но для которого требуется подделка, и для узла, у которого нет дочерних элементов, для которого мы не хотим добавлять поддельные. .
def covered_tree(node, level=0):
Рекурсивно, сначала глубина. Сначала выполняется рекурсивная обработка, затем определяется ширина покрытия. Если значение level
по умолчанию равно нулю, установите его на height_tree()
выше. Возвращает действительное дерево:
('[hello_____]', (('[a]', (('...', ()),)), ('[b______]', (('[cde]', ()), ('[fg]', ())))))
но родительские строки были расширены с помощью скобок и подчеркиваний. Дает узлы, такие как [a]
и [onomatopoeia]
с поддельными дочерними элементами, состоящие из заполнения периода
def padded_tree(node, tail=True):
Рекурсивно, сначала глубина. Сначала работает дополнение, а затем повторяется. Обрабатывает только заполнение в самом правом конце ветви, внутреннее заполнение было обработано covered_tree()
выше. Возвращает действительное дерево:
('[supercalifragilisticexpialidocious]', (('[a__________________]', (('[b____]', (('[candy]', ()),)), ('[onomatopoeia]', (('..............', ()),)))), ('[d__]..........', (('[egg]..........', (('[f]............', ()),)),))))
но родительские строки были расширены с добавлением точки.
def print_tree(node, line_width=0):
Итеративный, сначала ширина. Печатает дерево, устанавливая line_width
на ширину верхнего узла, так как оно охватывает все. Считает ширину печати до нуля, выводит новую строку и сбрасывает ширину печати обратно до line_width
.
OUTPUT
>>> tree = ("hello", (("a", ()), ("b", (("cde", ()), ("fg", ())))))
>>> print_tree(padded_tree(covered_tree(tree)))
[hello_____]
[a][b______]
...[cde][fg]
>>>
>>> tree = ("supercalifragilisticexpialidocious",(("a",(("b",(("candy",()),)),("onomatopoeia",()),)),("d",(("egg",(("f",()),)),)),))
>>> print_tree(padded_tree(covered_tree(tree)))
[supercalifragilisticexpialidocious]
[a__________________][d__]..........
[b____][onomatopoeia][egg]..........
[candy]..............[f]............
>>>
Я не совсем понимаю, как работает функция cover_tree. Ты можешь
уточни пожалуйста?
Поскольку это критическая функция, давайте разберем ее:
def covered_tree(node, level=0):
Если level
равен нулю, по умолчанию установите level
на результат height_tree(node)
. Разделите узел на две части: родитель (метка) и список дочерних элементов (узлы).
Выполните нашу рекурсию, создав новый список дочерних элементов (узлов), который является результатом вызова covered_tree()
для каждого дочернего элемента, но с явной передачей level - 1
. Для каждого из этих новых дочерних элементов суммируйте len()
(ширину) их меток. Из этого подсчета вычтите len()
(ширину) родительской метки и ширину 2, чтобы учесть скобки.
Теперь мы готовы создать наш возвратный узел. Это кортеж, который состоит из: нашего родителя, отформатированного в скобках плюс количество подчеркиваний, которые мы только что вычислили на предыдущем шаге; наш новый список детей. Однако, если имеется нет потомков, и level
больше единицы, то вместо пустых потомков мы возвращаем поддельный список потомков, состоящий из потомков с меткой строка периодов, чьи собственные дочерние элементы являются пустым кортежем (т. е. нашим пустым списком дочерних элементов). Длина этой строки периодов снова равна len()
(ширина) нашей родительской метки плюс 2 для учета скобок:
('[hello_____]', (('[a]', (('...', ()),)), ('[b______]', (('[cde]', ()), ('[fg]', ())))))