Дано целое число n
выходных n
итераций кривой Гильберта в ASCII с использованием символов _
и |
.
Вот первые 4 итерации:
n=1
_
| |
n=2
_ _
| |_| |
|_ _|
_| |_
n=3
_ _ _ _
| |_| | | |_| |
|_ _| |_ _|
_| |_____| |_
| ___ ___ |
|_| _| |_ |_|
_ |_ _| _
| |___| |___| |
n=4
_ _ _ _ _ _ _ _
| |_| | | |_| | | |_| | | |_| |
|_ _| |_ _| |_ _| |_ _|
_| |_____| |_ _| |_____| |_
| ___ ___ | | ___ ___ |
|_| _| |_ |_| |_| _| |_ |_|
_ |_ _| _ _ |_ _| _
| |___| |___| |_| |___| |___| |
|_ ___ ___ ___ ___ _|
_| |_ |_| _| |_ |_| _| |_
| _ | _ |_ _| _ | _ |
|_| |_| | |___| |___| | |_| |_|
_ _ | ___ ___ | _ _
| |_| | |_| _| |_ |_| | |_| |
|_ _| _ |_ _| _ |_ _|
_| |___| |___| |___| |___| |_
Разъяснения
- Мой вопрос похож на Рисование кривой Гильберта и Рисование кривой Гильберта с помощью косой черты .
- Преобразование между подчеркиванием (
_
) и вертикальной чертой (|
) - этоu=2*v-1
гдеu
число_
s иv
число|
s. - Чтобы сохранить соответствие с моим исходным постом, кривая должна начинаться и заканчиваться внизу.
- Вы можете иметь полную программу или функцию.
- Вывод на стандартный вывод (или что-то подобное).
- Вы можете иметь начальные или конечные пробелы, выходные данные просто должны выстроиться так, чтобы они выглядели как примеры.
- Это код-гольф, поэтому выигрывает самый короткий ответ в байтах.
Ответы:
Befunge,
444368323 байтаПопробуйте онлайн!
Типичный подход к построению кривой Гильберта состоит в том, чтобы следовать по пути в виде последовательности штрихов и поворотов, визуализировать результат в растровое изображение или некоторую область памяти, а затем записывать этот рендеринг после завершения пути. Это просто невозможно в Befunge, когда у нас есть только 2000 байтов памяти для работы, и это включает в себя источник самой программы.
Таким образом, подход, который мы здесь использовали, заключается в том, чтобы придумать формулу, которая точно сообщает нам, какой символ вывести для данной координаты x, y. Чтобы понять , как это работает, это проще всего игнорировать ASCII рендеринга , чтобы начать с, и просто думать о кривой , как из коробки символов:
┌
,┐
,└
,┘
,│
, и─
.Когда мы смотрим на кривую таким образом, мы сразу видим, что правая сторона является точным зеркалом левой стороны. Символы справа можно просто определить, посмотрев на их партнера слева и отразив его горизонтально (т. Е. Вхождения
┌
и┐
поменялись местами, как есть└
и┘
).Затем, глядя в левый нижний угол, мы снова видим, что нижняя половина является отражением верхней. Таким образом, символы внизу просто определяются путем поиска их партнера сверху и их отражения по вертикали (т. Е. Случаи
┌
и└
меняются местами, как┐
и┘
).Оставшаяся половина этого угла чуть менее очевидна. Правый блок может быть получен из вертикального отражения блока, диагонально смежного с ним.
И левый блок может быть получен из вертикального отражения блока в самом верхнем левом углу полной кривой.
На данный момент все, что у нас осталось, это верхний левый угол, который является еще одной кривой Гильберта на одну итерацию ниже. Теоретически, теперь нам просто нужно повторить процесс снова, но есть некоторая хитрость - на этом уровне левая и правая половины блока не являются точными зеркалами друг друга.
Таким образом, на любом другом уровне, кроме верхнего уровня, символы нижнего угла должны обрабатываться как особый случай, когда
┌
символ отображается как─
, а│
символ - как└
.Но кроме этого, мы действительно можем просто повторить этот процесс рекурсивно. На последнем уровне мы жестко кодируем верхний левый символ как
┌
, а символ под ним как│
.Теперь, когда у нас есть способ определить форму кривой по определенной координате x, y, как мы можем перевести это в рендеринг ASCII? На самом деле это просто простое отображение, которое переводит каждую возможную плитку в два символа ASCII.
┌
становится_
(пробел плюс подчеркивание)┐
становится└
становится|_
(вертикальная черта плюс подчеркивание)┘
становится|
(вертикальная черта плюс пробел)│
становится|
(снова вертикальная черта плюс пробел)─
становится__
(два подчеркивания)Поначалу это отображение не является интуитивно понятным, но вы можете увидеть, как оно работает, если посмотреть на два соответствующих рендеринга рядом.
И это в основном все, что нужно сделать. Фактически реализация этого алгоритма в Befunge - это еще одна проблема, но я оставлю это объяснение в другой раз.
источник
C 267 байт
Попробуйте онлайн!
h()
использует рекурсию для генерации штрихов кривой Глиберта.t()
Печатает символ обводки, только если позиция пераp
равна текущей позиции выводаq
.Это неэффективно, но просто.
Если кривая начинается в верхнем левом углу, код может быть уменьшен до 256 байтов.
источник
puts("")
вместоputchar(10)
и"..."+l*8+d*2
вместо&"..."[l*8+d*2]
иn--?h(d+r...-r,n):0
вместоn--&&(h(d+r...-r,n))