Рисование треугольника Серпинского было сделано до смерти . Есть и другие интересные вещи, которые мы можем сделать с этим, хотя. Если мы достаточно прищуримся в треугольнике, мы можем рассматривать перевернутые треугольники как узлы фрактального графа. Давайте найдем способ обойти этот график!
Сначала давайте назначим номер каждому узлу. Самый большой перевернутый треугольник будет нулевым узлом, а затем мы просто спустимся слой за слоем (сначала в ширину), назначив последовательные числа в порядке сверху-слева-справа:
Нажмите, чтобы увеличить версию, где маленькие цифры немного менее размыты.
(Конечно, эта модель продолжает до бесконечности внутри синих треугольников.) Еще один способ определить нумерацию, что центральный узел имеет индекс 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