Рисование треугольника Серпинского было сделано до смерти . Есть и другие интересные вещи, которые мы можем сделать с этим, хотя. Если мы достаточно прищуримся в треугольнике, мы можем рассматривать перевернутые треугольники как узлы фрактального графа. Давайте найдем способ обойти этот график!
Сначала давайте назначим номер каждому узлу. Самый большой перевернутый треугольник будет нулевым узлом, а затем мы просто спустимся слой за слоем (сначала в ширину), назначив последовательные числа в порядке сверху-слева-справа:
Нажмите, чтобы увеличить версию, где маленькие цифры немного менее размыты.
(Конечно, эта модель продолжает до бесконечности внутри синих треугольников.) Еще один способ определить нумерацию, что центральный узел имеет индекс 0
, а дети узла i
(смежные треугольники следующего меньшего масштаба) имеют индексы 3i+1
, 3i+2
и 3i+3
.
Как мы перемещаемся по этому графику? Есть шесть естественных шагов, которые можно сделать из любого данного треугольника:
- Можно всегда перемещаться через середину одного из ребер к одному из трех дочерних узлов текущего узла. Мы будем обозначать эти шаги как
N
,SW
иSE
. Например , если мы в настоящее время на узле2
, это приведет к узлам7
,8
,9
соответственно. Другие ходы по краям (непрямым потомкам) запрещены. - Можно также пройти через один из трех углов, если он не касается края треугольника, ни непосредственному родителю, ни одному из двух косвенных предков. Мы будем обозначать эти шаги как
S
,NE
иNW
. Например, если мы в настоящее время находимся на узле31
,S
приведет к10
,NE
будет недействительным иNW
приведет к0
.
Соревнование
Дайте два неотрицательных целых числа x
и y
найдите кратчайший путь от x
до y
, используя только шесть ходов, описанных выше. Если существует несколько кратчайших путей, выведите любой из них.
Обратите внимание, что ваш код должен работать не только для 5 уровней, изображенных на диаграмме выше. Вы можете предположить это x, y < 1743392200
. Это гарантирует, что они помещаются в 32-разрядное целое число со знаком. Обратите внимание, что это соответствует 20 уровням дерева.
Ваш код должен обработать любой действительный ввод менее чем за 5 секунд . Хотя это исключает грубый поиск в ширину, это должно быть довольно слабое ограничение - моя эталонная реализация обрабатывает произвольный ввод для глубины 1000 за полсекунды (это ~ 480-значные числа для узлов).
Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводя результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).
Выход должен быть плоским, недвусмысленным список строк N
, S
, NE
, NW
, SE
, SW
, используя любой разумный разделитель (пробелы, символы перевода строки, запятые, ","
...).
Применяются стандартные правила игры в гольф .
Тестовые случаи
Первые несколько тестовых случаев могут быть разработаны вручную, используя диаграмму выше. Другие обеспечивают, чтобы ответы были достаточно эффективными. Для них могут быть другие решения той же длины, которые не перечислены.
0 40 => N N N N
66 67 => S SW N N N
30 2 => NW NW -or- NE SW
93 2 => NE SW
120 61 => NW NW NW NW N SE SW N
1493682877 0 => S S NW NW
0 368460408 => SW SW N N SW SW SE SW SW N SE N N SW SW N SE SE
1371432130 1242824 => NW NW NE NW N SE SW SW SW SE SE SW N N N N SW
520174 1675046339 => NE NW NE NE SE SE SW SW N SE N SW N SW SE N N N N SE SE SW SW
312602548 940907702 => NE NW S SW N N SW SE SE SE SW SE N N SW SE SE SE SW
1238153746 1371016873 => NE NE NE SE N N SW N N SW N SE SE SW N SW N N SE N SE N
547211529 1386725128 => S S S NE NW N N SE N SW N SE SW SE SW N SE SE N SE SW SW N
1162261466 1743392199 => NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE NE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE SE
источник
APL (Dyalog Unicode) ,
144132129118133132130124117 байт SBCSБольшое спасибо Ven и ngn за их помощь в игре в гольф в The APL Orchard , отличном месте для изучения языка APL.
⎕IO←0
, Предложения по игре в гольф приветствуются.Изменить: -12 байт благодаря Ven и ngn, изменив способ
n
определения и переключившись с 1-индексации на 0-индексации. -3 из-за исправления ошибки, когда не все переключалось на 0-индексацию. -11 байт из-за изменения какP
иQ
как определены. +15 байт из-за исправления проблемы, когда мой алгоритм был некорректным, большое спасибо ngn за помощь в созданииs[⊃⍋|M-s]
раздела. -2 байта от перестановки метода поиска пути возврата и +1 байт для исправления ошибки. -2 байта благодаря Адаму от переопределения определенияI
. -6 байт благодаря ngn от переопределения определения'S' 'NE' 'NW' 'N' 'SW' 'SE'
и от перестановкиt
определения (это больше не отдельная переменная). -7 байт благодаря тому, какs
определяется ngn от игры в гольф .Попробуйте онлайн!
Объяснение ошибки в алгоритме
Основная проблема в том, что я думал, что кратчайший путь идет напрямую через общего предка, и на самом деле я не мог пройти через предка общего предка. Это неверно, как продемонстрируют следующие примеры.
С 66 до 5
С 299792458 по 45687
Пояснение к коду
Альтернативное решение с использованием Dyalog Extended и dfns
Если мы используем функцию
⎕CY 'dfns'
's'adic
, она реализует нашу биективную нумерацию base-n (которая послужила источником вдохновения для версии, которую я использую) для гораздо меньшего числа байтов. Переключение на Dyalog Extended также экономит большое количество байтов, и вот мы здесь. Большое спасибо Адаму за его помощь в игре в гольф. Предложения по игре в гольф приветствуются!Изменить: -8 байт из-за изменения, как
P
иQ
определены. -14 байт из-за перехода на Dyalog Extended. -2 из-за использования полной программы для удаления скобок dfn{}
. +17 байт из-за исправления проблемы, когда мой алгоритм был некорректным, и большое спасибо ngn за помощь в созданииs[⊃⍋|M-s]
раздела. +1 байт для исправления ошибки. -2 байта, благодаря Адаму за изменение определенияI
и -1 байт за то, что не забыли поставить мои гольфы в обоих решениях. -3 байта благодаря ngn путем перестановки генерации основных направлений, +1 байт из-за исправления глючного гольфа и -3 байта благодаря ngn путем перестановкиt
определения (это больше не отдельная переменная). -7 байт благодаря ngn путем изменения порядкаs
определения.APL (Dyalog Extended) ,
12311510199116117114109102 байтаПопробуйте онлайн!
источник