Эстетически приятное дерево делителей - это дерево делителей ввода, n
которое для любого составного числа m
имеет два дочерних узла, которые являются парой делителей , ближайших к квадратному корню из m
. Левый узел должен быть меньшим делителем, m
а правый узел должен быть большим делителем m
. Простое число в дереве не должно иметь дочерних узлов. Ваше дерево может быть в виде текста или изображения. Правила для вывода текста искусства следующие.
Правила интервалов
Чтобы разнести узлы на дереве, у нас есть следующие правила:
- Все узлы на заданной глубине от корня должны находиться на одной строке текста в выводе.
/ \ NOT / \ / \ / 3 2 3 2
- Для левых узлов входящая ветвь должна быть в верхнем правом углу, если узел представляет собой однозначное число, иначе чуть выше последней цифры. Пример:
/ А ТАКЖЕ / 3 720
- Для правых узлов входящая ветвь должна быть в верхнем левом углу, если узел представляет собой однозначное число, иначе чуть выше первой цифры. Пример:
\ А ТАКЖЕ \ 7 243
- Для исходящих левых ветвей ветвь должна начинаться на один пробел слева от числа. Пример:
275 / 11
- Для исходящих правых ветвей ветвь должна начинаться на один пробел справа от номера. Пример:
275 \ 25
- Любые два узла на одном уровне дерева должны иметь как минимум два пробела между ними. В то же время любые два поддерева на одном и том же уровне дерева должны иметь как можно меньше промежутков между ними.
Это дерево не работает, потому что ** поддерево ** слишком близко. 504 / \ / \ / \ / \ 21 24 / \. / \ / \. / \ 3 7. 4 6 , / \ / \ .2 2 2 3 Хотя у этого дерева достаточно места между его ветвями. 504 / \ / \ / \ / \ / \ 21 ... 24 / \ ... / \ / \ ... / \ 3 7 ... 4 6 ... / \ / \ ... 2 2 2 3
- Если любые два поддерева расположены слишком близко друг к другу на дереве, их можно разделить, добавив еще один ряд ветвей
/\
в дерево над родительскими элементами .
441 / \ Последняя строка еще не заполнена, и у нас уже нет свободного места. 21 21 / \ / \ Добавить еще один ряд веток 441 / \ Почти, но 7 и 3 слишком близко друг к другу. / \ Еще один ряд должен сделать это. 21 21 / \ / \ 3 7 3 7 Добавить еще один ряд веток 441 / \ И мы закончили. / \ / \ 21 21 / \ / \ 3 7 3 7
Примеры
В качестве полного примера, дерево делителей 24 будет выглядеть так:
24
/ \
/ \
4 6
/ \ / \
2 2 2 3
4 и 6 - пара делителей, ближайшая к квадратному корню из 24. 4 слева, потому что она меньше. На следующей строке номер 2 слева от 3, потому что он меньше.
Дерево делителей для 63 должно выглядеть так:
63 and NOT like this 63
/ \ / \
7 9 3 21
/ \ / \
3 3 7 3
В неправильном дереве 3 и 21 не являются парой делителей, ближайших к квадратному корню из 63, а 3 и 7 не отсортированы должным образом. Расположение филиала на 21 правильно, хотя.
Для 42 вы должны иметь:
42 and NOT 42
/ \ / \
6 7 21 2
/ \ / \
2 3 3 7
Давайте посмотрим на 720. Обратите внимание, что нам нужно пять уровней ветвей от 720
так, чтобы 24
и 30
поддеревья были правильно разнесены. Кроме того , обратите внимание , что 24
и 30
имеют два уровня ветвей , так как 4
и 6
есть дочерние узлы , которые необходимо правильное расстояние и дочерние узлы 30
должны быть на том же уровне, что и дочерние узлы 24
.
720
/ \
/ \
/ \
/ \
/ \
24 30
/ \ / \
/ \ / \
4 6 5 6
/ \ / \ / \
2 2 2 3 2 3
Соревнование
- Ваша задача состоит в том, чтобы создать правильно расположенное эстетически приятное дерево делителей для ввода
n
, гдеn
положительное целое число больше 1. - Ваш вывод может содержать начальные и конечные пробелы и начальные и конечные переводы строк, но в противном случае он должен соответствовать приведенным выше правилам пробелов.
- Ваш вывод может быть: текстовый рисунок, изображение (другие форматы, которые будут добавлены, если это необходимо).
- Для изображений убедитесь, что узлы вашего дерева расположены правильно и что узлы с одинаковой высотой в дереве имеют одинаковую высоту на изображении.
- Это код гольф. Наименьшее количество байтов (или эквивалент) выигрывает.
Благодарим Стью Гриффина за то, что он подумал об этой идее, и большое спасибо Питеру Тейлору, Мартину Эндеру, Мего и Эсу Я за помощь в переписывании спецификации. Как обычно, любые предложения или исправления приветствуются. Удачи и хорошего гольфа!
Больше тестовых случаев:
2
4
/ \
2 2
20
/ \
4 5
/ \
2 2
323
/ \
17 19
362880
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
576 630
/ \ / \
/ \ / \
/ \ / \
/ \ / \
/ \ / \
/ \ / \
24 24 21 30
/ \ / \ / \ / \
/ \ / \ / \ / \
4 6 4 6 3 7 5 6
/ \ / \ / \ / \ / \
2 2 2 3 2 2 2 3 2 3
1286250
/ \
/ \
/ \
/ \
/ \
1050 1225
/ \ / \
/ \ / \
/ \ / \
30 35 35 35
/ \ / \ / \ / \
5 6 5 7 5 7 5 7
/ \
2 3
источник
Ответы:
Python 2 ,
711651575559554547539540530522 байтаПосле четырех месяцев попыток написать этот ответ, врезаться в стену, оставить ее на несколько недель, промыть, повторить, я наконец-то закончил правильный ответ ASCII на этот вызов. Осталось только поиграть в гольф, поэтому предложения по игре в гольф приветствуются. Попробуйте онлайн!
Гольф: -60 байт от переименования некоторых часто используемых функций и изменения способа возврата результата. -73 байта от изменения того, как проверяются высоты поддеревьев, как вычисляются интервальные переменные и как возвращается результат. -3 байта от
isdigit()
замены FlipTack . -16 байтов играли в гольф, чтоisdigit()
замена еще дальше и замена "" сE
. -5 байтов от незначительных улучшений и перехода с Python 3 на Python 2. -7 байтов от изменения способа возврата результата. -8 байтов от небольшого изменения к тому, какA
определяется,изменяя, как, удаляяT
определяется, и добавляяW
, используя гипотезу, что любое поддерево, по крайней мере, на одну более длинную ветвь, чем его аналог, в целом обязательно длиннее, чем его аналогQ
в целом, и редактирование, как результат возвращается. -10 байт от использованияA<10
вместоL(S(A))<2
дляA
иB
. -8 байт от изменения значенияH
по умолчанию до,[0]
поскольку код избегает проблемы изменяемых аргументов по умолчанию, никогда неH
изменяя, не изменяя способq
определения, используя(B>9)
вместо1-(B<10)
,p
полностью удаляя и создаваяF
вместо негоp+q-M
.Исправление ошибок: Гипотеза неверна, контрпример в
11**9 = 2357947691
. +1 байтобъяснение
Вся функция может быть сведена к четырем шагам:
n
,A
иB
.A
иB
, перерисовывая по мере необходимости.Я буду проходить каждый шаг по порядку.
Шаг 1. Это самый простой шаг, прямо скажем. Проверяйте каждое число
z
от 1 до квадратного корня на делимость наn
и берите наибольшее,z
иn//z
это соответствует. Возврат толькоstr(n)
еслиn
простое число (илиA==1
илиB==n
)Шаг 2. Нарисуйте поддеревья
A
иB
и получите количество/\
ветвей между узлами в поддеревьях. Для этого мы получаем индексы каждого шага с цифрами, получаем первые различия индексов и снова вычитаем 1. Как только у нас есть высоты, мы сравниваем их, чтобы получить наибольшее, и перерисовываем поддеревья с новыми высотами.У меня есть подозрение, что поддерево, которое в целом выше, всегда имеет ответвления, длина которых равна или равна разветвлениям на более коротком поддереве, и я могу использовать это для игры в коде, но у меня пока нет доказательств этого.Контрпример в11**9 = 2357947691
.Шаг 3. Для написания этого шага потребовались месяцы. Шаг 2 занял несколько дней, чтобы написать и отладить, но поиск правильных формул для пробелов занял много лет. Я посмотрю, смогу ли я сжать то, что я понял, в несколько абзацев. Обратите внимание, что часть кода в этом объяснении с тех пор вышла из реального кода.
Во- первых,
p
,q
,h
,P
,Q
,s
иM
.p
это количество символов от конца левой ветви/
до правого конца левого поддерева.q
это количество символов от левого конца правого поддерева до конца правой ветви/
.h
это число ветвей между корнем и поддеревьями.P
иQ
являются просто противоположностямиp
иq
полезны для размещения пространств вокруг/\
ветвей вплоть до корняn
.s
это количество пробелов, которые добавляются между двумя поддеревьями.M
самый простой; это длинаn
. Положите графически:Формула для определения
p
такова:p = len(x[0]) - x[0].rindex(str(A)[-1]) - (A<10)
длина, минус нулевой индекс последнего символа в A, минус поправка для однозначногоA
s.Формула для определения
q
такова:q = y[0].index(str(B)[0]) + (B>9)
индекс первого символа в B плюс поправка для нумерации минус коррекция для однозначныхB
s (объединенная в одну коррекцию для многозначныхB
s).Формула для определения
h
заключается в следующем:h = H[0] or (p+q+M%2+2-M)//2 or 1
. Либо мы берем предопределенное,H
что означает, что мы перерисовываем дерево(from_the_left + from_the_right + parity_space + 2 - len(root)) // 2)
, либо используем минимальное количество уровней ветвления, 1.Формула для определения
s
заключается в следующем:s = 2*h+M-p-q
. Мы вычитаемp
иq
из числа промежутков между ветвями корня в их самом широком2*h + M
.Шаг 4. И, наконец, мы собрали все вместе. Сначала мы создаем корень,
[" "*(P+h)+Z+" "*(Q+h)]
затем добавляем ветви к поддеревьям[" "*(P+J)+"/"+" "*(2*h+M-2*J-2)+"\\"+" "*(Q+J)for J in G(h)][::-1]
и, наконец, добавляем наши правильно расположенные поддеревья[(" "*(2*h+M-p-q)).join([(I<L(w)and w[I]or" "*L(w[0]))for w in(x,y)])for I in G(max(L(x),L(y)))]
.И вуаля! У нас есть эстетически приятное дерево делителей!
Ungolfing:
источник
isdigit
быть ваш чек'/'<x[i].strip()[0]<':'
?Mathematica,
9686817978 байтСпасибо @MartinEnder за 2 байта.
Вывод выглядит так:
объяснение
Сформировать список делителей ввода. Найдите ближайший к квадратному корню элемент ввода. (
Max
для выравнивания вывода)Найдите другой делитель, разделив входные данные на найденный выше делитель, примените этот ввод в качестве заголовка результата.
Повторите процесс.
Если вход прост, не делайте ничего.
Отформатируйте вывод.
Изменить: более эстетически приятная версия (258 байт)
Вывод выглядит так:
источник
Sqrt@#
->#^.5
(конечно, тогда вы не можете использовать инфиксную нотацию для,Nearest
но тогда вы можете использоватьMax@
).Древесный уголь , 302 байта
Попробуйте онлайн! Ссылка на подробную версию кода. Поскольку подробная версия очень многословна, он транслитерирует основной алгоритм на JavaScript:
источник