Catene Steiner ricorsive


11

Le catene di Steiner sono un insieme di N cerchi in cui ogni cerchio è tangente ad altri 2 cerchi non intersecanti nonché ai cerchi precedenti e successivi della catena, come mostrato nelle immagini seguenti:

Ordine 3 Ordine 5 Ordine 7

In questa sfida, scriverai un programma / funzione che disegna ricorsivamente catene di Steiner, ovvero i cerchi di una data catena saranno i cerchi di base di un'altra iterazione di catene:

inserisci qui la descrizione dell'immagine

Sfida

Scrivi un programma / funzione che accetta le dimensioni dell'immagine e un elenco di numeri interi che denoti il ​​livello dei cerchi in ogni successiva iterazione di catene e genera un'immagine con le catene ricorsive di Steiner disegnate su di essa.

Ingresso

Il tuo programma / funzione accetterà 2 argomenti:

  • s - larghezza e altezza dell'immagine
  • ls - elenco di numeri interi positivi che indicano il numero di cerchi presenti in ogni iterazione successiva di catene, ordinate dalla catena più in alto alla catena più in basso

Produzione

Il tuo programma / funzione produrrà un'immagine della dimensione sx che smostra la catena di Steiner recusiva.

  • Il cerchio di base di livello superiore sarà grande come l'immagine con un diametro di s, centrato all'interno dell'immagine
  • Per semplificare le cose, i 2 cerchi di base di una catena di Steiner saranno concentrici, ovvero i punti centrali dei 2 cerchi di base saranno gli stessi
  • Dato un raggio esterno Re il numero di cerchi in una catena N, la formula per il raggio interno R'èR' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • I cerchi della catena e il cerchio della base interna saranno i cerchi della base esterna della successiva iterazione di catene
  • Mentre ricorre attraverso i cerchi della catena, l'ordine della catena successiva dovrebbe corrispondere al valore successivo in ls
  • Mentre ricorre attraverso il cerchio interno di una catena, l'ordine dovrebbe essere uguale all'ordine dei suoi genitori (esempio [5,2]):
  • Ordine 5.2
  • Tutte le catene dovrebbero terminare la ricorsione a una profondità della lunghezza di ls
  • La rotazione delle catene non ha importanza:
  • Rotazione 1 Rotazione 2
  • Tuttavia, le rotazioni delle catene ricorsive relative al punto centrale dei genitori dovrebbero essere le stesse:
  • Ordine 5.2 Ordine non valido 5.2
  • Tutti i cerchi devono essere disegnati con un contorno o un riempimento solido
  • La scelta del colore è lasciata all'implementazione, tranne per le lacune (ad esempio, riempiendo tutto con lo stesso colore)

Esecuzioni di esempio

Negli esempi seguenti, il colore è determinato da (depth of the recursion)^4.

Puoi trovare la fonte qui .

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


Risposte:


4

Javascript ES6, 379 byte

Questa soluzione è stata utilizzata per generare le esecuzioni di esempio nella domanda.

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)}

Ungolfed:

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

Nota: frestituisce una tela.

Esempio di esecuzione (presuppone che ci sia un oggetto <body>da aggiungere):

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

Dovrebbe scaricare la seguente immagine sulla pagina:

Produzione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.