再帰スタイナーチェーン


11

スタイナーチェーンは、次の画像に示すように、各サークルがチェーンの前および次のサークルだけでなく、2つの他の交差しないサークルに接するN個のサークルのセットです。

注文3 注文5 注文7

この課題では、シュタイナーチェーンを再帰的に描画するプログラム/関数を作成します。つまり、特定のチェーンの円は、チェーンの別の反復の基本円になります。

ここに画像の説明を入力してください

チャレンジ

画像の寸法と、チェーンの各連続反復における円のレベルを示す整数のリストを受け入れるプログラム/関数を作成し、再帰シュタイナーチェーンが描画された画像を出力します。

入力

プログラム/関数は2つの引数を受け入れます。

  • s -画像の幅と高さ
  • ls -チェーンの連続する各反復に存在する円の数を示す正の整数のリスト。最上位のチェーンから最下位のチェーンの順序

出力

プログラム/関数は、次元sxのイメージを出力しs、Resteinive Steinerチェーンを表示します。

  • 最上位の基本円はs、画像の中心にある直径の画像と同じ大きさになります
  • 物事を簡単にするために、シュタイナーチェーンの2つのベースサークルは同心になります。つまり、2つのベースラインサークルの中心点は同じになります。
  • 外側の半径、Rおよびチェーン内の円の数が与えられると、内側の半径Nの式R'R' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • チェーンの円と内側の基本円は、チェーンの次の反復の外側の基本円になります
  • チェーンサークルを再帰的に処理する間、次のチェーンの順序は次の値に対応する必要があります ls
  • チェーンの内側の円を再帰的に処理するとき、順序はその親の順序と同じである必要があります(例[5,2]):
  • 注文5.2
  • すべてのチェーンは、再帰の長さの深さで終了する必要があります ls
  • チェーンの回転は重要ではありません:
  • ローテーション1 ローテーション2
  • ただし、親の中心点に対する再帰チェーンの回転は同じである必要があります。
  • 注文5.2 無効な注文5.2
  • すべての円は、アウトラインまたは塗りつぶしで描画する必要があります
  • 色の選択は実装に任され、抜け穴を保存します(たとえば、すべてを同じ色で塗りつぶします)

実行例

次の例では、色はによって決定され(depth of the recursion)^4ます。

ここでソースを見つけることができます。

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


回答:


4

Javascript ES6、379バイト

このソリューションは、問題のサンプルの実行を生成するために使用されました。

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

ゴルフをしていない:

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

注:fキャンバスを返します。

実行例(<body>追加するaがあると仮定):

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

次の画像をページにダンプする必要があります。

出力

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.