Construa n-gons com uma régua e uma bússola


16

A tarefa é desenhar um polígono regular de n lados usando apenas uma bússola e uma régua não marcada.

A entrada (n) é um dos 10 números a seguir: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17.

Método : Como você só tem uma régua e uma bússola, só pode desenhar pontos, linhas e círculos.

Uma linha só pode ser desenhada:

  • através de dois pontos existentes.

Um círculo só pode ser desenhado:

  • com um ponto como centro e com o perímetro passando por um segundo ponto.

Um ponto só pode ser desenhado:

  • na interseção de duas linhas,

  • na interseção (s) de uma linha e um círculo,

  • na interseção (s) de dois círculos,

  • desde o início, quando você pode desenhar 2 pontos para começar.

Através deste processo (e somente através deste processo), você deve desenhar as n linhas do n-gon solicitado, juntamente com qualquer trabalho necessário para chegar a esse estágio.

EDIT: A posição das interseções deve ser calculada, mas linhas e círculos podem ser desenhados por qualquer meio fornecido pelo idioma.

Saída é uma imagem de um polígono regular de n lados, mostrando o trabalho.

Graficamente, não há restrições quanto ao tamanho, formato, espessura da linha ou qualquer outra coisa não mencionada aqui. No entanto, deve ser possível distinguir visualmente linhas distintas, círculos e suas interseções. Além disso:

  • As n linhas que compõem os lados do seu n-gon devem ter uma cor diferente do seu 'trabalho' (ou seja, pontos, círculos ou outras linhas) e uma cor diferente novamente para o seu plano de fundo.
  • O trabalho pode deixar as bordas da área de desenho, exceto os pontos, que devem estar todos dentro dos limites visíveis da imagem.
  • Um círculo pode ser um círculo completo ou apenas um arco (desde que mostre as interseções necessárias).
  • Uma linha é infinita (ou seja, sai da área de desenho) ou cortada nos dois pontos em que passa. EDIT: Uma linha pode ser desenhada a qualquer comprimento. Os pontos só podem ser criados onde a linha desenhada se cruza visualmente.
  • Um ponto pode ser desenhado como você desejar, incluindo a não marcação.

A pontuação é dupla, um envio recebe 1 ponto por entrada suportada, para um máximo de 10 pontos. Em caso de empate, a menor contagem de bytes vence.

O reconhecimento será concedido a envios que possam construir n-gons nas poucas etapas ou que sejam capazes de construir n-gons fora do intervalo especificado, mas isso não ajudará sua pontuação.

Informações básicas da Wikipedia


Se você permitir que as linhas sejam cortadas nos pontos definidos, isso significa que as interseções relevantes podem estar fora da linha desenhada.
Martin Ender

Podemos usar atalhos como plotar dois segmentos de linha AB e BC plotar uma única linha ABC, se nossa linguagem fornecer isso?
Martin Ender

11
É suficiente desenhar a construção ou o programa também precisa calculá- la? Por exemplo, se eu quiser desenhar um círculo na origem que passa pelo ponto (300.400), posso (sabendo que o raio é 500) fazer CIRCLE 0,0,500ou preciso fazer R=SQRT(300^2+400^2): CIRCLE 0,0,R? (BTW trabalhar fora postions de interseções é provavelmente mais difícil do que linhas e círculos.)
Nível River St

Da Wikipedia: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
Dr. belisarius 10/10

Normalmente, você chama "régua não marcada" como "régua" em termos matemáticos, como a citação de belisarius.
Just-

Respostas:


10

BBC Basic, 8 polígonos: 3,4,5,6,8,10,12,15 lados (também 60 lados)

Faça o download do emulador em http://www.bbcbasic.co.uk/bbcwin/download.html

Decidi não incluir 16 lados, simplesmente porque minha pré-construção estava ficando um pouco confusa. Seriam necessários mais 2 círculos e uma linha. O BTW 17 lados é realmente muito complicado e talvez fosse melhor como um programa separado.

Recebi mais retorno por adicionar 2 círculos à minha construção original para fazer o pentágono, pois isso também me deu acesso aos lados 10,15 e 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

O programa faz uma pré-construção antes de solicitar qualquer entrada do usuário. Isso é suficiente para definir pelo menos 2 pontos no círculo principal que correspondem aos vértices adjacentes de 3,4,5,6,8,10,12,15 ou figura de 60 lados. Os pontos são armazenados em um conjunto de matrizes de 99 elementos, nos quais os elementos de 0 a 59 são reservados para pontos igualmente espaçados ao redor da circunferência. Isto é principalmente para maior clareza, o octógono não se encaixa perfeitamente em 60 pontos, portanto é necessária alguma flexibilidade (e também para os 16 gon, se incluídos). A imagem se parece com a imagem abaixo, em branco e cinza, com apenas os dois círculos em amarelo sendo dedicados exclusivamente a formas com múltiplos de 5 lados. Veja http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscrib_in_a_Circle_240px.gifpara o meu método preferido de desenho do pentágono. O ângulo alegre é evitar linhas verticais, pois o programa não pode lidar com gradientes infinitos.

insira a descrição da imagem aqui

O usuário digita um número dpara o número de lados necessários. O programa procura na matriz o índice do primeiro dos dois pontos (o próximo fica a 60 / d no sentido horário).

O programa então percorre o processo de desenhar um círculo centrado no segundo ponto que passa pelo primeiro e calcular a nova interseção para percorrer o círculo principal. Os círculos da construção são desenhados em azul e o polígono necessário é desenhado em vermelho. As imagens finais são assim.

Estou bastante satisfeito com eles. O BBC Basic realiza os cálculos com precisão suficiente. No entanto, é aparente (principalmente com 15 e 60 lados) que o BBC Basic tende a desenhar círculos com um raio um pouco menor do que deveria.

insira a descrição da imagem aqui


11
Um truque que eu perdi com isso é que a linha de 45 graus corta o círculo principal ao lado de dois círculos que podem ser usados ​​para construir 24 e 40 gon, ambos fatores de 120. Existem dois fatores de 60 (20 e 30) falta, o que exigiria mais um círculo na pré-construção, para definir os dois cantos ausentes do pentágono e dar as diferenças 1 / 5-1 / 6 = 1/30 e 1 / 5-1 / 4 = 1/20 . No entanto, acho que não vou atualizar minha resposta no momento. BTW, obrigado pelo bônus @Martin!
Level River St

16

Mathematica, 2 3 4 polígonos, 759 bytes

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

Pontos aleatórios:

  • A entrada é fornecida via prompt.
  • Atualmente, estou apoiando as entradas 3 , 4 , 6 , 8 .
  • Entre suas opções, eu escolhi os seguintes estilos de plotagem:
    • Círculos completos.
    • Linhas de ponto a ponto, a menos que haja uma interseção relevante do lado de fora; nesse caso, eu codificarei a extensão.
    • Sem pontos.
    • O funcionamento é preto, os polígonos são vermelhos - não por razões estéticas, mas por razões de golfe.
  • Há alguma duplicação séria de código entre os polígonos. Acho que em algum momento farei uma única construção para todos eles, enumerando todas as linhas, pontos e círculos ao longo do caminho e depois reduza o Switchpara selecionar os círculos e linhas relevantes para cada construção. Dessa forma, eu poderia reutilizar muitas primitivas entre elas.
  • O código contém muitas funções padrão que determinam todas as interseções relevantes e criam círculos a partir de dois pontos.
  • Com isso, adicionarei mais polígonos no futuro.

Aqui está o código não destruído:

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

E aqui estão as saídas:

insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui insira a descrição da imagem aqui


Basta saber se seria mais curto codificar as linhas e círculos vermelhos e pretos para cada tipo de entrada e desenhá-los.
Optimizer

@ Otimizador Suponho que expressões n maiores e exatas para os pontos provavelmente também se tornem muito longas. Acho que quando adiciono mais polígonos, em algum momento fará sentido criar uma única construção para todos eles e, em seguida, basta selecionar os círculos e linhas relevantes no Switch. Isso provavelmente me permitiria reutilizar muito mais linhas e pontos de círculos.
Martin Ender

Eu isso eu tenho um caminho mais curto para a construção do octagon, mas não tenho certeza de como mostrá-lo ...
haskeller orgulhoso

@proudhaskeller Ainda é mais curto se você considerar que as 5 primeiras linhas da construção poderiam realmente ser descartadas reutilizando código do quadrado, e que essa maneira de construí-lo poderia ser generalizada para construir qualquer 2n-gon a partir de um n-gon ? (As duas coisas que tenho em mente para melhorar isso.) Se assim for ... hummm ... suponho que uma descrição rigorosa com pontos nomeados como este funcionaria.
Martin Ender

@proudhaskeller Você pode publicá-lo antes que a recompensa expire. ;)
Martin Ender
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.