Łańcuchy rekurencyjne Steiner

11

Łańcuchy Steinera to zestaw N kół, w których każde koło jest styczne do 2 innych nie przecinających się kół, a także do poprzedniego i następnego koła łańcucha, jak pokazano na poniższych zdjęciach:

Zamówienie 3 Zamówienie 5 Zamówienie 7

W tym wyzwaniu napiszesz program / funkcję, która rysuje rekurencyjnie łańcuchy Steinera, to znaczy koła danego łańcucha będą podstawowymi okręgami innej iteracji łańcuchów:

wprowadź opis zdjęcia tutaj

Wyzwanie

Napisz program / funkcję, która akceptuje wymiary obrazu i listę liczb całkowitych oznaczających poziom okręgów w każdej kolejnej iteracji łańcuchów, i wyślij obraz z narysowanymi do niego rekurencyjnymi łańcuchami Steiner.

Wejście

Twój program / funkcja zaakceptuje 2 argumenty:

  • s - szerokość i wysokość obrazu
  • ls - lista liczb całkowitych dodatnich oznaczających liczbę okręgów obecnych w każdej kolejnej iteracji łańcuchów, uporządkowana od łańcucha od najwyższego do najniższego łańcucha

Wynik

Twój program / funkcja wyświetli obraz wymiaru s x sprzedstawiający łańcuch odzysku Steiner.

  • Koło podstawowe najwyższego poziomu będzie tak duże, jak obraz o średnicy s, wyśrodkowany w środku obrazu
  • Dla uproszczenia, 2 podstawowe koła łańcucha Steiner będą koncentryczne, to znaczy, że punkty środkowe 2 podstawowych kół będą takie same
  • Biorąc pod uwagę promień zewnętrzny Ri liczbę kół w łańcuchu, Nwzór na promień wewnętrznyR' jest następującyR' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • Okręgi łańcucha, jak i wewnętrzny okrąg podstawy, będą zewnętrznymi okręgami podstawy następnej iteracji łańcuchów
  • Podczas rekurencji przez koła łańcucha kolejność następnego łańcucha powinna odpowiadać następnej wartości w ls
  • Podczas powtarzania się przez wewnętrzny krąg łańcucha, kolejność powinna być taka sama jak kolejność jego rodziców (przykład [5,2]):
  • Zamów 5.2
  • Wszystkie łańcuchy powinny kończyć rekurencję na głębokości ls
  • Rotacja łańcuchów nie ma znaczenia:
  • Obrót 1 Obrót 2
  • Jednak obroty łańcuchów rekurencyjnych względem punktu środkowego ich rodziców powinny być takie same:
  • Zamów 5.2 Nieprawidłowe zamówienie 5.2
  • Wszystkie koła powinny być narysowane konturem lub wypełnieniem pełnym
  • Wybór koloru pozostawia się do wdrożenia, z wyjątkiem luk (na przykład wypełnianie wszystkiego tym samym kolorem)

Przykład działa

W poniższych przykładach kolor określa (depth of the recursion)^4.

Możesz znaleźć źródło tutaj .

chain(600,[5,4,3])

5.4.3

chain(600,[11,1,1,1,1,1,1])

11.1.1.1.1.1.1

chain(600,[5,6,7,8,9])

5.6.7.8.9

Dendrobium
źródło
1
Związane z.
Martin Ender,

Odpowiedzi:

4

JavaScript ES6, 379 bajtów

To rozwiązanie zostało użyte do wygenerowania przykładowych przebiegów w pytaniu.

f=(s,ls)=>{with(V=document.createElement`canvas`)with(getContext`2d`)with(Math)return(width=height=s,translate(s/=2,s),(S=(o,d=0,n=ls[d],i=(o-o*sin(PI/n))/(sin(PI/n)+1),r=0)=>{fillStyle=`rgba(0,0,0,${pow(d/ls.length,4)})`;beginPath(),arc(0,0,o,-PI,PI),fill();if(d++<ls.length){S(i,d,n);for(;r<n;++r){save();translate(0,(o+i)/2);S((o-i)/2,d);restore();rotate((2*PI)/n);}}})(s),V)}

Nie golfowany:

f=(s,ls)=>{                                        // define function that accepts image dimensions and a list of orders
 with(V=document.createElement`canvas`)            // create canvas to draw on, bring its functions into current scope chain
 with(getContext`2d`)                              // bring graphics functions into current scope chain
 with(Math)return(                                 // bring Math functions into current scope chain
  width=height=s,                                  // set width and height of image
  translate(s/=2,s),                               // center the transform on image
   (S=(o,d=0,                                      // define recursive function that accepts outer radius, depth, and optionally order
       n=ls[d],                                    // default chain order to corresponding order in input list
       i=(o-o*sin(PI/n))/(sin(PI/n)+1),            // calculate inner base circle radius
       r=0)=>{                                     // initialize for loop var
    fillStyle=`rgba(0,0,0,${pow(d/ls.length,4)})`; // fill based on depth
    beginPath(),arc(0,0,o,-PI,PI),fill();          // draw circle
    if(d++<ls.length){                             // if within recursion limit
     S(i,d,n);                                     //   recurse on inner circle
     for(;r<n;++r){                                //   loop through all circles of the chain
      save();                                      //   save transform
      translate(0,(o+i)/2);                        //   translate origin to middle of the 2 base circles
      S((o-i)/2,d);                                //   recurse on chain circle
      restore();                                   //   restore transform
      rotate((2*PI)/n);                            //   rotate transform to next circle in chain
   }}})(s),                                        // begin the recursion
 V)}                                               // return the canvas

Uwaga: fzwraca płótno.

Przykładowy przebieg (przy założeniu, że <body>należy dołączyć):

document.body.appendChild(f(600,[13,7,11,5,3]))

Powinien zrzucić na stronę następujący obraz:

Wynik

Dendrobium
źródło