ASCII Hilbert Curve


23

ได้รับจำนวนเต็มnส่งออกnซ้ำ TH ของฮิลแบร์ต Curveใน ASCII โดยใช้ตัวละครและ_|

นี่คือการวนซ้ำ 4 ครั้งแรก:

n=1
 _ 
| |

n=2
 _   _ 
| |_| |
|_   _|
 _| |_

n=3
 _   _   _   _ 
| |_| | | |_| |
|_   _| |_   _|
 _| |_____| |_ 
|  ___   ___  |
|_|  _| |_  |_|
 _  |_   _|  _ 
| |___| |___| |

n=4
 _   _   _   _   _   _   _   _ 
| |_| | | |_| | | |_| | | |_| |
|_   _| |_   _| |_   _| |_   _|
 _| |_____| |_   _| |_____| |_ 
|  ___   ___  | |  ___   ___  |
|_|  _| |_  |_| |_|  _| |_  |_|
 _  |_   _|  _   _  |_   _|  _ 
| |___| |___| |_| |___| |___| |
|_   ___   ___   ___   ___   _|
 _| |_  |_|  _| |_  |_|  _| |_ 
|  _  |  _  |_   _|  _  |  _  |
|_| |_| | |___| |___| | |_| |_|
 _   _  |  ___   ___  |  _   _ 
| |_| | |_|  _| |_  |_| | |_| |
|_   _|  _  |_   _|  _  |_   _|
 _| |___| |___| |___| |___| |_ 

ชี้แจง

  • คำถามของฉันจะคล้ายกับการวาดเส้นโค้งฮิลแบร์ตและวาดเส้นโค้งฮิลแบร์ตโดยใช้เครื่องหมายทับ
  • การแปลงระหว่างขีดล่าง ( _) และแถบแนวตั้ง (| ) คือu=2*v-1ตำแหน่งที่ uมีจำนวนของ_s และvคือจำนวนของ|s
  • เพื่อรักษาความสอดคล้องกับโพสต์ต้นฉบับของฉันเส้นโค้งต้องเริ่มต้นและสิ้นสุดที่ด้านล่าง
  • คุณสามารถมีโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบ
  • ส่งออกไปยัง stdout (หรือสิ่งที่คล้ายกัน)
  • คุณสามารถมีช่องว่างนำหน้าหรือต่อท้ายช่องว่างสีขาวเอาท์พุทก็ต้องเข้าแถวเพื่อให้มันดูเหมือนตัวอย่าง
  • นี่คือ code-golf ดังนั้นคำตอบที่สั้นที่สุดในจำนวนไบต์ชนะ

3
คุณช่วยกรุณารวมคำจำกัดความของ Hilbert Curve ไว้ในโพสต์ของคุณได้ไหมและข้อกำหนดที่แน่นอนสำหรับวิธีการสร้างเวอร์ชั่น ASCII?
Loovjo

@Bobas_Pett: ไม่ใช่kolmogorov-complex
shooqie


@ Loovjo ฉันเพิ่มในจุดที่เกี่ยวกับความยาวของขีดล่าง (_) และแถบแนวตั้ง (|) ภายใต้ "ชี้แจง" หากยังต้องการข้อมูลเพิ่มเติมหรือคำจำกัดความที่เข้มงวดโปรดบอกฉัน
Bobas_Pett

@shooqie ฉันลบแท็ก
Bobas_Pett

คำตอบ:


5

Befunge, 444 368 323 bytes

&1>\1-:v
0v^*2\<_$00p>
_>:10p\:20pv^_@#-*2g00:+1,+55$
^!-<v*2g000<>$#<0>>-\:v
g2*^>>10g20g+v \ ^*84g_$:88+g,89+g,\1+:00
v#*!-1g02!g01_4^2_
>::00g2*-!\1-:10g-\20g-++>v
87+#^\#p01#<<v!`g01/2\+76:_
vv1-^#1-g01:\_$:2/20g`!
_ 2/^>:10g#vv#`g02/4*3:\+77
v>0p^^/2:/2_
<^2-1-g02</2`#*3:
0g+10p2*:^*3_1
! "#%$
%$"#!
 !!##%
|||_
 _ __

ลองออนไลน์!

วิธีการทั่วไปในการวาด Hilbert Curve คือการทำตามเส้นทางเป็นชุดของสโตรกและเทิร์นการเรนเดอร์ผลลัพธ์ลงในบิตแมปหรือพื้นที่หน่วยความจำบางส่วนแล้วเขียนเรนเดอร์นั้นเมื่อเส้นทางเสร็จสมบูรณ์ นี่เป็นไปไม่ได้ใน Befunge เมื่อเรามีหน่วยความจำ 2,000 ไบต์เท่านั้นที่ใช้งานได้และนั่นรวมถึงแหล่งที่มาของโปรแกรมด้วย

ดังนั้นวิธีที่เราทำในที่นี้คือสูตรที่บอกเราว่าตัวอักษรที่จะส่งออกสำหรับพิกัด x, y ที่กำหนด เพื่อให้เข้าใจถึงวิธีการทำงานนี้ก็ง่ายที่สุดที่จะไม่สนใจการแสดงผล ASCII ที่จะเริ่มต้นด้วยและเพียงแค่คิดว่าของเส้นโค้งเป็นที่สร้างขึ้นจากตัวละครกล่อง: , , , , และ

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

ระดับ 3 Hilbert Curve แสดงการสะท้อนข้ามแกนตั้ง

จากนั้นดูที่มุมล่างซ้ายอีกครั้งเราจะเห็นได้ว่าครึ่งล่างเป็นภาพสะท้อนของครึ่งบน ดังนั้นตัวละครที่อยู่ด้านล่างจะถูกกำหนดโดยเพียงแค่มองหาคู่ของพวกเขาด้านบนและสะท้อนให้เห็นในแนวตั้ง (เช่นเกิดขึ้นและมีการแลกเปลี่ยนเป็นและ)

ระดับ 3 Hilbert Curve แสดงการสะท้อนข้ามแกนนอนที่มุมล่างซ้าย

ครึ่งที่เหลือของมุมนี้ไม่ค่อยชัดเจนนัก บล็อกด้านขวาสามารถได้มาจากการสะท้อนแนวตั้งของบล็อกที่อยู่ติดกันในแนวทแยงมุม

ระดับ 3 Hilbert Curve แสดงให้เห็นว่าจะได้รับบล็อกมุมบนขวาของมุมซ้ายล่างได้อย่างไร

และบล็อกมือซ้ายสามารถได้มาจากการสะท้อนแนวตั้งของบล็อกในมุมบนซ้ายของเส้นโค้งเต็ม

ระดับ 3 Hilbert Curve แสดงให้เห็นว่าจะได้บล็อกมุมบนซ้ายของมุมซ้ายล่างได้อย่างไร

ณ จุดนี้สิ่งที่เราเหลือไว้คือมุมบนซ้ายซึ่งเป็นอีกมุมหนึ่งของฮิลแบร์ตเคอร์ที่ต่ำลงหนึ่งรอบ ในทางทฤษฎีตอนนี้เราควรจะต้องทำซ้ำขั้นตอนอีกครั้ง แต่มีการจับ - ในระดับนี้ครึ่งซ้ายและขวาของบล็อกไม่ได้สะท้อนแน่นอนของกันและกัน

ดังนั้นในสิ่งอื่นที่ไม่ใช่ระดับบนสุดที่ตัวละครที่มุมด้านล่างต้องมีการจัดการเป็นกรณีพิเศษที่ตัวละครจะสะท้อนให้เห็นเป็นและตัวละครที่สะท้อนให้เห็นเป็น

ระดับ 3 Hilbert Curve แสดงให้เห็นว่าจะได้บล็อกมุมบนซ้ายของมุมซ้ายล่างได้อย่างไร

แต่นอกเหนือจากนั้นเราสามารถทำซ้ำกระบวนการนี้ซ้ำ ๆ ได้ ในระดับสุดท้ายที่เรา hardcode ด้านบนซ้ายเป็นตัวและตัวอักษรด้านล่างเป็น

ลำดับของภาพที่แสดงให้เห็นว่าส่วนต่าง ๆ ของเส้นโค้งได้รับมาอย่างไร

ตอนนี้เรามีวิธีกำหนดรูปร่างของเส้นโค้งที่พิกัด x, y เฉพาะแล้วเราจะแปลสิ่งนั้นเป็นการเรนเดอร์ ASCII ได้อย่างไร? จริงๆแล้วมันเป็นเพียงการทำแผนที่อย่างง่าย ๆ ที่แปลไทล์แต่ละอันที่เป็นไปได้ให้เป็นอักขระ ASCII สองตัว

  • กลายเป็น _(ช่องว่างบวกขีดล่าง)
  • กลายเป็น  (สองช่องว่าง)
  • กลายเป็น|_(แถบแนวตั้งบวกขีดล่าง)
  • กลายเป็น(แถบแนวตั้งบวกพื้นที่)
  • จะกลายเป็น(อีกครั้งแถบแนวตั้งพร้อมพื้นที่)
  • กลายเป็น__(ขีดล่างสองอัน)

การทำแผนที่นี้ไม่ง่ายในตอนแรก แต่คุณสามารถดูวิธีการทำงานเมื่อดูการเรนเดอร์ที่เกี่ยวข้องกันสองแบบ

Hilbert Curve ระดับ 2 แสดงผลเป็นศิลปะ ASCII และมีตัวละครแบบกล่อง

และนั่นคือทั้งหมดที่มีให้ การใช้อัลกอริทึมนี้ใน Befunge จริง ๆ แล้วเป็นปัญหาอีกอย่างหนึ่งโดยสิ้นเชิง แต่ฉันจะทิ้งคำอธิบายไว้อีกครั้ง


2

C, 267 ไบต์

const n=4,s=1<<n,a[]={1,-s,-1,s};l,p,q;
t(d){d&=3;p-q||printf("%.2s",&"__|      _|       |___ _|_| | | "[l*8+d*2]);p+=a[l=d];}
h(d,r,n){n--&&(h(d+r,-r,n),t(d+r),h(d,r,n),t(d),h(d,r,n),t(d-r),h(d-r,-r,n));}
main(){for(;p=s*s-s,l=1,q<s*s;++q%s||putchar(10))h(0,1,n),t(3);}

ลองออนไลน์!

h()ใช้การเรียกซ้ำเพื่อสร้างเส้นโค้งของ hlibert t()พิมพ์ตัวอักษรเดียวที่ออกจังหวะถ้าตำแหน่งปากกาเท่ากับตำแหน่งปัจจุบันการส่งออกpq

สิ่งนี้ไม่มีประสิทธิภาพ แต่ง่าย

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