Нарисуйте кривую Гильберта


12

Кривая Гильберта - это тип кривой заполнения пространства, и она в основном отображает линию на плоскость. Каждая точка на линии соответствует только одной точке на плоскости, а каждая точка на плоскости соответствует только одной точке на линии. Показаны итерации с 0 по 4 кривой Гильберта:

Итерации от 0 до 4:

Цель этой задачи: написать код, который рисует четвертую итерацию кривой Гильберта, как определено выше. Ваш код должен быть полным - другими словами, если вы создаете функцию для рисования кривой Гильберта, ваш код должен вызывать эту функцию. Вывод может быть либо отображен непосредственно на экране, либо вы можете записать вывод в файл изображения. Кривая может быть повернута или перевернута, но линии должны пересекаться под прямым углом, и выход не может быть растянут. Искусство ASCII ценится, но не будет принято. Самый короткий код в байтах побеждает!


Сколько раз вход? Или мы можем выбрать любое значение по крайней мере 4?
— Луис Мендо

Искусство ASCII считается графическим?
— Габриэль Бенами

Нет; извините - тогда это будет дубликат другого вопроса
— Х. Антонио Перес

@JorgePerez Может ли кривая иметь другую ориентацию? Как версия ваших примеров, развернутая вертикально или на 90 градусов
— Луис Мендо

Да! Хотя общая форма все еще должна быть квадратной
— Х. Антонио Перес

Ответы:


7

R, 90 байт

n=scan();a=1+1i;b=1-1i;z=0;for(k in 1:n)z=c((w<-1i*Conj(z))-a,z-b,z+a,b-w)/2;plot(z,t="s")

Бесстыдный R-порт алгоритма, используемый в ссылке, размещенной @Luis Mendo.

Ибо n=5мы получаем:

введите описание изображения здесь


7

MATL , 39 38 байт

O5:"tZjJ*JQ-wJq+t2+&y2j+_v2/]XG25Y01ZG

Это принимает количество итераций в качестве входных данных. Если вы хотите жестко закодировать его, замените iего на номер.

Программа является портом кода Matlab от Jonas Lundgren, показанного здесь .

Результат показан ниже. Вы также можете попробовать это в MATL Online! Требуется пара секунд, чтобы произвести вывод. Этот компилятор является экспериментальным; вам может понадобиться обновить страницу и снова нажать «Выполнить», если она изначально не работает.

введите описание изображения здесь

объяснение

O          % Push 0. This is the initial value of "z" in the original code
5:"        % Do 5 times
  t        %   Duplicate
  Zj       %   Complex conjugate
  J*       %   Multiply by 1j (imaginary unit). This is "w" in the original code
  JQ-      %   Subtract 1+1j
  w        %   Swap: brings copy of "z" to top
  Jq+      %   Add 1-1j
  t        %   Duplicate
  2+       %   Add 2
  &y       %   Duplicate the third element from top
  2j+_     %   Add 2j and negate
  v        %   Concatenate the three matrices vertically
  2/       %   Divide by 2
]          % End
XG         % Plot (in complex plane). The numbers are joined by straight lines
25Y0       % Push string 'square'
1ZG        % Make axis square

Не могли бы вы объяснить, как работает ваш код?
— Х. Антонио Перес

Алгоритм в точности как в ссылке. Но я добавлю объяснение
— Луис Мендо

Добавлено @Jorge Объяснение
— Луис Мендо

о боже, тот, на котором ты основал свой, намного проще моего = /
— flawr

@flawr Вся заслуга Джонаса Лундгрена :-)
— Луис Мендо

6

MATLAB, 264 262 161 байт

Это работает во многом так же, за исключением того, что мы в основном вычисляем «производную» кривой Гильберта, которую мы затем «интегрируем» через «cumsum». Это уменьшает размер кода на кучу байтов.

function c;plot(cumsum([0,h(1,1+i,4)]));axis equal;end function v=h(f,d,l);v=d*[i*f,1,-i*f];if l;l=l-1;D=i*d*f;w=h(f,d,l);x=h(-f,D,l);v=[x,D,w,d,w,-D,-x];end;end

Старая версия

Это просто рекурсивный подход. Я использовал комплексные числа для хранения векторной информации для простоты. Вы можете изменить кривую на детали h(0,1,1+i,4). Первый аргумент p=0- это начальная позиция, второй аргумент f- это флаг ориентации ( +1или -1), третий аргумент d- это направление / вращение, в котором должна быть нарисована кривая, а четвертый l- глубина рекурсии.

function c;hold on;h(0,1,1+i,4);axis equal;end function p=h(p,f,d,l);q=@plot;if l;l=l-1;d=i*d*f;p=h(p,-f,d,l);q(p+[0,d]);p=p+d;d=-i*d*f;p=h(p,f,d,l);q(p+[0,d]);p=p+d;p=h(p,f,d,l);d=-i*d*f;q(p+[0,d]);p=p+d;p=h(p,-f,d,l);else;q(p + d*[0,i*f,1+i*f,1]);p=p+d;end;end

Вот как это выглядит в старых версиях:

Вот как это выглядит в 2015b:

->


Ха-ха, круто :)
— flawr

@ LuisMendo Теперь я смог немного поиграть в гольф с cumsumидеей, которая просто великолепна!
— flawr

3

MATLAB / Octave, 202 байта

Я заметил, что версия @LuisMendo, связанная с ней , была намного короче, чем предыдущее решение "ручной работы", но использует совершенно другой подход. Я выкладываю здесь версию для гольфа как CW:

Эта версия основана на системном подходе Линденмайера:

A=zeros(0,2);B=A;C=A;D=A;n=[0,1];e=[1,0];for k=1:4;a=[B;n;A;e;A;-n;C];b=[A;e;B;n;B;-e;D];c=[D;-e;C;-n;C;e;A];D=[C;-n;D;-e;D;n;B];A=a;B=b;C=c;end;A=[0,0;cumsum(A)];plot(A(:,1),A(:,2));axis off;axis equal

введите описание изображения здесь


3

JavaScript (ES6), 266 ... 233 232 байта

SVG-рендеринг кривой Гильберта.

document.write('<svg><path fill=none stroke=red d="M8 8'+(f=(i,s='2',d=x=y=8)=>i?f(i-1,s.replace(/./g,c=>[32410401423,,10432423401][+c]||c)):s.replace(/./g,c=>c-4?(d+=c&1&&c-2,''):`L${x+=4-'4840'[d&=3]} ${y+=4-'0484'[d]}`))(5)+'">')

Сохранено 1 байт благодаря Нейлу


1
Попробуйтеfill=none
— Нил

2

Python 3, 177 175 171 байт

Простая реализация системы Линденмайера для кривой Гильберта. Предложения по игре в гольф приветствуются!

Редактировать: -2 байта благодаря Kade. -3 байта от перестройки построения кривой Гильберта. -1 байт благодаря ETHproductions.

from turtle import*;s="a";exec('t=""\nfor c in s:t+=c>"F"and"+-abFF-+baFFba-+FFab+-"[c<"b"::2]or c\ns=t;'*5)
for c in s:
 if"-">c:rt(90)
 elif"F">c:lt(90)
 elif"a">c:fd(9)

введите описание изображения здесь

Ungolfing

import turtle

hilbert_seq = "a"

for _ in range(5):
    new_seq = ""
    for char in hilbert_seq:
        if char == "a":
            new_seq += "-bF+aFa+Fb-"
        elif char == "b":
            new_seq += "+aF-bFb-Fa+"
        else:
            new_seq += char
    hilbert_seq = new_seq

for char in hilbert_seq:
    if char == "F":
        turtle.forward(9)
    elif char == "+":
        turtle.right(90)
    elif char == "-":
        turtle.left(90)

Изменение , как вы формируете tможет сохранить два байта: t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Поскольку модель для них двоих почти одинакова, мне интересно, есть ли способ использовать это ..
— Kade

Возможно изменить, if c>"E":чтобы if"E"<c:сохранить байт?
— ETHproductions

1

MSWLogo (версия 6.5b), 136 байт

На основании окончательной программы кривой Гильберта здесь .

to h :n :a :l
if :n=0[stop]
rt :a
h :n-1(-:a):l
fd :l
lt :a
h :n-1 :a :l
fd :l
h :n-1 :a :l
lt :a
fd :l
h :n-1(-:a):l
rt :a
end
h 5 90 9

hОпределяется функция , которая принимает количество итераций :n( начиная с 1), угол :a, длину :l. Это рекурсивно, вызывая более низкую итерацию с углом :aв двух случаях, чтобы получить правильную ориентацию.

  • rt :a, lt :aповерните черепаху (треугольник, чей путь прослежен) вправо, влево на :aградусы.
  • fd :lдвигает черепаху вперед по :lшагам.

Наконец, функция называется: h 5 90 9. Черепаха может быть скрыта за дополнительные 2 байта ht.

(5-1) -я итерация


Что происходит в левом верхнем углу?
— Flawr

@flawr Это черепаха. Это может быть скрыто путем добавления ht.
— для Моники

1

Mathematica 128 байт

Graphics[Line@AnglePath[Total/@Split[Cases[Nest[#/.{-2->(s=##&@@#&)[l={-1,2,0,1,-2,0,-2,1,0,2,-1}],2->s@-l}&,{-2},4],-1|1|0],#!=0&][[;;-2,;;-2]]*Pi/2]]

Замените 4 выше с другим количеством итераций, если хотите.

Выполнено как система Линденмайера с целочисленными последовательностями, а не с последовательностями строк, поэтому второе производственное правило является просто отрицательным по отношению к первому правилу. Эта версия составляет 151 байт.

Порт кода MATLAB Джонаса Лундгрена составляет всего 128 байт.

z=0;Graphics[Line[{Re[#],Im[#]}&/@Flatten[Table[w=I*Conjugate[z];z={w-(a=1+I),z-(b=1-I),z+a,b-w}/2,{k,5}][[5]]]],AspectRatio->1]

Я вижу, что в будущей версии Mathematica это может стать очень коротким, что-то вроде:

Graphics@HilbertCurve[n]

http://mathworld.wolfram.com/HilbertCurve.html


1

LindenMASM , 63 байта

Еще один вопрос с ответом LindenMASM? Потрясающие!

STT
AXI A
INC 5
SET F 0
RPL A -BF+AFA+FB-
RPL B +AF-BFB-FA+
END

Еще раз, из-за некоторых ошибок рисования в Python turtle, иногда, когда вы запускаете это, весь рисунок не появляется. Однако вы можете видеть, что это действительно работает:

4-я итерация

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.