Рекурсивные цепи Штейнера

11

Цепочки Штейнера - это набор из N кругов, каждый из которых касается 2 других непересекающихся кругов, а также предыдущего и следующего кругов цепи, как показано на изображениях ниже:

Заказ 3 Заказ 5 Заказ 7

В этой задаче вы напишите программу / функцию, которая рекурсивно рисует цепочки Штейнера, то есть окружности данной цепочки будут базовыми окружностями другой итерации цепочек:

введите описание изображения здесь

Вызов

Напишите программу / функцию, которая принимает размеры изображения и список целых чисел, обозначающих уровень окружностей в каждой последующей итерации цепочек, и выведите изображение с рекурсивными цепочками Штейнера, нарисованными на нем.

вход

Ваша программа / функция будет принимать 2 аргумента:

  • s - ширина и высота изображения
  • ls - список натуральных чисел, обозначающих количество кружков, присутствующих в каждой последующей итерации цепочек, упорядоченных от самой верхней цепочки до самой нижней цепочки

Выход

Ваша программа / функция выведет изображение размера sx sс рекурсивной цепочкой Штейнера.

  • Базовый круг верхнего уровня будет таким же большим, как изображение с диаметром 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

Dendrobium
источник
1
Связанные с.
Мартин Эндер

Ответы:

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

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

Примечание: fвозвращает холст.

Пример выполнения (предполагается, что есть что <body>добавить):

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

Должен сбросить следующее изображение на страницу:

Выход

Dendrobium
источник