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


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на номер.

Програма - порт коду Матлаба Джонаса Лундгрена, показаний тут .

Результат показаний нижче. Ви також можете спробувати його на 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 Додано пояснення
Луїс Мендо

omg, той, на якому ви базувались, набагато простіше, ніж мій = /
недолік

@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:

->

1
У Matlab R2015b він планує кольори <3
Луїс Мендо

Ха-ха так круто :)
недолік

@LuisMendo Я тепер міг трохи пограти в гольф з cumsumідеєю, яка просто геніальна!
недолік

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

Пітон 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"]. Оскільки шаблон майже однаковий для двох із них, мені цікаво, чи є якийсь спосіб це використати ..
Каде

Можливо, змінити, 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

Математика 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's turtle, іноді, коли ви запускаєте це, цілого малюнка немає. Однак ви можете бачити, що це справді працює:

4-а ітерація

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.