Построить н-гон с линейкой и компасом


16

Задача состоит в том, чтобы нарисовать правильный многоугольник из n сторон, используя только компас и линейку без опознавательных знаков.

Вход (n) является одним из следующих 10 чисел: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17.

Метод : поскольку у вас есть только линейка и компас, вы можете рисовать только точки, линии и круги.

Линия может быть нарисована только:

  • через две существующие точки.

Круг можно нарисовать только:

  • с одной точкой в ​​качестве центра и с периметром, проходящим через вторую точку.

Точку можно нарисовать только:

  • на пересечении двух линий,

  • на пересечении (ях) линии и круга,

  • на пересечении (ях) двух окружностей,

  • в начале, когда вы можете нарисовать 2 точки, чтобы начать.

Через этот процесс (и только через этот процесс) вы должны нарисовать n линий запрошенного n-gon вместе с любой работой, необходимой для достижения этой стадии.

РЕДАКТИРОВАТЬ: Положение пересечений должны быть рассчитаны, но линии и круги могут быть нарисованы любым способом, предусмотренным языком.

Вывод представляет собой изображение n-стороннего правильного многоугольника, показывающее работу.

Графически нет никаких ограничений на размер изображения, формат, толщину линии или что-либо еще, не упомянутое здесь. Однако должна быть возможность визуально различать различные линии, круги и их пересечения. Дополнительно:

  • N линий, которые составляют стороны вашего n-гона, должны иметь другой цвет по сравнению с вашей «рабочей» (то есть любые точки, круги или другие линии) и снова иметь другой цвет на вашем фоне.
  • Рабочие могут оставить границы области рисования, кроме точек, которые должны находиться в пределах видимых границ изображения.
  • Круг может быть полным кругом или просто дугой (если он показывает необходимые пересечения).
  • Линия бесконечна (т.е. покидает область рисования) или обрезана в двух точках, через которые она проходит. РЕДАКТИРОВАТЬ: линия может быть проведена любой длины. Точки могут быть созданы только там, где нарисованная линия визуально пересекается.
  • Точка может быть нарисована по вашему желанию, в том числе не отмечая ее.

Подсчет очков имеет два аспекта: за каждый вход, который он поддерживает, предоставляется 1 балл, что составляет максимум 10 баллов. В случае ничьи побеждает самый короткий счетчик байтов.

Признание будет дано представлениям, которые могут построить n-гоны за наименьшее количество шагов или способны построить n-гоны за пределами заданного диапазона, но это не поможет вашему счету.

Справочная информация из Википедии


Если вы позволите отрезать линии в точках, которые они определяют, это означает, что соответствующие пересечения могут находиться за пределами нарисованной линии.
Мартин Эндер

Можем ли мы использовать такие ярлыки, как построение двух отрезков AB и BC путем построения отрезка ABC из одной линии, если наш язык это обеспечивает?
Мартин Эндер

1
Достаточно ли нарисовать конструкцию или программа должна рассчитать и ее? Например, если я хочу нарисовать круг в начале координат, проходящем через точку (300 400), могу ли я (зная, что радиус равен 500) сделать CIRCLE 0,0,500или мне нужно это сделать R=SQRT(300^2+400^2): CIRCLE 0,0,R? (Кстати, выработка положений пересечений, вероятно, сложнее, чем линий и окружностей.)
Level River St

Из Википедии:Carl Friedrich Gauss in 1796 showed that a regular n-sided polygon can be constructed with straightedge and compass if the odd prime factors of n are distinct Fermat primes
Доктор Белизарий

Обычно вы называете «безымянный правитель» как «прямой край» в математических терминах, как, например, цитата Велизария.
Половина

Ответы:


10

BBC Basic, 8 полигонов: 3,4,5,6,8,10,12,15 сторон (также 60 сторон)

Загрузите эмулятор на http://www.bbcbasic.co.uk/bbcwin/download.html

Я решил не включать 16 сторон, просто потому что моя предварительная конструкция становилась довольно загроможденной. Еще 2 круга и линия будут необходимы. Кстати, 17 сторон действительно очень сложны и, возможно, лучше всего подходят в качестве отдельной программы.

Я получил больше прибыли за добавление 2 кругов к моей первоначальной конструкции, чтобы создать пятиугольник, так как это также дало мне доступ к 10,15 и 60 сторонам.

  GCOL 7                               :REM light grey
  z=999                                :REM width of display (in positive and negative direction)
  e=1                                  :REM enable automatic drawing of line through intersections of 2 circles
  DIM m(99),c(99),p(99),q(99),r(99)    :REM array dimensioning for lines and points
  REM lines have a gradient m and y-intercept c. Points have coordinates (p,q) and may be associated with a circle of radius r.

  REM PRECONSTRUCTION

  ORIGIN 500,500
  p(60)=0:q(60)=0                      :REM P60=centre of main circle
  p(15)=240:q(15)=70                   :REM P15=intersection main circle & horiz line
  t=FNr(60,15)                         :REM draw main circle, set radius, SQR(240^2+70^2)=250 units (125 pixels)
  t=FNl(1,60,15)                       :REM L1=horizontal through main circle
  t=FNc(15,45,1,60,-1)                 :REM define P45 as other intersection of main cir and horiz line. overwrite P15 with itself.

  t=FNr(15,45):t=FNr(45,15)            :REM draw 2 large circles to prepare to bisect L1
  t=FNc(61,62,2,45,15)                 :REM bisect L1, forming line L2 and two new points
  t=FNc(30,0,2,60,-1)                  :REM define points P0 and P30 on the crossings of L2 and main circle
  t=FNr(30,60):t=FNc(40,20,3,60,30)    :REM draw circles at P30, and line L3 through intersections with main circle, to define 2 more points
  t=FNr(15,60):t=FNc(25,5,4,60,15)     :REM draw circles at P15, and line L4 through intersections with main circle, to define 2 more points
  t=FNx(63,3,4):t=FNl(5,63,60)         :REM draw L5 at 45 degrees
  t=FNc(64,53,5,60,-1)                 :REM define where L5 cuts the main circle

  e=0                                  :REM disable automatic line drawing through intersections of 2 circles
  GCOL 11                              :REM change to light yellow for the 5 sided preconstruction
  t=FNx(65,1,4):t=FNr(65,0)            :REM draw a circle of radius sqrt(5) at intersection of L1 and L4
  t=FNc(66,67,1,65,-1)                 :REM find point of intersection of this circle with L1
  t=FNr(0,67)                          :REM draw a circle centred at point 0 through that intersection
  t=FNc(36,24,6,60,0)                  :REM find the intersections of this circle with the main circle


  REM USER INPUT AND POLYGON DRAWING

  INPUT d
  g=ASC(MID$("  @@XT u X @  T",d))-64  :REM sides,first point: 3,0; 4,0; 5,24; 6,20; 8,53; 10,24; 12,0; 15,20
  IF d=60 THEN g=24                    :REM bonus polygon 60, first point 24
  FORf=0TOd
    GCOL12                             :REM blue
    h=(g+60DIVd)MOD60                  :REM from array index for first point, calculate array index for second point
    t=FNr(h,g)                         :REM draw circle centred on second point through first point
    t=FNc((h+60DIVd)MOD60,99,99,60,h)  :REM calculate the position of the other intersection of circle with main circle. Assign to new point.
    GCOL9                              :REM red
    LINEp(g),q(g),p(h),q(h)            :REM draw the side
    g=h                                :REM advance through the array
  NEXT

  END

  REM FUNCTIONS

  REM line through a and b
  DEFFNl(n,a,b)
  m(n)=(q(a)-q(b))/(p(a)-p(b))
  c(n)=q(a)-m(n)*p(a)
  LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z
  =n

  REM radius of circle at point a passing through point b
  DEFFNr(a,b)
  r(a)=SQR((p(a)-p(b))^2+(q(a)-q(b))^2)
  CIRCLEp(a),q(a),r(a)
  =a

  REM intersection of 2 lines: ma*x+ca=mb*x+cb so (ma-mb)x=cb-ca
  DEFFNx(n,a,b)
  p(n)=(c(b)-c(a))/(m(a)-m(b))
  q(n)=m(a)*p(n)+c(a)
  =n

  REM intersection of 2 circles a&b (if b>-1.) The first step is calculating the line through the intersections
  REM if b < 0 the first part of the function is ignored, and the function moves directly to calculating intersection of circle and line.
  REM inspiration from http://math.stackexchange.com/a/256123/137034

  DEFFNc(i,j,n,a,b)
  IF b>-1 c(n)=((r(a)^2-r(b)^2)-(p(a)^2-p(b)^2)-(q(a)^2-q(b)^2))/2/(q(b)-q(a)):m(n)=(p(a)-p(b))/(q(b)-q(a)):IF e LINE -z,c(n)-m(n)*z,z,c(n)+m(n)*z

  REM intersection of circle and line
  REM (mx+ c-q)^2+(x-p)^2=r^2
  REM (m^2+1)x^2 + 2*(m*(c-q)-p)x + (c-q)^2+p^2-r^2=0
  REM quadratic formula for ux^2+vx+w=0 is x=-v/2u +/- SQR(v^2-4*u*w)/2u or x= v/2u +/- SQR((v/2u)^2 - w/u)

  u=m(n)^2+1
  v=-(m(n)*(c(n)-q(a))-p(a))/u               :REM here v corresponds to v/2u in the formula above
  w=SQR(v^2-((c(n)-q(a))^2+p(a)^2-r(a)^2)/u)


  s=SGN(c(n)+m(n)*v-q(a)):IF s=0 THEN s=1    :REM sign of s depends whether midpoint between 2 points to be found is above centre of circle a
  p(i)=v+s*w:q(i)=m(n)*p(i)+c(n)             :REM find point that is clockwise respect to a
  p(j)=v-s*w:q(j)=m(n)*p(j)+c(n)             :REM find point that is anticlockwise respect to a
  =n

Программа делает предварительную конструкцию, прежде чем запрашивать какой-либо пользовательский ввод. Этого достаточно, чтобы определить по крайней мере 2 точки на главном круге, которые соответствуют смежным вершинам 3,4,5,6,8,10,12,15 или 60-сторонней фигуры. Точки хранятся в наборе из 99 элементов, в которых элементы 0-59 отводятся для одинаково разнесенных точек по окружности. Это в основном для наглядности, восьмиугольник не идеально вписывается в 60 точек, поэтому здесь требуется некоторая гибкость (а также для 16-гиона, если он был включен). Изображение выглядит как изображение ниже, в белом и сером цвете, с только два желтых кружка предназначены исключительно для фигур, кратных 5 сторонам. См. Http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Incribed_in_a_Circle_240px.gifдля моего предпочтительного метода рисования пятиугольника. Угол поворота состоит в том, чтобы избегать вертикальных линий, поскольку программа не может обрабатывать бесконечные градиенты.

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

Пользователь вводит число dдля количества требуемых сторон. Программа ищет в массиве индекс первой из двух точек (следующая находится на расстоянии 60 градусов в направлении по часовой стрелке).

Затем программа проходит цикл рисования круга с центром во второй точке, проходящей через первую точку, и расчета нового пересечения, чтобы обойти главный круг. Строительные круги нарисованы синим цветом, а требуемый многоугольник - красным. Окончательные изображения выглядят так.

Я очень доволен ими. BBC Basic выполняет расчеты достаточно точно. Однако очевидно (особенно с 15 и 60 сторонами), что BBC Basic имеет тенденцию рисовать круги с немного меньшим радиусом, чем следовало бы.

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


1
Один трюк, который я пропустил, заключается в том, что линия под 45 градусами разрезает главный круг рядом с двумя кругами, которые можно использовать для построения 24-гоночных и 40-гоновых, оба фактора равны 120. Есть два фактора 60 (20 и 30) отсутствует, что потребует еще один круг в предварительной конструкции, чтобы определить два отсутствующих угла пятиугольника и дать различия 1 / 5-1 / 6 = 1/30 и 1 / 5-1 / 4 = 1/20 , Однако я не думаю, что буду обновлять свой ответ в данный момент. Кстати, спасибо за бонус @Martin!
Уровень Река St

16

Mathematica, 2 3 4 полигона, 759 байтов

S=Solve;n=Norm;A=Circle;L=Line;c={#,Norm[#-#2]}&{a_,b_List}~p~{c_,d_List}:=a+l*b/.#&@@S[a+l*b==c+m*d,{l,m}]{a_,b_List}~p~{c_,r_}:=a+l*b/.S[n[c-a-l*b]==r,l]{c_,r_}~p~{d_,q_}:={l,m}/.S[n[c-{l,m}]==r&&n[d-{l,m}]==q,{l,m}]q={0,0};r={1,0};a=q~c~r;b=r~c~q;Graphics@Switch[Input[],3,{s=#&@@p[a,b];A@@@{a,b},Red,L@{q,r,s,q}},4,{k={q,r};{d,e}=a~p~b;j={d,e-d};d=k~p~j~c~q;{e,f}=j~p~d;A@@@{a,b,d},L/@Accumulate/@{k,j},Red,L@{q,e,r,f,q}},6,{d={q,r};e=#&@@d~p~a;f=e~c~q;{g,h}=a~p~f;{i,j}=a~p~b;A@@@{a,b,f},L@{#-2#2,#+2#2}&@@d,Red,L@{r,i,g,e,h,j,r}},8,{k={q,r};{d,e}=a~p~b;j={d,e-d};d=k~p~j~c~q;{e,f}=j~p~d;g=e~c~q;h=q~c~e;i=r~c~e;{o,s}=g~p~h;{t,u}=g~p~i;o={o,2s-2o};s={t,2u-2t};{t,u}=o~p~d;{v,w}=s~p~d;A@@@{a,b,d,g,h,i},L/@Accumulate/@{k,j,o,s},Red,L@{q,t,e,v,r,u,f,w,q}}]

Случайные маркеры:

  • Ввод осуществляется через приглашение.
  • Я в настоящее время поддерживаю входы 3 , 4 , 6 , 8 .
  • Из ваших вариантов я выбрал следующие стили печати:
    • Полные круги.
    • Линии от конечной точки к конечной точке, если только соответствующее пересечение не находится снаружи, в этом случае я жестко закодирую экстент.
    • Нет очков.
    • Работа черная, полигоны красные - не по эстетическим соображениям, а по соображениям игры в гольф.
  • Есть серьезное дублирование кода между полигонами. Я думаю, что в какой-то момент я просто сделаю единую конструкцию для всех из них, перечисляя все линии, точки и окружности на этом пути, а затем просто уменьшая, Switchчтобы выбрать соответствующие окружности и линии для каждой конструкции. Таким образом, я мог бы использовать много примитивов между ними.
  • Код содержит множество стандартных функций, которые определяют все соответствующие пересечения и создают круги из двух точек.
  • Учитывая это, я буду добавлять больше полигонов в будущем.

Вот негольфированный код:

S = Solve;
n = Norm;
A = Circle;
L = Line;
c = {#, Norm[# - #2]} &
{a_, b_List}~p~{c_, d_List} := 
 a + l*b /. # & @@ S[a + l*b == c + m*d, {l, m}]
{a_, b_List}~p~{c_, r_} := a + l*b /. S[n[c - a - l*b] == r, l]
{c_, r_}~p~{d_, q_} := {l, m} /. 
  S[n[c - {l, m}] == r && n[d - {l, m}] == q, {l, m}]
q = {0, 0};
r = {1, 0};
a = q~c~r;
b = r~c~q;
Graphics@Switch[Input[],
  3,
  {
   s = # & @@ p[a, b];
   A @@@ {a, b},
   Red,
   L@{q, r, s, q}
   },
  4,
  {
   k = {q, r};
   {d, e} = a~p~b;
   j = {d, e - d};
   d = k~p~j~c~q;
   {e, f} = j~p~d;
   A @@@ {a, b, d},
   L /@ Accumulate /@ {k, j},
   Red,
   L@{q, e, r, f, q}
   },
  6,
  {
   d = {q, r};
   e = # & @@ d~p~a;
   f = e~c~q;
   {g, h} = a~p~f;
   {i, j} = a~p~b;
   A @@@ {a, b, f},
   L@{# - 2 #2, # + 2 #2} & @@ d,
   Red,
   L@{r, i, g, e, h, j, r}
   },
  8,
  {
   k = {q, r};
   {d, e} = a~p~b;
   j = {d, e - d};
   d = k~p~j~c~q;
   {e, f} = j~p~d;
   g = e~c~q;
   h = q~c~e;
   i = r~c~e;
   {o, s} = g~p~h;
   {t, u} = g~p~i;
   o = {o, 2 s - 2 o};
   s = {t, 2 u - 2 t};
   {t, u} = o~p~d;
   {v, w} = s~p~d;
   A @@@ {a, b, d, g, h, i},
   L /@ Accumulate /@ {k, j, o, s},
   Red,
   L@{q, t, e, v, r, u, f, w, q}
   }
  ]

А вот и выводы:

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


Просто интересно, будет ли короче жестко закодировать красные и черные линии и круги для каждого типа ввода и нарисовать их.
Оптимизатор

@Optimizer Полагаю, что для больших n точных выражений для точек, вероятно, тоже будет довольно много. Я думаю, что когда я добавлю больше полигонов, в какой-то момент будет иметь смысл создать одну единственную конструкцию для всех из них, а затем просто выбрать соответствующие круги и линии в Switch. Это, вероятно, позволило бы мне использовать намного больше кругов, линий и точек.
Мартин Эндер

У меня есть более короткий способ построить восьмиугольник, но я не уверен, как показать его вам ...
гордый haskeller

@proudhaskeller Является ли это еще короче, если учесть, что первые 5 строк конструкции могут быть фактически исключены из повторного использования кода из квадрата, и что этот способ его построения потенциально может быть обобщен для построения любого 2n-гона из n-гона ? (Обе вещи я имею в виду для улучшения этого.) Если так ... ммм ... я предполагаю, что точное описание с именованными точками, как этот, будет работать.
Мартин Эндер

@proudhaskeller Вы можете вместо этого опубликовать его самостоятельно до истечения срока действия награды. ;)
Мартин Эндер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.