Costruisci n-gon con un righello e una bussola


16

Il compito è disegnare un poligono regolare di n lati usando solo una bussola e un righello non marcato.

Input (n) è uno dei seguenti 10 numeri: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17.

Metodo : poiché hai solo un righello e una bussola puoi disegnare solo punti, linee e cerchi.

Una linea può essere solo disegnata:

  • attraverso due punti esistenti.

Un cerchio può essere disegnato solo:

  • con un punto al centro e con il suo perimetro che passa attraverso un secondo punto.

Un punto può essere solo disegnato:

  • all'intersezione di due linee,

  • all'intersezione (e) di una linea e un cerchio,

  • all'intersezione (i) di due cerchi,

  • all'inizio, quando puoi iniziare a disegnare 2 punti.

Attraverso questo processo (e solo attraverso questo processo) è necessario tracciare le n linee dell'n-gon richiesto, insieme a tutto il lavoro necessario per arrivare a quello stadio.

EDIT: la posizione delle intersezioni deve essere calcolata, ma le linee e i cerchi possono essere disegnati con qualsiasi mezzo fornito dalla lingua.

L'output è un'immagine di un poligono regolare n-side, che mostra funzionante.

Graficamente non ci sono restrizioni su dimensioni dell'immagine, formato, spessore della linea o qualsiasi altra cosa non menzionata qui. Tuttavia, deve essere possibile distinguere visivamente linee, cerchi e loro intersezioni distinti. Inoltre:

  • Le n linee che compongono i lati di n-gon devono essere di colore diverso da quello del tuo "lavoro" (ovvero punti, cerchi o altre linee) e di nuovo un colore diverso rispetto allo sfondo.
  • Lavorare può lasciare i bordi dell'area di disegno, ad eccezione dei punti, che devono essere tutti entro i limiti visibili dell'immagine.
  • Un cerchio può essere un cerchio completo o solo un arco (purché mostri le intersezioni richieste).
  • Una linea è infinita (ovvero lascia l'area di disegno) o tagliata nei due punti che attraversa. EDIT: una linea può essere tracciata in qualsiasi lunghezza. I punti possono essere creati solo dove la linea disegnata si interseca visivamente.
  • È possibile disegnare un punto come desiderato, incluso non contrassegnarlo.

Il punteggio è duplice, un invio ottiene 1 punto per input supportato, per un massimo di 10 punti. In caso di pareggio, vince il conteggio dei byte più corto.

Il riconoscimento verrà assegnato agli invii che possono costruire n-gon nel minor numero di passaggi o sono in grado di costruire n-gon al di fuori dell'intervallo dato, ma non aiuterà il tuo punteggio.

Informazioni di base da Wikipedia


Se si consente di tagliare le linee nei punti in cui sono definite, ciò significa che le intersezioni rilevanti potrebbero trovarsi al di fuori della linea disegnata.
Martin Ender,

Possiamo usare scorciatoie come la stampa di due segmenti di linea AB e BC disegnando una striscia di linea singola ABC, se la nostra lingua lo fornisce?
Martin Ender,

1
È sufficiente disegnare la costruzione o anche il programma deve calcolarla ? Ad esempio, se voglio disegnare un cerchio sull'origine che passa attraverso il punto (300.400) posso (sapendo che il raggio è 500) CIRCLE 0,0,500o devo fare R=SQRT(300^2+400^2): CIRCLE 0,0,R? (A proposito, elaborare posizioni di intersezioni è probabilmente più difficile di linee e cerchi.)
Level 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,

Di solito si chiama "righello non marcato" come "bordo dritto" in termini matematici, come la citazione di Belisario.
solo il

Risposte:


10

BBC Basic, 8 poligoni: 3,4,5,6,8,10,12,15 lati (anche 60 lati)

Scarica l'emulatore da http://www.bbcbasic.co.uk/bbcwin/download.html

Ho deciso di non includere 16 lati, semplicemente perché la mia pre-costruzione stava diventando piuttosto ingombra. Sarebbero necessari altri 2 cerchi e una linea. I lati BTW 17 sono davvero molto complicati e forse andrebbero meglio come programma separato.

Ho avuto più guadagno per l'aggiunta di 2 cerchi alla mia costruzione originale per creare il pentagono, poiché questo mi ha anche permesso di accedere a 10,15 e 60 lati.

  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

Il programma esegue una pre-costruzione prima di richiedere qualsiasi input dell'utente. Questo è sufficiente per definire almeno 2 punti sul cerchio principale che corrispondono a vertici adiacenti di una figura 3,4,5,6,8,10,12,15 o 60 lati. I punti sono memorizzati in una serie di matrici di 99 elementi, in cui gli elementi 0-59 sono messi da parte per punti equidistanti attorno alla circonferenza. Ciò è principalmente per chiarezza, l'ottagono non si adatta perfettamente a 60 punti, quindi è necessaria una certa flessibilità lì (e anche per il 16 gon se fosse incluso.) L'immagine assomiglia all'immagine qui sotto, in bianco e grigio, con solo i due cerchi in giallo sono dedicati esclusivamente alle forme con multipli di 5 lati. Vedi http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribed_in_a_Circle_240px.gifper il mio metodo di disegno preferito del pentagono. L'angolo sbarazzino è di evitare le linee verticali, poiché il programma non è in grado di gestire pendenze infinite.

inserisci qui la descrizione dell'immagine

L'utente inserisce un numero dper il numero di lati richiesti. Il programma cerca nell'array l'indice del primo dei due punti (il successivo è a 60 / d di distanza in senso orario).

Il programma procede quindi attraverso il processo di tracciare un cerchio centrato sul secondo punto che passa attraverso il primo e calcolare il nuovo incrocio per percorrere il cerchio principale. I cerchi di costruzione sono disegnati in blu e il poligono richiesto è disegnato in rosso. Le immagini finali sembrano così.

Sono abbastanza contento di loro. BBC Basic esegue i calcoli in modo sufficientemente accurato. Tuttavia è evidente (in particolare con 15 e 60 lati) che BBC Basic tende a disegnare cerchi con un raggio leggermente più piccolo di quanto dovrebbe.

inserisci qui la descrizione dell'immagine


1
Un trucco che mi è sfuggito è che la linea a 45 gradi taglia il cerchio principale proprio accanto a due cerchi che possono essere usati per costruire 24 gon e 40 gon, entrambi fattori di 120. Ci sono due fattori di 60 (20 e 30) mancante, che richiederebbe un altro cerchio nella precostruzione, per definire i due angoli mancanti del pentagono e dare le differenze 1 / 5-1 / 6 = 1/30 e 1 / 5-1 / 4 = 1/20 . Tuttavia, non credo che aggiornerò la mia risposta al momento. A proposito, grazie per il bonus @Martin!
Level River St

16

Mathematica, 2 3 4 poligoni, 759 byte

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

Punti elenco casuali:

  • L'input viene fornito tramite prompt.
  • Attualmente sto supportando gli ingressi 3 , 4 , 6 , 8 .
  • Tra le tue opzioni, ho scelto i seguenti stili di stampa:
    • Cerchi completi.
    • Linee da endpoint a endpoint, a meno che non si trovi una intersezione rilevante all'esterno, nel qual caso codificherò con forza l'estensione.
    • Nessun punto
    • Le lavorazioni sono nere, i poligoni sono rossi, non per l'estetica ma per motivi di golf.
  • C'è una seria duplicazione del codice tra i poligoni. Penso che a un certo punto farò solo una singola costruzione per tutti loro, enumerando tutte le linee, i punti e i cerchi lungo la strada, e quindi ridurrò semplicemente la Switchselezione dei cerchi e delle linee pertinenti per ciascuna costruzione. In questo modo potrei riutilizzare un sacco di primitivi tra di loro.
  • Il codice contiene molte funzioni di plateplate che determinano tutte le intersezioni rilevanti e creano cerchi da due punti.
  • Con quello sul posto, aggiungerò più poligoni in futuro.

Ecco il codice ungolfed:

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

Ed ecco gli output:

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


Mi chiedo solo se sarebbe più breve codificare le linee e i cerchi rossi e neri per ciascun tipo di input e disegnarli.
Ottimizzatore

@Optimizer Suppongo che espressioni n più grandi per i punti probabilmente diventeranno anche piuttosto lunghe. Penso che quando aggiungo più poligoni, ad un certo punto avrà senso creare una sola costruzione per tutti loro, e quindi selezionare solo i cerchi e le linee pertinenti nel Switch. Ciò probabilmente mi permetterebbe di riutilizzare molti più cerchi e linee e punti.
Martin Ender,

Io questo ho un modo più breve di costruire l'ottagono, ma non sono sicuro di come mostrartelo ...
orgoglioso haskeller,

@proudhaskeller È ancora più breve se si considera che le prime 5 linee della costruzione potrebbero effettivamente essere abbandonate riutilizzando il codice dal quadrato e che questo modo di costruirlo potrebbe potenzialmente essere generalizzato per costruire qualsiasi 2n-gon da un n-gon ? (Entrambe le cose, ho in mente di migliorare questo.) Se è così ... ummm ... Suppongo che una descrizione rigorosa con punti nominati come questo funzionerebbe.
Martin Ender,

@proudhaskeller Puoi invece pubblicarlo tu stesso prima della scadenza della taglia. ;)
Martin Ender,
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.