Bangun n-gon dengan penggaris dan kompas

16

Tugasnya adalah menggambar poligon beraturan dengan hanya menggunakan kompas dan penggaris yang tidak bertanda.

Input (n) adalah salah satu dari 10 angka berikut: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17.

Metode : Karena Anda hanya memiliki penggaris dan kompas, Anda hanya dapat menggambar titik, garis, dan lingkaran.

Garis hanya dapat ditarik:

  • melalui dua poin yang ada.

Lingkaran hanya bisa digambar:

  • dengan satu titik sebagai pusatnya dan dengan perimeternya melewati titik kedua.

Poin hanya dapat ditarik:

  • di persimpangan dua garis,

  • di persimpangan garis dan lingkaran,

  • di persimpangan dua lingkaran,

  • di awal, ketika Anda dapat menggambar 2 poin untuk memulai.

Melalui proses ini (dan hanya melalui proses ini) Anda harus menggambar garis n dari n-gon yang diminta, bersama dengan pekerjaan apa pun yang diperlukan untuk sampai ke tahap itu.

EDIT: Posisi persimpangan harus dihitung, tetapi garis dan lingkaran dapat ditarik dengan cara apa pun yang disediakan oleh bahasa.

Output adalah gambar dari poligon reguler n-sided, menunjukkan kerja.

Secara grafis tidak ada batasan pada ukuran gambar, format, ketebalan garis atau apa pun yang tidak disebutkan di sini. Namun harus dimungkinkan untuk secara visual membedakan garis, lingkaran, dan persimpangan yang berbeda. Selain itu:

  • Garis n yang membentuk sisi n-gon Anda harus memiliki warna yang berbeda dengan 'kerja' Anda (yaitu titik, lingkaran, atau garis lain) dan warna yang berbeda lagi untuk latar belakang Anda.
  • Bekerja dapat meninggalkan batas area gambar, kecuali titik, yang semuanya harus berada dalam batas gambar yang terlihat.
  • Lingkaran bisa berupa lingkaran penuh atau hanya busur (selama itu menunjukkan persimpangan yang diperlukan).
  • Sebuah garis tidak terbatas (yaitu meninggalkan area gambar) atau memotong pada dua titik yang dilaluinya. EDIT: Sebuah garis dapat ditarik panjangnya. Poin hanya dapat dibuat jika garis yang ditarik secara visual memotong.
  • Suatu titik dapat ditarik sesuai keinginan, termasuk tidak menandainya.

Skor dua kali lipat, kiriman mendapat 1 poin per input yang didukungnya, untuk maksimum 10 poin. Dalam hal undian, jumlah byte terpendek menang.

Pengakuan akan diberikan pada kiriman yang dapat membuat n-gon dalam langkah paling sedikit atau mampu membuat n-gon di luar rentang yang diberikan, tetapi itu tidak akan membantu skor Anda.

Info latar belakang dari Wikipedia

jsh
sumber
Jika Anda membiarkan garis terpotong pada titik yang ditentukan olehnya, itu berarti persimpangan yang relevan bisa berada di luar garis yang ditarik.
Martin Ender
Bisakah kita menggunakan cara pintas seperti memplot dua segmen garis AB dan BC dengan memplot satu baris strip ABC, jika bahasa kita menyatakannya?
Martin Ender
1
Apakah cukup untuk menggambar konstruksi, atau apakah program harus menghitungnya juga? Misalnya, jika saya ingin menggambar lingkaran pada titik asal melewati titik (300.400) dapatkah saya (mengetahui radius 500) melakukan CIRCLE 0,0,500atau harus saya lakukan R=SQRT(300^2+400^2): CIRCLE 0,0,R? (BTW mengerjakan posisi persimpangan mungkin lebih sulit daripada garis dan lingkaran.)
Level River St
Dari 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
Biasanya Anda menyebut "penguasa tak bertanda" sebagai "ujung lurus" dalam istilah matematika, seperti kutipan oleh belisarius.
justhalf

Jawaban:

10

BBC Basic, 8 poligon: 3,4,5,6,8,10,12,15 sisi (juga 60 sisi)

Unduh emulator di http://www.bbcbasic.co.uk/bbcwin/download.html

Saya memutuskan untuk tidak memasukkan 16 sisi, hanya karena pra-konstruksi saya semakin berantakan. 2 lingkaran lagi dan satu garis akan dibutuhkan. Sisi BTW 17 memang sangat rumit, dan mungkin akan lebih baik sebagai program terpisah.

Saya mendapat lebih banyak pengembalian karena menambahkan 2 lingkaran pada konstruksi asli saya untuk membuat pentagon, karena ini juga memberi saya akses ke 10,15 dan 60 sisi.

  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

Program ini melakukan pra-konstruksi sebelum meminta input pengguna. Ini cukup untuk mendefinisikan setidaknya 2 titik pada lingkaran utama yang sesuai dengan simpul yang berdekatan dari angka 3,4,5,6,8,10,12,15 atau 60 sisi. Poin disimpan dalam satu set array elemen 99, di mana elemen 0-59 disisihkan untuk titik yang berjarak sama di sekitar keliling. Ini terutama untuk kejelasan, segi delapan tidak pas dengan 60 poin sehingga beberapa fleksibilitas diperlukan di sana (dan juga untuk 16-gon jika disertakan.) Gambar terlihat seperti gambar di bawah ini, putih dan abu-abu, dengan hanya dua lingkaran berwarna kuning secara eksklusif didedikasikan untuk bentuk dengan kelipatan 5 sisi. Lihat http://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribed_in_a_Circle_240px.gifuntuk metode menggambar pentagon pilihan saya. Sudut jaunty adalah untuk menghindari garis vertikal, karena program tidak dapat menangani gradien tak terbatas.

masukkan deskripsi gambar di sini

Pengguna memasukkan angka duntuk jumlah sisi yang diperlukan. Program mencari dalam array indeks yang pertama dari dua titik (yang berikutnya adalah 60 / d jauhnya searah jarum jam.)

Program kemudian loop melalui proses menggambar lingkaran yang berpusat pada titik kedua yang melewati throug yang pertama, dan menghitung persimpangan baru untuk berjalan di lingkaran utama. Lingkaran konstruksi digambar dengan warna biru, dan poligon yang diperlukan digambar dengan warna merah. Gambar akhir terlihat seperti ini.

Saya cukup senang dengan mereka. BBC Basic melakukan perhitungan dengan cukup akurat. Namun jelas (terutama dengan sisi 15 dan 60) bahwa BBC Basic cenderung menggambar lingkaran dengan jari-jari sedikit lebih kecil dari yang seharusnya.

masukkan deskripsi gambar di sini

Level River St
sumber
1
Satu trik yang saya lewatkan dengan ini adalah bahwa garis 45 derajat memotong lingkaran utama tepat di samping dua lingkaran yang dapat digunakan untuk membangun 24-gon dan 40-gon, kedua faktor 120. Ada dua faktor 60 (20 dan 30) hilang, yang akan membutuhkan satu lingkaran lagi dalam prakonstruksi, untuk menentukan dua sudut pentagon yang hilang dan memberikan perbedaan 1 / 5-1 / 6 = 1/30 dan 1 / 5-1 / 4 = 1/20 . Namun saya tidak berpikir saya akan memperbarui jawaban saya saat ini. BTW, Terima kasih atas bonus @Martin!
Level River St
16

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

Poin-poin acak:

  • Input diberikan melalui prompt.
  • Saya saat ini mendukung input 3 , 4 , 6 , 8 .
  • Dari opsi Anda, saya memilih gaya plot berikut:
    • Lingkaran penuh.
    • Baris dari titik ke titik, kecuali jika persimpangan yang relevan terletak di luar, dalam hal ini saya akan meng-hardcode luasnya.
    • Tidak ada poin.
    • Kerjanya hitam, poligon berwarna merah - bukan untuk estetika tetapi untuk alasan golf.
  • Ada beberapa duplikasi kode yang serius di antara poligon. Saya pikir di beberapa titik saya hanya akan melakukan konstruksi tunggal untuk mereka semua, menghitung semua garis dan titik dan lingkaran di sepanjang jalan, dan kemudian hanya mengurangi Switchuntuk memilih lingkaran dan garis yang relevan untuk setiap konstruksi. Dengan begitu saya bisa menggunakan kembali banyak primitif di antara mereka.
  • Kode mengandung banyak fungsi boilerplate yang menentukan semua persimpangan yang relevan, dan membuat lingkaran dari dua titik.
  • Dengan itu, saya akan menambahkan lebih banyak poligon di masa depan.

Berikut adalah kode yang tidak dipisahkan:

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

Dan inilah outputnya:

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Martin Ender
sumber
Hanya bertanya-tanya apakah akan lebih pendek untuk kode keras garis dan lingkaran merah dan hitam untuk setiap jenis input dan menggambar mereka.
Pengoptimal
@ Opptizer Saya kira untuk ekspresi yang lebih besar dan tepat untuk poin mungkin akan menjadi cukup lama juga. Saya pikir ketika saya menambahkan lebih banyak poligon, pada titik tertentu akan masuk akal untuk membuat satu konstruksi tunggal untuk semuanya, dan kemudian cukup pilih lingkaran dan garis yang relevan di Switch. Itu mungkin akan memungkinkan saya untuk menggunakan kembali lebih banyak garis dan titik lingkaran.
Martin Ender
Saya ini, saya memiliki cara yang lebih singkat untuk membangun segi delapan, tapi saya tidak yakin bagaimana menunjukkannya kepada Anda ...
bangga haskeller
@proudhaskeller Apakah masih lebih pendek jika Anda menganggap bahwa 5 baris pertama konstruksi sebenarnya dapat dibuang menggunakan kembali kode dari alun-alun, dan bahwa cara membangun ini berpotensi digeneralisasi untuk membangun 2n-gon dari n-gon ? (Kedua hal itu, ada dalam benakku untuk memperbaiki ini.) Jika demikian ... ummm ... kurasa deskripsi yang tepat dengan poin yang disebutkan seperti ini akan bekerja.
Martin Ender
@proudhaskeller Anda malah dapat mempostingnya sendiri sebelum hadiahnya berakhir. ;)
Martin Ender