Vẽ đường cong Hilbert


12

Hilbert Curve là một loại đường cong lấp đầy không gian và về cơ bản nó ánh xạ một đường thẳng tới một mặt phẳng. Mỗi điểm trong đường thẳng tương ứng với chỉ một điểm trong mặt phẳng và mỗi điểm trong mặt phẳng tương ứng với chỉ một điểm trên đường thẳng. Hiển thị là các lần lặp từ 0 đến 4 của Đường cong Hilbert:

Lặp lại 0 đến 4:

Mục tiêu của nhiệm vụ này: Viết mã rút ra lần lặp thứ tư của Đường cong Hilbert, như được định nghĩa ở trên. Mã của bạn phải hoàn chỉnh - nói cách khác, nếu bạn tạo một hàm để vẽ Đường cong Hilbert, mã của bạn phải gọi hàm đó. Đầu ra có thể được hiển thị trực tiếp trên màn hình hoặc bạn có thể ghi đầu ra vào một tệp hình ảnh. Đường cong có thể được xoay hoặc lật, nhưng các đường phải giao nhau ở các góc phải và đầu ra không thể được kéo dài. Nghệ thuật ASCII được đánh giá cao nhưng sẽ không được chấp nhận. Mã ngắn nhất trong byte thắng!


Là số lần đầu vào? Hoặc chúng ta có thể chọn bất kỳ giá trị ít nhất 4?
Luis Mendo

Là nghệ thuật ASCII được coi là đồ họa?
Gabriel Benamy

Không; xin lỗi - sau đó nó sẽ là một bản sao của một câu hỏi khác
J. Antonio Perez

@JorgePerez Đường cong có thể có hướng khác không? Giống như một phiên bản lật theo chiều dọc hoặc xoay 90 độ trong các ví dụ của bạn
Luis Mendo

Đúng! Mặc dù hình dạng tổng thể vẫn phải là hình vuông
J. Antonio Perez

Câu trả lời:


7

R, 90 byte

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")

Cổng R không biết xấu hổ của thuật toán được sử dụng trong liên kết được đăng bởi @Luis Mendo.

Đối với n=5chúng tôi nhận được:

nhập mô tả hình ảnh ở đây


7

MATL , 39 38 byte

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

Điều này lấy số lần lặp làm đầu vào. Nếu bạn muốn mã cứng nó, thay thế ibằng số.

Chương trình này là một cổng của mã Matlab của Jonas Lundgren được hiển thị ở đây .

Kết quả sẽ được hiển thị dưới đây. Bạn cũng có thể dùng thử tại MATL Online! Phải mất vài giây để tạo ra đầu ra. Trình biên dịch này là thử nghiệm; bạn có thể cần làm mới trang và nhấn "Chạy" lại nếu nó không hoạt động ban đầu.

nhập mô tả hình ảnh ở đây

Giải trình

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

Bạn có thể giải thích làm thế nào mã của bạn hoạt động?
J. Antonio Perez

Thuật toán chính xác như trong liên kết. Nhưng tôi sẽ thêm một lời giải thích
Luis Mendo

@Jorge Giải thích thêm
Luis Mendo

ồ, cái mà bạn dựa vào của bạn dễ hơn tôi rất nhiều = /
flawr

@flawr Tất cả tín dụng cho Jonas Lundgren :-)
Luis Mendo

6

MATLAB, 264 262 161 byte

Điều này vẫn hoạt động rất giống nhau, ngoại trừ việc chúng ta cơ bản tính toán "đạo hàm" của đường cong hilbert, sau đó chúng ta "tích hợp" thông qua `cumsum``. Điều này làm giảm kích thước mã bằng một loạt các byte.

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

Phiên bản cũ

Đây chỉ là một cách tiếp cận đệ quy đơn giản. Tôi đã sử dụng số phức để lưu trữ thông tin véc tơ cho đơn giản. Bạn có thể thay đổi đường cong ở phần này h(0,1,1+i,4). Đối số thứ nhất p=0là vị trí ban đầu, đối số thứ hai flà cờ cho hướng ( +1hoặc -1), đối số thứ ba dlà hướng / xoay trong đó đường cong sẽ được vẽ và đối số thứ tư llà độ sâu đệ quy.

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

Đây là những gì nó trông giống như trong các phiên bản cũ hơn:

Đây là những gì nó trông giống như trong năm 2015b:

->

1
Trong Matlab R2015b, nó vẽ các màu <3
Luis Mendo

Haha tuyệt quá :)
flawr

@LuisMendo Bây giờ tôi đã có thể chơi golf một chút với cumsumý tưởng thật tuyệt vời!
flawr

3

MATLAB / Octave, 202 byte

Tôi nhận thấy các phiên bản @LuisMendo liên kết là cách ngắn hơn so với trước giải pháp "thủ công" nhưng sử dụng một cách tiếp cận hoàn toàn khác nhau. Tôi đang đăng một phiên bản golf ở đây bây giờ dưới dạng CW:

Phiên bản này dựa trên phương pháp hệ thống Lindenmayer:

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

nhập mô tả hình ảnh ở đây


3

JavaScript (ES6), 266 ... 233 232 byte

Một kết xuất SVG của đường cong Hilbert.

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)+'">')

Đã lưu 1 byte nhờ Neil


1
Hãy thửfill=none
Neil

2

Trăn 3, 177 175 171 byte

Một triển khai đơn giản của hệ thống Lindenmayer cho đường cong Hilbert. Gợi ý chơi golf chào mừng!

Chỉnh sửa: -2 byte nhờ Kade. -3 byte từ cấu trúc lại cách xây dựng đường cong Hilbert. -1 byte nhờ vào 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)

nhập mô tả hình ảnh ở đây

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)

Thay đổi cách bạn hình thành tcó thể lưu hai byte : t+=[[c,"+AF-BFB-FA+"][c=="B"],"-BF+AFA+FB-"][c=="A"]. Vì mô hình gần như giống nhau cho hai người họ, tôi tự hỏi liệu có cách nào để sử dụng nó không ..
Kade

Có lẽ thay đổi if c>"E":để if"E"<c:tiết kiệm một byte?
Sản xuất ETH

1

MSWLogo (Phiên bản 6.5b), 136 byte

Dựa trên chương trình đường cong Hilbert cuối cùng ở đây .

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

Một hàm hđược định nghĩa, trong đó có số lần lặp :n(dựa trên 1), góc :a, độ dài :l. Nó là đệ quy, gọi một lần lặp thấp hơn của chính nó với góc :abị phủ định trong hai trường hợp để có được định hướng chính xác.

  • rt :a, lt :axoay con rùa (hình tam giác có đường đi) bên phải, bên trái theo :ađộ.
  • fd :ldi chuyển rùa về phía trước theo :lcác bước.

Cuối cùng, hàm được gọi là : h 5 90 9. Con rùa có thể được ẩn thêm 2 byte , ht.

(5-1) lần lặp thứ


Điều gì đang xảy ra ở góc trên bên trái?
flawr

@flawr Đó là con rùa. Nó có thể được ẩn bằng cách nối thêm ht.
u54112

1

Toán học 128 byte

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]]

Thay thế 4 ở trên với một số lần lặp khác nhau nếu bạn muốn.

Được thực hiện dưới dạng hệ thống Lindenmayer với các chuỗi số nguyên thay vì chuỗi chuỗi, vì vậy quy tắc sản xuất thứ hai chỉ là phủ định của quy tắc đầu tiên. Phiên bản này là 151 byte.

Cổng mã MATLAB của Jonas Lundgren chỉ có 128 byte.

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]

Tôi thấy rằng trong một phiên bản tương lai của Mathematica, điều này có thể trở nên thực sự ngắn, đại loại như:

Graphics@HilbertCurve[n]

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


1

LindenMASM , 63 byte

Một câu hỏi khác với câu trả lời LindenMASM? Tuyệt vời!

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

Một lần nữa, do một số lỗi vẽ với Python turtle, đôi khi khi bạn chạy nó, toàn bộ bản vẽ không có ở đó. Tuy nhiên, bạn có thể thấy nó thực sự hoạt động:

Lặp lại lần thứ 4

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.