วาดเส้นโค้งของ Hilbert


12

Hilbert Curve เป็นรูปแบบหนึ่งของการเติมพื้นที่ว่างและโดยทั่วไปแล้วจะจับคู่กับระนาบ แต่ละจุดในเส้นตรงกับจุดเดียวในระนาบและแต่ละจุดในระนาบนั้นตรงกับจุดเดียวบนเส้น มีการทำซ้ำ 0 ถึง 4 ของ Hilbert Curve:

การทำซ้ำ 0 ถึง 4:

วัตถุประสงค์ของงานนี้: เขียนโค้ดที่วาดการวนซ้ำที่สี่ของ Hilbert Curve ตามที่กำหนดไว้ข้างต้น รหัสของคุณควรจะสมบูรณ์ - ในคำอื่น ๆ ถ้าคุณสร้างฟังก์ชั่นเพื่อวาดเส้นโค้ง Hilbert รหัสของคุณจะต้องเรียกใช้ฟังก์ชันนั้น สามารถแสดงเอาต์พุตโดยตรงบนหน้าจอหรือคุณสามารถเขียนเอาต์พุตไปยังไฟล์รูปภาพ เส้นโค้งอาจหมุนหรือพลิกได้ แต่เส้นจะต้องตัดกันที่มุมขวาและไม่สามารถยืดออกได้ ศิลปะ ASCII ได้รับการชื่นชม แต่จะไม่ได้รับการยอมรับ รหัสที่สั้นที่สุดเป็นไบต์ชนะ!


จำนวนครั้งที่อินพุตหรือไม่ หรือเราสามารถเลือกค่าใด ๆ อย่างน้อย 4?
Luis Mendo

ASCII เป็นภาพกราฟิกหรือไม่?
Gabriel Benamy

ไม่มี ขอโทษด้วยซ้ำอีกคำถาม
เจ. อันโตนิโอเปเรซ

@ JorgePerez เส้นโค้งสามารถมีทิศทางที่แตกต่างกันได้หรือไม่? เหมือนตัวอย่างเวอร์ชันของคุณในแนวตั้งที่พลิกกลับหรือ 90 องศา
หลุยส์เมนโดะ

ใช่ แม้ว่ารูปร่างโดยรวมจะต้องเป็นรูปสี่เหลี่ยมจัตุรัส
J. Antonio Perez

คำตอบ:


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

Shameless R-port ของอัลกอริทึมที่ใช้ในลิงค์ที่โพสต์โดย @Luis Mendo

สำหรับn=5เราได้รับ:

ป้อนคำอธิบายรูปภาพที่นี่


7

MATL , 39 38 ไบต์

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

วิธีนี้ใช้จำนวนการวนซ้ำเป็นอินพุต หากคุณต้องการรหัสยากให้แทนที่iด้วยหมายเลข

โปรแกรมนี้เป็นพอร์ตของรหัส Matlab โดย Jonas Lundgren แสดงให้เห็นที่นี่

ผลลัพธ์แสดงไว้ด้านล่าง คุณสามารถลองที่MATL Online! ใช้เวลาสองสามวินาทีในการสร้างเอาต์พุต คอมไพเลอร์นี้กำลังทำการทดลอง คุณอาจต้องรีเฟรชหน้าเว็บและกด "Run" อีกครั้งหากไม่ได้ผลในตอนแรก

ป้อนคำอธิบายรูปภาพที่นี่

คำอธิบาย

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

คุณสามารถอธิบายวิธีการทำงานของรหัสของคุณได้อย่างไร
J. Antonio Perez

อัลกอริทึมตรงตามลิงค์ แต่ฉันจะเพิ่มคำอธิบาย
Luis Mendo

@ คำอธิบาย George เพิ่ม
Luis Mendo


@flawr เครดิตทั้งหมดให้กับ Jonas Lundgren :-)
Luis Mendo

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
Luis Mendo

ฮ่าฮ่าเจ๋งมาก :)
ข้อผิดพลาด

@ LuisMendo ฉันสามารถเล่นกอล์ฟได้แล้วด้วยcumsumความคิดที่ยอดเยี่ยม!
ข้อบกพร่อง

3

MATLAB / Octave, 202 ไบต์

ฉันสังเกตเห็นว่าการเชื่อมโยง @LuisMendo รุ่น นั้นสั้นกว่าโซลูชัน "แฮนด์เมด"ก่อนหน้านี้แต่ใช้วิธีการที่ต่างออกไปโดยสิ้นเชิง ฉันกำลังโพสต์เวอร์ชัน golfed ที่นี่ตอนนี้เป็น CW:

รุ่นนี้เป็นไปตามแนวทางของระบบ 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

ป้อนคำอธิบายรูปภาพที่นี่


3

JavaScript (ES6), 266 ... 233 232 ไบต์

การแสดง SVG ของ Hilbert Curve

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 ไบต์ขอบคุณ Neil


1
ลองfill=none
Neil

2

Python 3, 177 175 171 ไบต์

การใช้งานระบบ Lindenmayer อย่างง่ายสำหรับกราฟโค้งของฮิลแบร์ต ยินดีต้อนรับคำแนะนำการเล่นกอล์ฟ!

แก้ไข: -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-based) มุมความยาว:a :lเป็นการเรียกซ้ำเรียกซ้ำตัวเองต่ำกว่าโดยมีมุมเป็น:aลบในสองกรณีเพื่อให้ได้แนวที่ถูกต้อง

  • rt :a, lt :aหมุนเต่า (thingy สามเหลี่ยมที่มีเส้นทางเป็น traced) ขวา, ซ้ายโดย:aองศา
  • fd :lย้ายเต่าไปข้างหน้าทีละ:lขั้นตอน

ในที่สุดฟังก์ชั่นนี้ถูกเรียกว่า: h 5 90 9. เต่าสามารถซ่อนไว้ได้อีก 2 ไบต์, ht.

(5-1) -th ซ้ำ


เกิดอะไรขึ้นที่มุมซ้ายบน
ข้อบกพร่อง

@ flawr นั่นคือเต่า htมันสามารถซ่อนไว้โดยท้าย
สำหรับโมนิก้า

1

Mathematica 128 Bytes

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 ด้านบนด้วยจำนวนการทำซ้ำที่แตกต่างกันหากคุณต้องการ

เสร็จสิ้นเป็นระบบ Lindenmayer ที่มีลำดับเลขจำนวนเต็มมากกว่าลำดับสตริงดังนั้นกฎการผลิตที่สองเป็นเพียงค่าลบของกฎข้อแรก รุ่นนี้มีขนาด 151 ไบต์

พอร์ตของโค้ด MATLAB ของ Jonas Lundgren นั้นมีขนาด 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.