สร้าง n-gons ด้วยไม้บรรทัดและเข็มทิศ


16

ภารกิจคือการวาดรูปหลายเหลี่ยมปกติของด้าน n โดยใช้เพียงเข็มทิศและไม้บรรทัดที่ไม่มีเครื่องหมาย

อินพุต (n) เป็นหนึ่งใน 10 หมายเลขต่อไปนี้: 3, 4, 5, 6, 8, 10, 12, 15, 16, 17

วิธีการ : เนื่องจากคุณมีไม้บรรทัดและเข็มทิศเท่านั้นคุณจึงสามารถวาดจุดเส้นและวงกลมได้เท่านั้น

บรรทัดสามารถวาดได้เท่านั้น:

  • ผ่านสองจุดที่มีอยู่

วงกลมสามารถวาดได้เท่านั้น:

  • มีจุดเดียวเป็นศูนย์กลางและมีเส้นรอบวงของมันผ่านจุดที่สอง

จุดสามารถวาดได้เท่านั้น:

  • ที่จุดตัดของสองบรรทัด

  • ที่จุดตัดของเส้นตรงและวงกลม

  • ที่จุดตัดของวงกลมสองวง

  • ที่จุดเริ่มต้นเมื่อคุณอาจวาด 2 คะแนนเพื่อเริ่มต้น

ผ่านกระบวนการนี้ (และผ่านขั้นตอนนี้เท่านั้น) คุณจะต้องวาดเส้น n ของ n-gon ที่ร้องขอพร้อมกับการทำงานใด ๆ ที่จำเป็นเพื่อไปยังขั้นตอนนั้น

แก้ไข: ตำแหน่งของจุดตัดต้องคำนวณ แต่เส้นและวงกลมอาจถูกวาดด้วยวิธีการใด ๆ ที่ให้ไว้โดยภาษา

เอาท์พุทเป็นภาพของรูปหลายเหลี่ยมปกติด้าน n แสดงการทำงาน

กราฟิกไม่มีข้อ จำกัด เกี่ยวกับขนาดภาพรูปแบบความหนาของเส้นหรือสิ่งอื่นใดที่ไม่ได้กล่าวถึงที่นี่ อย่างไรก็ตามต้องเป็นไปได้ที่จะแยกแยะความแตกต่างของเส้นวงกลมและทางแยกต่าง ๆ ของภาพ นอกจากนี้:

  • เส้น n ที่ประกอบขึ้นเป็นด้าน n-gon ของคุณจะต้องเป็นสีที่แตกต่างจาก 'การทำงาน' ของคุณ (เช่นจุดวงกลมหรือเส้นอื่น ๆ ) และสีที่ต่างออกไปจากพื้นหลังของคุณ
  • การทำงานสามารถออกจากเส้นขอบของพื้นที่วาดรูปยกเว้นจุดซึ่งทั้งหมดต้องอยู่ภายในขอบเขตที่มองเห็นได้ของภาพ
  • วงกลมสามารถเป็นวงกลมเต็มหรือเพียงแค่ส่วนโค้ง (ตราบใดที่มันแสดงจุดตัดที่จำเป็น)
  • บรรทัดไม่มีที่สิ้นสุด (เช่นออกจากพื้นที่วาดภาพ) หรือตัดที่จุดสองจุดที่ผ่าน แก้ไข: บรรทัดอาจถูกวาดที่ความยาวใด ๆ สามารถสร้างคะแนนได้เฉพาะเมื่อเส้นที่วาดวาดตัดกันเท่านั้น
  • จุดสามารถวาดตามที่คุณต้องการรวมถึงไม่ทำเครื่องหมาย

การให้คะแนนคือสองเท่าการส่งจะได้รับ 1 จุดต่ออินพุตที่สนับสนุนสูงสุด 10 คะแนน ในกรณีที่มีการเสมอจำนวนไบต์ที่สั้นที่สุดจะชนะ

จะมีการรับรู้ถึงการส่งที่สามารถสร้าง n-gons ในขั้นตอนที่น้อยที่สุดหรือสามารถสร้าง n-gons นอกช่วงที่กำหนด แต่จะไม่ช่วยให้คะแนนของคุณ

ข้อมูลความเป็นมาจาก Wikipedia


หากคุณอนุญาตให้ตัดบรรทัดที่จุดที่กำหนดโดยนั่นหมายความว่าจุดตัดที่เกี่ยวข้องอาจอยู่นอกเส้นที่ลาก
Martin Ender

เราสามารถใช้ทางลัดเช่นการพล็อตสองบรรทัดเซ็กเมนต์ AB และ BC โดยการพล็อตแถบบรรทัดเดียว ABC ได้หรือไม่หากภาษาของเราให้ข้อมูลนั้น
Martin Ender

1
มันเพียงพอที่จะวาดสิ่งก่อสร้างหรือไม่หรือโปรแกรมต้องคำนวณด้วยเช่นกัน? ตัวอย่างเช่นถ้าฉันต้องการวาดวงกลมที่จุดกำเนิดที่ผ่านจุด (300,400) ฉันสามารถ (รู้ว่ารัศมีคือ 500) ทำCIRCLE 0,0,500หรือฉันต้องทำR=SQRT(300^2+400^2): CIRCLE 0,0,Rอย่างไร (BTW การหาตำแหน่งของจุดตัดน่าจะยากกว่าเส้นและวงกลม)
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
ดร. เบลิซาเรีย

โดยปกติแล้วคุณเรียกว่า "ไม้บรรทัดที่ไม่มีเครื่องหมาย" เป็น "เส้นตรง" ในแง่คณิตศาสตร์เช่นคำพูดของเบลิซาเรียส
justhalf

คำตอบ:


10

บีบีซีเบสิค, 8 รูปหลายเหลี่ยม: 3,4,5,6,8,10,12,15 ข้าง (รวมถึง 60 ด้าน)

ดาวน์โหลดโปรแกรมจำลองที่http://www.bbcbasic.co.uk/bbcwin/download.html

ฉันตัดสินใจที่จะไม่รวม 16 ด้านเพียงเพราะก่อนการก่อสร้างของฉันเริ่มจะค่อนข้างรก ต้องการวงกลมเพิ่มอีก 2 วงและจะต้องมีบรรทัด BTW 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-gon ถ้ารวมอยู่ด้วย) ภาพดูเหมือนภาพด้านล่างสีขาวและสีเทามีเพียง วงกลมสองวงในสีเหลืองนั้นอุทิศให้กับรูปร่างที่มีทวีคูณของ 5 ด้าน ดูhttp://en.wikipedia.org/wiki/Pentagon#mediaviewer/File:Regular_Pentagon_Inscribeed_in_a_Circle_240px.gifสำหรับวิธีการวาดรูปห้าเหลี่ยมที่ฉันต้องการ มุม jaunty คือการหลีกเลี่ยงเส้นแนวตั้งเนื่องจากโปรแกรมไม่สามารถรองรับการไล่ระดับสีแบบไม่ จำกัด

ป้อนคำอธิบายรูปภาพที่นี่

ผู้ใช้ป้อนหมายเลขdตามจำนวนด้านที่ต้องการ โปรแกรมจะค้นหาดัชนีของจุดสองจุดแรกในแถวลำดับถัดไปคือ 60 / d ในทิศทางตามเข็มนาฬิกา

จากนั้นโปรแกรมจะวนซ้ำไปตามกระบวนการของการวาดวงกลมที่มีศูนย์กลางอยู่ที่จุดที่สองซึ่งผ่านรอบแรกและคำนวณจุดตัดใหม่เพื่อเดินวนรอบวงกลมหลัก วงกลมก่อสร้างถูกวาดด้วยสีน้ำเงินและรูปหลายเหลี่ยมที่ต้องการจะถูกวาดด้วยสีแดง ภาพสุดท้ายเป็นแบบนี้

ฉันค่อนข้างพอใจกับพวกเขา BBC Basic ทำการคำนวณอย่างถูกต้องเพียงพอ อย่างไรก็ตามมันชัดเจน (โดยเฉพาะกับ 15 และ 60 ด้าน) ที่ BBC Basic มีแนวโน้มที่จะวาดวงกลมที่มีรัศมีขนาดเล็กกว่าที่ควรจะเป็น

ป้อนคำอธิบายรูปภาพที่นี่


1
เคล็ดลับอย่างหนึ่งที่ฉันพลาดคือการที่เส้น 45 องศาตัดวงกลมหลักข้างสองวงกลมที่สามารถใช้ในการสร้าง 24-gon และ 40-gon, ทั้งสองปัจจัยจาก 120 มีสองปัจจัย 60 (20 และ 30) หายไปซึ่งจะต้องมีอีกหนึ่งวงกลมในการเตรียมการล่วงหน้าเพื่อกำหนดมุมที่หายไปสองส่วนของรูปห้าเหลี่ยมและให้ความแตกต่าง 1 / 5-1 / 6 = 1/30 และ 1 / 5-1 / 4 = 1/20 . อย่างไรก็ตามฉันไม่คิดว่าฉันจะอัปเดตคำตอบของฉันในขณะนี้ BTW ขอบคุณสำหรับโบนัส @Martin!
เลเวลริเวอร์เซนต์

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เพื่อเลือกวงกลมและเส้นที่เกี่ยวข้องสำหรับแต่ละการก่อสร้าง ด้วยวิธีนี้ฉันสามารถใช้สิ่งดั้งเดิมมากมายระหว่างพวกเขา
  • รหัสมีฟังก์ชั่นสำเร็จรูปจำนวนมากซึ่งกำหนดจุดตัดที่เกี่ยวข้องทั้งหมดและสร้างวงกลมจากสองจุด
  • เมื่อถึงตอนนั้นฉันจะเพิ่มรูปหลายเหลี่ยมมากขึ้นในอนาคต

นี่คือรหัส 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}
   }
  ]

และนี่คือผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


เพียงแค่สงสัยว่ามันจะสั้นลงหรือยากที่จะเขียนโค้ดสำหรับเส้นสีแดงและสีดำสำหรับแต่ละอินพุตและวาด
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ฉันคิดว่าสำหรับขนาดใหญ่nการแสดงออกที่แน่นอนสำหรับจุดที่อาจจะกลายเป็นที่ค่อนข้างยาวเกินไป ฉันคิดว่าเมื่อฉันเพิ่มรูปหลายเหลี่ยมมากขึ้นในบางจุดมันจะสมเหตุสมผลในการสร้างหนึ่งเดียวสำหรับพวกเขาทั้งหมดแล้วเลือกวงกลมและเส้นที่เกี่ยวข้องในSwitchผมคิดว่าเมื่อฉันจะเพิ่มรูปหลายเหลี่ยมมากขึ้นในบางจุดก็จะทำให้ความรู้สึกที่จะทำให้หนึ่งเดียวสำหรับการก่อสร้างทั้งหมดของพวกเขาและจากนั้นเพียงแค่เลือกแวดวงที่เกี่ยวข้องและสายในนั่นอาจทำให้ฉันสามารถใช้เส้นและจุดวงกลมอีกครั้งได้มากขึ้น
Martin Ender

ฉันนี่ฉันมีวิธีที่สั้นกว่าในการสร้างรูปแปดเหลี่ยม แต่ฉันไม่แน่ใจว่าจะแสดงให้คุณเห็น ...
ภูมิใจ haskeller

@proudhaskeller มันยังสั้นกว่านี้หรือไม่ถ้าคุณคิดว่า 5 บรรทัดแรกของการก่อสร้างสามารถนำมาใช้ซ้ำเพื่อนำโค้ดจากสแควร์มาใช้ใหม่ได้ ? (ทั้งสองสิ่งนี้ฉันมีความคิดที่จะปรับปรุงสิ่งนี้) ถ้าเป็นเช่นนั้น ... อืมมมม ... ฉันคิดว่าคำอธิบายที่ละเอียดถี่ถ้วนกับชื่อที่ตั้งชื่อแบบนี้จะใช้ได้
Martin Ender

@proudhaskeller คุณสามารถโพสต์ด้วยตัวเองแทนก่อนที่เงินรางวัลจะหมดอายุ ;)
Martin Ender
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.