Tenun Gasket - menggambar simpul Sierpi Sierski


33

Diberikan bilangan bulat N> = 2, menghasilkan gambar yang menunjukkan simpul Sierpiński derajat N.

Sebagai contoh, berikut adalah simpul tingkat 2, 3, 4 dan 5:

Gelar 2 Gelar 3 Gelar 4 Tingkat 5

Klik pada gambar untuk melihat ukuran penuh (semakin tinggi tingkat semakin besar gambar).

Spesifikasi

  1. Simpul Sierpiński derajat N diambil dengan menggunakan simpul segitiga Sierpi Sierski derajat N sebagai titik panduan. Segitiga Sierpiński derajat N adalah tiga segitiga Sierpiński derajat N-1 yang disusun menjadi segitiga yang lebih besar. Segitiga Sierpiński derajat 0 adalah segitiga sama sisi.
  2. Segitiga komponen terkecil memiliki panjang sisi 64, memberikan segitiga Sierpiński di mana simpul didasarkan pada panjang sisi keseluruhan 64 * 2 ^ N
  3. Pusat segitiga luar diposisikan di tengah gambar. Ini tidak memberikan ruang putih yang sama di atas dan bawah.
  4. Outputnya adalah gambar persegi panjang sisi langit-langit (64 * 2 ^ N * 2 / ROOT3)mana langit-langit (x)adalah ceiling(x), integer lebih besar terkecil dari atau sama dengan x. Ini hanya cukup besar untuk puncak atas segitiga Sierpiński yang mendasari untuk terkandung dalam gambar ketika pusat segitiga berada di tengah-tengah gambar.
  5. Kurva tunggal harus melewati dan di bawah dirinya sendiri, secara bergantian. Solusi dapat memilih di bawah di bawah lalu di atas, atau di atas di bawah.
  6. Contoh gambar menunjukkan latar depan hitam dan latar belakang putih. Anda dapat memilih dua warna yang mudah dibedakan. Anti-aliasing diizinkan tetapi tidak perlu.
  7. Tidak boleh ada celah di mana dua busur bertemu atau di mana kurva melewati atau di bawah itu sendiri.
  8. Output dapat berupa file gambar format raster, atau file gambar format vektor apa pun yang menyertakan ukuran tampilan standar yang benar. Jika Anda menampilkan langsung ke layar, ini harus dalam bentuk yang memungkinkan gulir untuk melihat gambar penuh ketika lebih besar dari layar.

Menentukan pusat busur, jari-jari dan ketebalan

  1. Simpul dibangun sebagai serangkaian busur melingkar yang bertemu pada titik-titik di mana garis singgung mereka sejajar, untuk memberikan sambungan yang mulus. Busur ini ditampilkan sebagai sektor berbentuk lingkaran (busur dengan ketebalan).
  2. Pusat-pusat busur ini adalah simpul dari segitiga terbalik terkecil. Setiap simpul tersebut adalah pusat tepat satu busur.
  3. Setiap busur memiliki jari-jari 64 * ROOT3 / 2
  4. Pengecualian adalah bahwa busur dalam tiga segitiga terluar (di sudut-sudut segitiga besar) memiliki pusat yang merupakan titik tengah dari dua simpul dalam yang berdekatan, dan dengan demikian memiliki jari-jari 64 * (ROOT3 / 2-1 / 2)
  5. Setiap busur diwakili dengan ketebalan total (perbedaan antara jari-jari dalam dan jari-jari luar) dari 64 * (ROOT3 / 2) / 4dan batas hitam ini masing-masing memiliki ketebalan 64 * (ROOT3 / 2) / 16Kurva harus memiliki batas-batas ini, dan bukan hanya menjadi strip padat.

Satuan ukuran

  1. Semua jarak dalam piksel (1 adalah jarak horizontal atau vertikal antara 2 piksel yang berdekatan).
  2. Akar kuadrat dari 3 harus akurat hingga 7 angka signifikan. Artinya, perhitungan Anda harus setara dengan menggunakan ROOT3 sedemikian rupa1.7320505 <= ROOT3 < 1.7320515

Mencetak gol

Kode terpendek dalam byte menang.


Bagi mereka yang bertanya-tanya, N = 0 dan N = 1 tidak termasuk karena mereka sesuai dengan lingkaran dan trefoil, yang tidak cocok dengan pola yang berlaku untuk N> = 2. Saya berharap bahwa sebagian besar pendekatan untuk tantangan ini perlu menambahkan kode kasus khusus untuk 0 dan 1, jadi saya memutuskan untuk menghilangkannya.


1
Apakah ada gunanya memiliki diagram untuk menunjukkan apa yang terkait dengan semua angka?
trichoplax

Sebelum saya golf jawaban saya / tambahkan sudut, apakah 7 angka penting benar-benar diperlukan untuk detail kecil seperti ketebalan garis, dll? Akurasi seperti "7 angka signifikan atau 1 piksel, mana yang lebih besar" tampaknya lebih tepat.
Level River St

@LevelRiverSt karena ukuran gambar berskala dengan input, bahkan 7 angka signifikan tidak cukup untuk akurasi 1 piksel untuk N. lebih besar. Saya telah menetapkan 7 angka penting setelah beberapa diskusi dalam obrolan, sehingga semua jawaban dijaga tetap sama standar.
trichoplax

Ya, perlu untuk penskalaan gambar untuk angka signifikan N. 7 yang lebih besar pada gambar 1000000 x 1000000 sesuai dengan 0,1 piksel, tetapi dengan perhitungan menengah, itu bisa lebih buruk dari itu. Saya hanya berpikir stroke-width:3.464102dan mirip sedikit berlebihan jika idenya adalah mendapatkan akurasi 1 pixel. Saya akan teruskan dan memasukkannya seperti itu, jika itu yang berkuasa.
Level River St

Jawaban:


27

Ruby, 1168 932

Mengoreksi kesalahan dari tadi malam, lebih banyak bermain golf setelah klarifikasi.

Ini (saat ini) adalah program lengkap yang menerima nomor dari stdin dan menampilkan svgfile ke stdout. Saya memilih svg karena saya tahu mungkin untuk memenuhi semua persyaratan pertanyaan, tetapi memang ada beberapa masalah. dalam SVG tertentu hanya mendukung lengkungan lingkaran sebagai bagian dari pathobjek, dan tidak mendefinisikan mereka dalam hal pusatnya melainkan dua titik akhir.

Kode

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

Output N = 4

disusun kembali oleh pertukaran Stack. Terlihat jauh lebih baik dari aslinya.

masukkan deskripsi gambar di sini Penjelasan

Pada awalnya saya mempertimbangkan sesuatu seperti http://euler.nmt.edu/~jstarret/sierpinski.html di mana segitiga dipecah menjadi tiga helai berwarna berbeda, masing-masing membentuk jalur dari satu sudut ke sudut lain. Lingkaran tidak lengkap ditampilkan sebagai segi enam tidak lengkap di sana. Tuliskan lingkaran di dalam segi enam menunjukkan bahwa jari-jari lingkaran harus sqrt(3)/2dikali panjang samping. Untaian dapat dibangun secara rekursif seperti yang ditunjukkan, tetapi ada komplikasi tambahan karena sudut perlu dibulatkan dan sulit untuk mengetahui ke arah mana untuk melengkung, jadi saya tidak menggunakan pendekatan ini.

Apa yang saya lakukan adalah sebagai berikut.

Pada gambar di bawah ini Anda dapat melihat ada lilitan horizontal yang dimiliki oleh N = 2 unit (berwarna hijau) yang tersusun dalam segitiga sierpinski dan lintasan penjembatan tambahan (berwarna biru.)

Sudah menjadi rahasia umum bahwa angka ganjil pada segitiga Pascal membentuk segitiga sierpinski. Segitiga sierpinski digit biner dapat diperoleh secara analog dengan mulai dari angka p=1dan berulang-ulang dengan p<<1.

Saya memodifikasi pendekatan ini, mulai dari p=2dan berulang kali dengan p*4. Ini memberikan segitiga sierpinski bergantian dengan kolom nol.

Sekarang kita bisa melakukan hakhift p dan memeriksa menggunakan tiga bit terakhir %8. Jika ya 010kita perlu menggambar twist hijau milik unit N = 2. jika mereka 101kita perlu menggambar twist biru, menjembatani. Untuk menguji kedua angka-angka ini bersama-sama kita menemukan modulo %3dan jika ini 2 kita perlu menggambar twist.

Akhirnya, sebagai tambahan pada tikungan horizontal, kami membuat dua salinan diputar melalui 120 dan 240 derajat untuk menggambar tikungan diagonal dan melengkapi gambar. Yang tersisa hanyalah menambahkan sudut.

Kode yang dikomentari

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

masukkan deskripsi gambar di sini


Di mana Anda mengatakan "Terlihat jauh lebih baik dari aslinya" mungkin ada baiknya menambahkan sesuatu seperti "(klik gambar untuk melihat ukuran penuh)" untuk siapa saja yang tidak menyadarinya.
trichoplax

@trichoplax itu tidak terjadi pada saya untuk mengklik gambar. Tapi bagaimanapun, ini adalah PNG, karena pertukaran stack tidak menerima gambar svg, jadi ujung-ujungnya sengaja dikaburkan. File SVG lokal saya memiliki tepi lebih tajam dan terlihat jauh lebih baik.
Level River St

@trichoplax perbaikan cepat pada ukuran gambar selesai. Akan bermain golf lagi di hari lain.
Level River St

1
+1 karya bagus. Saya sangat suka penjelasan rinci dengan diagram kode warna.
trichoplax

1
Hyperlink sudah mati.
mbomb007
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.