Konstruiere n-Gons mit einem Lineal und einem Kompass

16

Die Aufgabe besteht darin, ein reguläres Polygon von n Seiten mit nur einem Kompass und einem nicht markierten Lineal zu zeichnen.

Eingabe (n) ist eine der folgenden 10 Zahlen: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17.

Methode : Da Sie nur ein Lineal und einen Kompass haben, können Sie nur Punkte, Linien und Kreise zeichnen.

Eine Linie kann nur gezeichnet werden:

  • durch zwei bestehende Punkte.

Ein Kreis kann nur gezeichnet werden:

  • mit einem Punkt als Mittelpunkt und mit seinem Umfang durch einen zweiten Punkt.

Ein Punkt kann nur gezogen werden:

  • am Schnittpunkt zweier Linien,

  • an der Schnittstelle (n) einer Linie und eines Kreises,

  • am Schnittpunkt zweier Kreise,

  • zu Beginn, wenn Sie 2 Punkte ziehen können, um zu beginnen.

Durch diesen Prozess (und nur durch diesen Prozess) müssen Sie die n Linien des angeforderten n-Gons zeichnen, zusammen mit jeglicher Arbeit, die erforderlich ist, um zu dieser Stufe zu gelangen.

BEARBEITEN: Die Position von Schnittpunkten muss berechnet werden, aber Linien und Kreise können mit allen Mitteln gezeichnet werden, die von der Sprache bereitgestellt werden.

Die Ausgabe ist ein Bild eines n-seitigen regulären Polygons, das die Arbeit zeigt.

Grafisch gibt es keine Einschränkungen hinsichtlich Bildgröße, Format, Linienstärke oder sonstigem, was hier nicht erwähnt wird. Es muss jedoch möglich sein, verschiedene Linien, Kreise und deren Schnittpunkte visuell zu unterscheiden. Zusätzlich:

  • Die n Linien, aus denen die Seiten Ihres n-gons bestehen, müssen eine andere Farbe haben als Ihre Arbeit (dh Punkte, Kreise oder andere Linien) und eine andere Farbe für Ihren Hintergrund.
  • Beim Arbeiten können die Ränder des Zeichenbereichs mit Ausnahme von Punkten, die sich alle innerhalb der sichtbaren Grenzen des Bildes befinden müssen, verlassen werden.
  • Ein Kreis kann ein Vollkreis oder nur ein Bogen sein (solange er die erforderlichen Schnittpunkte anzeigt).
  • Eine Linie ist unendlich (dh verlässt den Zeichenbereich) oder wird an den beiden Punkten, durch die sie verläuft, abgeschnitten. BEARBEITEN: Eine Linie kann in beliebiger Länge gezogen werden. Punkte können nur dort erstellt werden, wo sich die gezeichnete Linie visuell schneidet.
  • Ein Punkt kann nach Belieben gezeichnet werden, auch wenn er nicht markiert ist.

Es gibt zwei Punkte, eine Einsendung erhält 1 Punkt für jede Eingabe, die sie unterstützt, für maximal 10 Punkte. Im Falle eines Unentschieden gewinnt die kürzeste Byteanzahl.

Einsendungen, die in den wenigsten Schritten n-Gons konstruieren können oder in der Lage sind, n-Gons außerhalb des angegebenen Bereichs zu konstruieren, werden anerkannt, aber dies hilft Ihrer Punktzahl nicht.

Hintergrundinformationen aus Wikipedia

jsh
quelle
Wenn Sie zulassen, dass Linien an den Punkten abgeschnitten werden, durch die sie definiert sind, bedeutet dies, dass relevante Schnittpunkte außerhalb der gezeichneten Linie liegen können.
Martin Ender
Können wir Abkürzungen wie das Zeichnen von zwei Liniensegmenten AB und BC durch Zeichnen eines einzelnen Linienstreifens ABC verwenden, wenn unsere Sprache dies vorsieht?
Martin Ender
1
Reicht es aus, die Konstruktion zu zeichnen , oder muss das Programm sie auch berechnen ? Wenn ich zum Beispiel einen Kreis am Ursprung zeichnen möchte, der durch den Punkt (300, 400) verläuft, kann ich (mit einem Radius von 500) dies tun CIRCLE 0,0,500oder muss ich dies tun R=SQRT(300^2+400^2): CIRCLE 0,0,R? (Übrigens ist das Ausarbeiten von Positionen von Kreuzungen wahrscheinlich schwieriger als das Ausarbeiten von Linien und Kreisen.)
Level River St
Aus 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
Normalerweise nennt man "nicht markiertes Lineal" mathematisch "gerade Kante", wie das Zitat von belisarius.
Nur die Hälfte des

Antworten:

10

BBC Basic, 8 Polygone: 3,4,5,6,8,10,12,15 Seiten (auch 60 Seiten)

Laden Sie den Emulator unter http://www.bbcbasic.co.uk/bbcwin/download.html herunter

Ich habe mich entschieden, 16 Seiten nicht einzubeziehen, nur weil meine Vorkonstruktion ziemlich unübersichtlich wurde. 2 weitere Kreise und eine Linie wären nötig. BTW 17 Seiten ist in der Tat sehr kompliziert und würde vielleicht am besten als separates Programm gehen.

Ich bekam mehr Gegenleistung für das Hinzufügen von 2 Kreisen zu meiner ursprünglichen Konstruktion, um das Fünfeck herzustellen, da dies mir auch Zugang zu 10,15 und 60 Seiten verschaffte.

  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

Das Programm führt eine Vorkonstruktion durch, bevor Benutzereingaben angefordert werden. Dies ist ausreichend, um mindestens 2 Punkte auf dem Hauptkreis zu definieren, die benachbarten Eckpunkten einer 3, 4, 5, 6, 8, 10, 12, 15 oder 60-seitigen Figur entsprechen. Die Punkte werden in einem Satz von 99-Element-Arrays gespeichert, in denen die Elemente 0-59 für gleichmäßig verteilte Punkte am Umfang beiseite gelegt werden. Dies dient hauptsächlich der Klarheit. Das Achteck passt nicht perfekt in 60 Punkte. Daher ist dort eine gewisse Flexibilität erforderlich (und auch für das 16-Gon, wenn es enthalten wäre.) Das Bild sieht wie das folgende aus, nur in Weiß und Grau mit Die beiden gelben Kreise sind ausschließlich Formen mit einem Vielfachen von 5 Seiten gewidmet. Siehe http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribed_in_a_Circle_240px.giffür meine bevorzugte Pentagon-Zeichenmethode. Der unruhige Winkel soll vertikale Linien vermeiden, da das Programm keine unendlichen Steigungen verarbeiten kann.

Bildbeschreibung hier eingeben

Der Benutzer gibt eine Zahl dfür die Anzahl der erforderlichen Seiten ein. Das Programm schlägt im Array den Index des ersten der beiden Punkte nach (der nächste Punkt ist im Uhrzeigersinn 60 / d entfernt).

Das Programm durchläuft dann den Prozess des Zeichnens eines Kreises, der auf dem zweiten Punkt zentriert ist, der durch den ersten verläuft, und des Berechnens des neuen Schnittpunkts, um sich um den Hauptkreis herum fortzubewegen. Die Konstruktionskreise werden blau und das gewünschte Polygon rot gezeichnet. Die endgültigen Bilder sehen so aus.

Ich bin sehr zufrieden mit ihnen. BBC Basic führt die Berechnungen genau genug durch. Es ist jedoch offensichtlich (besonders bei 15 und 60 Seiten), dass BBC Basic dazu neigt, Kreise mit einem etwas kleineren Radius zu zeichnen, als es sollte.

Bildbeschreibung hier eingeben

Level River St
quelle
1
Ein Trick, den ich dabei übersehen habe, ist, dass die 45-Grad-Linie den Hauptkreis direkt neben zwei Kreisen schneidet, die zum Konstruieren des 24-Gon und 40-Gon verwendet werden können, beides Faktoren von 120. Es gibt zwei Faktoren von 60 (20 und 30) fehlt, was einen weiteren Kreis in der Vorkonstruktion erfordern würde, um die zwei fehlenden Ecken des Fünfecks zu definieren und die Differenzen 1 / 5-1 / 6 = 1/30 und 1 / 5-1 / 4 = 1/20 zu ergeben . Ich glaube jedoch nicht, dass ich meine Antwort im Moment aktualisieren werde. BTW, Danke für den Bonus @Martin!
Level River St
16

Mathematica, 2 3 4 Polygone, 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}}]

Zufällige Aufzählungszeichen:

  • Die Eingabe erfolgt über die Eingabeaufforderung.
  • Ich unterstütze derzeit die Eingänge 3 , 4 , 6 , 8 .
  • Aus Ihren Optionen habe ich die folgenden Darstellungsstile ausgewählt:
    • Volle Kreise.
    • Linien von Endpunkt zu Endpunkt, es sei denn, ein relevanter Schnittpunkt liegt außerhalb. In diesem Fall codiere ich die Ausdehnung fest.
    • Keine Punkte.
    • Arbeiten sind schwarz, Polygone sind rot - nicht aus ästhetischen Gründen, sondern aus Golfgründen.
  • Zwischen den Polygonen gibt es einige ernsthafte Code-Duplikationen. Ich denke, irgendwann mache ich einfach eine einzige Konstruktion für alle, zähle alle Linien und Punkte und Kreise auf dem Weg auf und reduziere dann einfach die Switch, um die relevanten Kreise und Linien für jede Konstruktion auszuwählen. Auf diese Weise konnte ich viele Primitive zwischen ihnen wiederverwenden.
  • Der Code enthält viele Boilerplate-Funktionen, die alle relevanten Schnittpunkte bestimmen und Kreise aus zwei Punkten erstellen.
  • Wenn dies geschehen ist, werde ich in Zukunft weitere Polygone hinzufügen.

Hier ist der ungolfed Code:

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

Und hier sind die Ausgaben:

Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben

Martin Ender
quelle
Ich frage mich nur, ob es kürzer wäre, die roten und schwarzen Linien und Kreise für jeden Eingabetyp fest zu codieren und zu zeichnen.
Optimierer
@Optimizer Ich nehme an, dass für größere n genaue Ausdrücke für die Punkte wahrscheinlich auch ziemlich lang werden. Ich denke, wenn ich mehr Polygone hinzufüge, ist es irgendwann sinnvoll, eine einzige Konstruktion für alle zu erstellen und dann einfach die relevanten Kreise und Linien in der Liste auszuwählen Switch. Das würde mir wahrscheinlich erlauben, viel mehr Kreislinien und Punkte wiederzuverwenden.
Martin Ender
In diesem Fall habe ich eine kürzere Möglichkeit, das Achteck zu konstruieren, aber ich bin nicht sicher, wie ich es Ihnen zeigen soll ...
stolzer Haskeller
@proudhaskeller Ist es noch kürzer, wenn Sie bedenken, dass die ersten 5 Zeilen der Konstruktion tatsächlich wegfallen könnten, indem Sie Code aus dem Quadrat wiederverwenden, und dass diese Art der Konstruktion möglicherweise verallgemeinert werden könnte, um ein beliebiges 2n-Gon aus einem n-Gon zu konstruieren ? (Beide Dinge habe ich im Sinn, um dies zu verbessern.) Wenn ja ... ähm ... würde eine rigorose Beschreibung mit benannten Punkten wie diesem funktionieren.
Martin Ender
@proudhaskeller Du könntest es stattdessen selbst posten, bevor das Kopfgeld abläuft. ;)
Martin Ender