Gasket Dệt - vẽ một nút Sierpiński


33

Cho số nguyên N> = 2, tạo ra hình ảnh hiển thị nút Sierpiński độ N.

Ví dụ: đây là các nút độ 2, 3, 4 và 5:

Bằng 2 Bằng 3 Bằng 4 Bằng 5

Nhấp vào hình ảnh để xem kích thước đầy đủ (độ càng cao thì hình ảnh càng lớn).

Đặc điểm kỹ thuật

  1. Một nút Sierpiński có độ N được vẽ bằng cách sử dụng các đỉnh của tam giác Sierpiński độ N làm điểm hướng dẫn. Một tam giác Sierpiński có độ N là ba tam giác Sierpiński bậc N-1 được sắp xếp thành một tam giác lớn hơn. Một tam giác Sierpiński có độ 0 là một tam giác đều.
  2. Các tam giác thành phần nhỏ nhất có chiều dài cạnh 64, tạo ra tam giác Sierpiński mà nút được dựa trên chiều dài tổng thể của 64 * 2 ^ N
  3. Tâm của tam giác ngoài được định vị ở tâm ảnh. Điều này không cho khoảng trắng bằng nhau ở trên và dưới.
  4. Kết quả là một hình ảnh vuông có độ dài cạnh trần (64 * 2 ^ N * 2 / ROOT3)nơi trần (x)ceiling(x), càng lớn số nguyên nhỏ nhất hơn hoặc bằng x. Giá trị này chỉ đủ lớn để đỉnh trên cùng của tam giác Sierpiński nằm bên dưới hình ảnh khi tâm của tam giác nằm ở trung tâm của hình ảnh.
  5. Các đường cong duy nhất phải vượt qua và dưới chính nó, xen kẽ nghiêm ngặt. Các giải pháp có thể chọn giữa dưới rồi hơn, hoặc sau đó dưới.
  6. Các hình ảnh ví dụ cho thấy nền trước và nền trắng. Bạn có thể chọn bất kỳ hai màu dễ dàng phân biệt. Khử răng cưa được cho phép nhưng không cần thiết.
  7. Không được có những khoảng trống nơi hai cung gặp nhau hoặc nơi đường cong đi qua hoặc bên dưới chính nó.
  8. Đầu ra có thể là bất kỳ tệp hình ảnh định dạng raster hoặc bất kỳ tệp hình ảnh định dạng vector nào có kích thước hiển thị mặc định chính xác. Nếu bạn hiển thị trực tiếp lên màn hình, thì đây phải ở dạng cho phép cuộn để xem hình ảnh đầy đủ khi lớn hơn màn hình.

Xác định tâm vòng cung, bán kính và độ dày

  1. Nút được xây dựng như một chuỗi các cung tròn gặp nhau tại các điểm mà tiếp tuyến của chúng song song, để tạo ra một liên kết liền mạch. Các cung này được hiển thị dưới dạng các hình khuyên (hình cung có độ dày).
  2. Tâm của các cung này là các đỉnh của các tam giác lộn ngược nhỏ nhất. Mỗi đỉnh như vậy là trung tâm của chính xác một cung.
  3. Mỗi cung có bán kính là 64 * ROOT3 / 2
  4. Ngoại lệ là các cung trong ba hình tam giác ngoài cùng (ở các góc của tam giác lớn) có tâm là trung điểm của hai đỉnh bên trong liền kề và do đó có bán kính là 64 * (ROOT3 / 2-1 / 2)
  5. Mỗi cung được biểu thị với tổng độ dày (chênh lệch giữa bán kính trong và bán kính ngoài) 64 * (ROOT3 / 2) / 4và các viền đen của mỗi cung có độ dày 64 * (ROOT3 / 2) / 16Đường cong phải có các đường viền này, và không chỉ là một dải liền.

Đơn vị đo lường

  1. Tất cả các khoảng cách đều tính bằng pixel (1 là khoảng cách ngang hoặc dọc giữa 2 pixel liền kề).
  2. Căn bậc 3 của 3 phải chính xác đến 7 số liệu có ý nghĩa. Nghĩa là, tính toán của bạn phải tương đương với việc sử dụng ROOT3 sao cho1.7320505 <= ROOT3 < 1.7320515

Chấm điểm

Mã ngắn nhất tính bằng byte thắng.


Đối với những người thắc mắc, N = 0 và N = 1 không được bao gồm bởi vì chúng tương ứng với một vòng tròn và một trục chính, không hoàn toàn khớp với mẫu áp dụng cho N> = 2. Tôi hy vọng rằng hầu hết các cách tiếp cận cho thử thách này sẽ cần thêm mã trường hợp đặc biệt cho 0 và 1, vì vậy tôi quyết định bỏ qua chúng.


1
Nó sẽ giúp có một sơ đồ để hiển thị những gì tất cả các số liên quan đến?
trichoplax

Trước khi tôi đánh golf câu trả lời / thêm góc của mình, có 7 con số đáng kể thực sự cần thiết cho các chi tiết nhỏ như độ dày của đường, v.v? Độ chính xác như "7 con số đáng kể hoặc 1 pixel, tùy theo giá trị nào lớn hơn" có vẻ phù hợp hơn.
Cấp sông St

@LevelRiverSt vì kích thước của tỷ lệ hình ảnh với đầu vào, thậm chí 7 con số quan trọng là không đủ cho độ chính xác 1 pixel cho lớn hơn. Tôi đã giải quyết 7 con số quan trọng sau khi thảo luận trong trò chuyện, để tất cả các câu trả lời được giữ nguyên Tiêu chuẩn.
trichoplax

Có, cần phải điều chỉnh tỷ lệ của hình ảnh cho các số liệu có ý nghĩa lớn hơn của N. 7 trên hình ảnh 1000000 x 1000000 tương ứng với 0,1 pixel, nhưng với các tính toán trung gian, nó có thể tệ hơn thế. Tôi chỉ nghĩ stroke-width:3.464102và tương tự là một chút quá mức nếu ý tưởng là để có được độ chính xác 1 pixel. Tôi sẽ đi trước và bao gồm nó như thế, mặc dù, nếu đó là phán quyết.
Cấp sông St

Câu trả lời:


27

Ruby, 1168 932

Sửa một lỗi từ tối qua, chơi golf nhiều hơn sau khi làm rõ.

Đây là (hiện tại) một chương trình đầy đủ chấp nhận một số từ stdin và xuất một svgtệp thành thiết bị xuất chuẩn. Tôi đã chọn svg vì tôi biết có thể đáp ứng tất cả các yêu cầu của câu hỏi, nhưng nó có một số vấn đề. đặc biệt là SVG chỉ hỗ trợ các vòng tròn như một phần của pathđối tượng và không định nghĩa chúng theo trung tâm của chúng mà là hai điểm cuối.

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

Đầu ra N = 4

thay đổi kích thước bằng cách trao đổi Stack. Có vẻ tốt hơn nhiều so với ban đầu.

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

Lúc đầu, tôi đã xem xét một cái gì đó như http://euler.nmt.edu/~jstarret/sierpinski.html trong đó tam giác được chia thành ba dải màu khác nhau, mỗi chuỗi tạo thành một đường dẫn từ góc này sang góc khác. Các vòng tròn không đầy đủ được hiển thị dưới dạng hình lục giác không hoàn chỉnh ở đó. ghi các vòng tròn bên trong các hình lục giác cho thấy bán kính vòng tròn phải sqrt(3)/2gấp đôi chiều dài. Các sợi có thể được xây dựng đệ quy như được hiển thị, nhưng có một sự phức tạp thêm bởi vì các góc cần được làm tròn và rất khó để biết hướng nào để cong, vì vậy tôi đã không sử dụng phương pháp này.

Những gì tôi đã làm là sau đây.

Trong hình ảnh bên dưới, bạn có thể thấy có các vòng xoắn ngang thuộc đơn vị N = 2 (màu xanh lá cây) được sắp xếp theo hình tam giác sierpinki và các vòng xoắn cầu nối bổ sung (màu xanh lam.)

Một kiến ​​thức phổ biến là các số lẻ trên tam giác của Pascal tạo thành một tam giác sierpinki. Một tam giác sierpinki có các chữ số nhị phân có thể thu được theo cách tương tự bằng cách bắt đầu với số p=1và lặp đi lặp lại với nó p<<1.

Tôi đã sửa đổi cách tiếp cận này, bắt đầu từ p=2và lặp đi lặp lại với p*4. Điều này cho ra một tam giác sierpinki xen kẽ với các cột số không.

Bây giờ chúng ta có thể quyền p và kiểm tra ba bit cuối bằng cách sử dụng %8. Nếu chúng là 010chúng ta cần vẽ một vòng xoắn màu xanh lá cây thuộc về một đơn vị N = 2. nếu chúng là 101chúng ta cần vẽ một vòng xoắn màu xanh, bắc cầu. Để kiểm tra cả hai số này với nhau, chúng ta tìm modulo %3và nếu đây là 2, chúng ta cần vẽ đường xoắn.

Cuối cùng, ngoài các vòng xoắn ngang, chúng tôi tạo hai bản sao xoay qua 120 và 240 độ để vẽ các đường xoắn chéo và hoàn thành bức tranh. Tất cả những gì còn lại là thêm các góc.

Mã nhận xét

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

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


Nếu bạn nói "Trông tốt hơn nhiều so với bản gốc", có thể đáng để thêm một cái gì đó như "(nhấp vào hình ảnh để xem kích thước đầy đủ)" cho bất cứ ai không nhận ra.
trichoplax

@trichoplax nó đã không xảy ra với tôi để nhấp vào hình ảnh. Nhưng dù sao, đây là một PNG, vì trao đổi ngăn xếp không chấp nhận hình ảnh svg, vì vậy các cạnh bị cố tình làm mờ. Tệp SVG cục bộ của tôi có các cạnh sắc nét hơn nhiều và trông đẹp hơn nhiều.
Cấp sông St

@trichoplax sửa nhanh về kích thước hình ảnh được thực hiện. Sẽ chơi golf thêm một ngày nữa.
Cấp sông St

1
+1 công việc tuyệt vời. Tôi đặc biệt thích phần giải thích chi tiết với sơ đồ mã màu.
trichoplax

1
Các siêu liên kết đã chết.
mbomb007
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.