การทอผ้าแบบปะเก็น - วาดปมSierpiński


33

รับจำนวนเต็ม N> = 2 สร้างภาพที่แสดงให้เห็นถึงปมSierpińskiของระดับ N

ตัวอย่างเช่นนี่คือ knots ของระดับ 2, 3, 4 และ 5:

ระดับ 2 ระดับ 3 ระดับ 4 ระดับ 5

คลิกที่ภาพเพื่อดูขนาดเต็ม (ยิ่งระดับยิ่งภาพใหญ่ขึ้น)

สเปค

  1. ปมSierpińskiของระดับ N ถูกวาดโดยใช้จุดยอดของรูปสามเหลี่ยมSierpińskiของระดับ N เป็นจุดนำทาง รูปสามเหลี่ยมSierpińskiของระดับ N คือสามเหลี่ยมสามรูปแบบของSierpińskiของระดับ N-1 ที่จัดเป็นรูปสามเหลี่ยมขนาดใหญ่กว่า สามเหลี่ยมSierpińskiของระดับ 0 เป็นรูปสามเหลี่ยมด้านเท่า
  2. สามเหลี่ยมมุมฉากส่วนประกอบที่เล็กที่สุดมีความยาวด้าน 64 ทำให้สามเหลี่ยม Sierpi knski ซึ่งปมขึ้นอยู่กับความยาวด้านโดยรวมของ 64 * 2 ^ N
  3. ศูนย์กลางของสามเหลี่ยมด้านนอกจะอยู่ที่ตำแหน่งกึ่งกลางของภาพ นี่ไม่ได้ให้พื้นที่สีขาวเท่ากันที่ด้านบนและด้านล่าง
  4. เอาต์พุตเป็นรูปสี่เหลี่ยมจัตุรัสที่มีความยาวด้านเพดาน (64 * 2 ^ N * 2 / ROOT3)ซึ่งเพดาน (x)เป็นceiling(x)จำนวนเต็มเล็กที่สุดที่มากกว่าหรือเท่ากับ x นี่มีขนาดใหญ่พอสำหรับจุดสุดยอดด้านบนของสามเหลี่ยมSierpińskiที่อยู่ภายในรูปภาพเมื่อจุดศูนย์กลางของรูปสามเหลี่ยมอยู่ที่กึ่งกลางของภาพ
  5. เส้นโค้งเดียวจะต้องผ่านและผ่านตัวเองสลับอย่างเคร่งครัด วิธีแก้ปัญหาสามารถเลือกได้ว่าจะต่ำกว่าหรือต่ำกว่านั้น
  6. ภาพตัวอย่างแสดงพื้นหน้าสีดำและพื้นหลังสีขาว คุณสามารถเลือกสีที่แตกต่างได้สองสี อนุญาตให้ลบนามแฝง แต่ไม่จำเป็น
  7. จะต้องไม่มีช่องว่างที่มีเส้นโค้งสองเส้นมาบรรจบกันหรือโค้งที่ผ่านหรือเหนือตัวมันเอง
  8. ผลลัพธ์อาจเป็นไฟล์ภาพรูปแบบแรสเตอร์ใด ๆ หรือไฟล์ภาพรูปแบบเวกเตอร์ใด ๆ ที่มีขนาดการแสดงเริ่มต้นที่ถูกต้อง หากคุณแสดงไปที่หน้าจอโดยตรงต้องอยู่ในรูปแบบที่ช่วยให้การเลื่อนเพื่อดูภาพเต็มเมื่อมีขนาดใหญ่กว่าหน้าจอ

การกำหนดศูนย์กลางส่วนโค้งรัศมีและความหนา

  1. ปมถูกสร้างขึ้นเป็นชุดของส่วนโค้งแบบวงกลมที่พบกัน ณ จุดที่เส้นสัมผัสของมันนั้นขนานกัน ส่วนโค้งเหล่านี้จะแสดงเป็นภาควงแหวน (ส่วนโค้งที่มีความหนา)
  2. ศูนย์กลางของส่วนโค้งเหล่านี้คือจุดยอดของสามเหลี่ยมคว่ำที่เล็กที่สุด จุดสุดยอดแต่ละจุดนั้นเป็นศูนย์กลางของส่วนโค้งเดียว
  3. แต่ละส่วนโค้งมีรัศมี 64 * ROOT3 / 2
  4. ยกเว้นว่าส่วนโค้งของสามเหลี่ยมสามด้านนอกสุด (ที่มุมของสามเหลี่ยมขนาดใหญ่) มีจุดศูนย์กลางซึ่งเป็นจุดกึ่งกลางของจุดยอดทั้งสองที่อยู่ติดกันและมีรัศมีของ 64 * (ROOT3 / 2-1 / 2)
  5. แต่ละอาร์คแสดงด้วยความหนารวม (ความแตกต่างระหว่างรัศมีด้านในและรัศมีด้านนอก) ของ64 * (ROOT3 / 2) / 4และขอบสีดำของแต่ละอันนี้มีความหนาของ64 * (ROOT3 / 2) / 16เส้นโค้งต้องมีเส้นขอบเหล่านี้และไม่ใช่แค่แถบทึบ

หน่วยวัด

  1. ระยะทางทั้งหมดอยู่ในหน่วยพิกเซล (1 คือระยะทางแนวนอนหรือแนวตั้งระหว่าง 2 พิกเซลที่อยู่ติดกัน)
  2. สแควร์รูทของ 3 จะต้องแม่นยำถึง 7 ตัวเลขที่สำคัญ นั่นคือการคำนวณของคุณจะต้องเทียบเท่ากับการใช้ ROOT3 เช่นนั้น1.7320505 <= ROOT3 < 1.7320515

เกณฑ์การให้คะแนน

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


สำหรับผู้ที่สงสัยว่าจะไม่รวม N = 0 และ N = 1 เพราะตรงกับวงกลมและพระฉายาลักษณ์ซึ่งไม่ตรงกับรูปแบบที่ใช้กับ N> = 2 ฉันคาดหวังว่าวิธีการส่วนใหญ่ในการท้าทายนี้จะต้องเพิ่มรหัสกรณีพิเศษสำหรับ 0 และ 1 ดังนั้นฉันจึงตัดสินใจละเว้น


1
มันจะช่วยให้มีแผนภาพเพื่อแสดงตัวเลขทั้งหมดที่เกี่ยวข้อง?
trichoplax

ก่อนที่ฉันจะเล่นคำตอบ / เพิ่มมุมฉันจำเป็นต้องมี 7 ตัวเลขที่สำคัญจริง ๆ สำหรับรายละเอียดเล็ก ๆ เช่นความหนาของเส้นหรือไม่? ความแม่นยำเช่น "ตัวเลขสำคัญ 7 หรือ 1 พิกเซลแล้วแต่ว่าจะใหญ่กว่าใด" ดูจะเหมาะสมกว่า
ระดับแม่น้ำเซนต์

@LevelRiverSt เนื่องจากขนาดของภาพที่ปรับขนาดด้วยอินพุตแม้ตัวเลขที่สำคัญ 7 รายการไม่เพียงพอสำหรับความแม่นยำ 1 พิกเซลสำหรับ N. ที่ใหญ่กว่าฉันได้ตัดสินตัวเลขสำคัญจำนวน 7 รายการหลังจากการสนทนาในการแชทเพื่อให้คำตอบทั้งหมดเป็นแบบเดียวกัน มาตรฐาน.
trichoplax

ใช่มันเป็นสิ่งจำเป็นสำหรับการปรับขนาดของรูปภาพสำหรับตัวเลขที่มีขนาดใหญ่กว่า N. 7 ในรูปภาพขนาด 1000000 x 1000000 ซึ่งตรงกับ 0.1 พิกเซล แต่ด้วยการคำนวณระดับกลางอาจจะแย่กว่านั้น ฉันแค่คิดstroke-width:3.464102และคล้ายกันมากเกินไปถ้าคิดว่าจะได้รับความแม่นยำ 1 พิกเซล ฉันจะไปข้างหน้าและรวมไว้เช่นนั้นแม้ว่าหากเป็นคดี
เลเวลริเวอร์เซนต์

คำตอบ:


27

ทับทิม, 1168 932

แก้ไขข้อผิดพลาดจากเมื่อคืนทำให้การตีกอล์ฟต้องทำมากขึ้นหลังจากการชี้แจง

นี่คือ (ปัจจุบัน) โปรแกรมเต็มรูปแบบที่รับหมายเลขจาก stdin และส่งออกsvgไฟล์ไปยัง stdout ฉันเลือก svg เพราะฉันรู้ว่าเป็นไปได้ที่จะตอบสนองความต้องการทั้งหมดของคำถาม แต่ก็มีปัญหาบางอย่าง โดยเฉพาะ SVG รองรับเฉพาะส่วนโค้งของวงกลมเป็นส่วนหนึ่งของpathวัตถุและไม่ได้กำหนดไว้ในแง่ของศูนย์กลาง แต่เป็นจุดปลายทั้งสอง

รหัส

n=gets.to_i
r=64*w=0.75**0.5
m=1<<n-2
z=128*m/w
a=(s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
")%[0,r-r*m*8/3]+"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"
p=2
m.times{|i|(i*2+1).times{|j|(p>>j)%8%3==2&&a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}
p^=p*4}
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"

เอาท์พุท N = 4

rescaled โดยแลกเปลี่ยนแลกเปลี่ยน ดูดีขึ้นกว่าเดิมมาก

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

ตอนแรกฉันคิดว่าชอบ http://euler.nmt.edu/~jstarret/sierpinski.htmlโดยที่สามเหลี่ยมถูกแบ่งออกเป็นสามเส้นที่มีสีต่างกันซึ่งแต่ละอันจะสร้างเส้นทางจากมุมหนึ่งไปอีกมุมหนึ่ง วงกลมที่ไม่สมบูรณ์จะแสดงเป็นรูปหกเหลี่ยมที่ไม่สมบูรณ์ที่นั่น วงกลมที่ถูกจารึกไว้ในรูปหกเหลี่ยมแสดงให้เห็นว่ารัศมีวงกลมควรเป็นsqrt(3)/2เท่าของความยาว sidelength เกลียวอาจถูกสร้างซ้ำได้ตามที่แสดง แต่มีความซับซ้อนเพิ่มเนื่องจากมุมต้องถูกปัดเศษและเป็นการยากที่จะรู้ว่าทิศทางใดที่จะโค้งดังนั้นฉันไม่ได้ใช้วิธีนี้

สิ่งที่ฉันทำคือต่อไปนี้

ในภาพด้านล่างคุณจะเห็นว่ามีการบิดแนวนอนของ N = 2 หน่วย (เป็นสีเขียว) ที่จัดเรียงเป็นรูปสามเหลี่ยม sierpinski และการบิดเชื่อมโยงเพิ่มเติม (เป็นสีน้ำเงิน)

มันเป็นความรู้ทั่วไปที่ว่าเลขคี่บนสามเหลี่ยมของปาสคาลเป็นรูปสามเหลี่ยม sierpinski รูปสามเหลี่ยม sierpinski ของเลขฐานสองสามารถรับได้ในลักษณะที่คล้ายกันโดยเริ่มต้นด้วยจำนวนp=1และซ้ำแล้วซ้ำอีกด้วยp<<1มันด้วย

ฉันมีการปรับเปลี่ยนวิธีการนี้เริ่มต้นที่p=2และซ้ำ XORing p*4กับ นี่จะให้รูปสามเหลี่ยม sierpinski สลับกับคอลัมน์ของศูนย์

ตอนนี้เราสามารถ rightshift %8พีและตรวจสอบในช่วงสามบิตใช้ หากพวกเขา010เราจำเป็นต้องวาดเกลียวสีเขียวที่เป็นของหน่วย N = 2 หากพวกเขา101เราจำเป็นต้องวาดสีน้ำเงินบิดเป็นเกลียว เพื่อทดสอบตัวเลขทั้งสองนี้ด้วยกันเราจะพบโมดูโล%3และถ้านี่คือ 2 เราต้องวาดการบิด

ในที่สุดเพิ่มเติมจากการบิดแนวนอนเราทำสำเนาสองชุดที่หมุนถึง 120 และ 240 องศาเพื่อวาดเส้นทแยงมุมบิดและทำภาพให้สมบูรณ์ สิ่งที่เหลืออยู่ก็คือการเพิ่มมุม

รหัสแสดงความคิดเห็น

n=gets.to_i

#r=vertical distance between rows 
r=64*w=0.75**0.5

#m=number of rows of horizontal twists
m=1<<n-2

#z=half the size of the viewport
z=128*m/w

#s=SVG common to all paths
s="<path style='fill:none;stroke:black;stroke-width:3.464102' transform='translate(%f %f)'
"

#initialize a with SVG to draw top corner loop. Set k and l to the SVG common to all arcs of 58*w and 70*w radius 
a=s%[0,r-r*m*8/3]+
"d='M18.11943,-2A#{b=r-6*w-32} #{b} 0 0,0 #{-b} 0#{k='A%f %f 0 0 '%([58*w]*2)}0 0,38.71692
M28.58980,1.968882#{l='A%f %f 0 0 '%([70*w]*2)}0 #{c=r+6*w-32} 0A#{c} #{c} 0 0,0 #{-c} 0#{l}0 -9 44.65423'/>"

#p is the pattern variable, top row of twists has one twist so set to binary 00000010
p=2

#loop vertically and horizontally
m.times{|i|
 (i*2+1).times{|j|

   #leftshift p. if 3 digits inspected are 010 or 101 
   (p>>j)%8%3==2&&

   #append to a, the common parts of a path...
   a<<s%[128*(j-i),r*3+r*i*4-r*m*8/3]+

   #...and the SVG for the front strand and left and right parts of the back strand (each strand has 2 borders)
"d='M-55,44.65423#{k}0 11.5,25.11473#{l}1 35.41020,1.968882
M-64,51.48786#{l}0 20.5,30.31089#{k}1 36.82830,13.17993
M-82.17170,-2.408529#{l}1 -11.5,25.11473#{k}0 0,38.71692
M-81.52984 8.35435#{k}1 -20.5,30.31089#{l}0 -9,44.65423
M9,44.65423#{k}0 81.52984,8.35435
M0,51.48786#{l}0 91.17169,13.17993'/>"}

#modify the pattern by xoring with 4 times itself for the next row
p^=p*4}

#output complete SVG of correct size with three copies of the finished pattern rotated through 0,120,240 degrees.
puts "<svg xmlns='http://www.w3.org/2000/svg' viewBox='#{-z} #{-z} #{e=2*z+1} #{e}' width='#{e}px' height='#{e}px'>"+
"<g transform='rotate(%d)'>#{a}</g>"*3%[0,120,240]+"</svg>"

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


ที่คุณพูดว่า "ดูดีกว่าต้นฉบับ" อาจเป็นสิ่งที่ควรค่าแก่การเพิ่ม "(คลิกที่ภาพเพื่อดูขนาดเต็ม)" สำหรับทุกคนที่ไม่ทราบ
trichoplax

@ ตรีโกณมิติมันไม่ได้เกิดขึ้นกับฉันที่จะคลิกที่ภาพ แต่อย่างไรก็ตามนี่คือ PNG เนื่องจากการแลกเปลี่ยนสแต็กไม่ยอมรับรูปภาพ svg ดังนั้นขอบจึงเบลอโดยเจตนา ไฟล์ SVG ในพื้นที่ของฉันมีขอบที่คมกว่าและดูดีกว่ามาก
เลเวลริเวอร์

@trichoplax แก้ไขอย่างรวดเร็วกับขนาดภาพที่ทำ จะตีกอล์ฟเพิ่มอีกวัน
ระดับแม่น้ำเซนต์

1
+1 ยอดเยี่ยม ฉันชอบคำอธิบายโดยละเอียดอย่างยิ่งกับแผนภาพรหัสสี
trichoplax

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