কোথায় লেজার যায়?


34

একটি 2-মাত্রিক গ্রিড নিন এবং আয়না উপস্থাপনের জন্য এটিতে কয়েকটি লাইন বিভাগগুলি আঁকুন। এখন তাত্ত্বিক লেজার স্থাপনের জন্য একটি বিন্দু এবং নির্দেশক দিকটি নির্ধারণ করার জন্য একটি কোণ চয়ন করুন। প্রশ্নটি হ'ল: যদি আপনি কিছু নির্দিষ্ট দূরত্বের জন্য লেজার বিম পথ অনুসরণ করেন তবে আপনি কোন সমন্বয় বিন্দুতে রয়েছেন?

উদাহরণ:

লেজার উদাহরণ

এই ছবিটি সালে L, লেজার অবস্থান হয় tএটা কোণ (ধনাত্মক X অক্ষ থেকে পরিমাপ), হয় M1, M2এবং M3সব লাইন বিভাগটির আয়না, এবং Eপরে লেজার মরীচি পথে বিন্দু D = d1 + d2 + d3 + d4ইউনিট, থেকে শুরু L

লক্ষ্য

সবচেয়ে কম প্রোগ্রাম (বাইটে) যে আউটপুট লিখুন Eদেওয়া L, t, D, এবং একটি আয়না তালিকা।
( বাইট গণনা করার জন্য http://mothereff.in/byte-counter ব্যবহার করুন ))

ছক পূরণ করা

ইনপুট স্ট্যান্ডিন থেকে ফর্ম্যাটে আসবে:

Lx Ly t D M1x1 M1y1 M1x2 M1y2 M2x1 M2y1 M2x2 M2y2 ...
  • সমস্ত মান ভাসমান করা হবে এই Regex মিলে পয়েন্ট: [-+]?[0-9]*\.?[0-9]+
  • প্রতিটি সংখ্যার মাঝে সর্বদা এক স্থান থাকে।
  • ইনপুট চারপাশে উদ্ধৃতি প্রয়োজন অনুমোদিত।
  • tডিগ্রীতে হয়, তবে প্রয়োজনীয় [0, 360)পরিসরে হয় না। (আপনি যদি পছন্দ করেন তবে এর পরিবর্তে আপনি রেডিয়ান ব্যবহার করতে পারেন, কেবল আপনার উত্তরে তাই বলুন))
  • Dনেতিবাচক হতে পারে, কার্যকরভাবে লেজার 180 ডিগ্রি ঘোরানো। D0 হতে পারে।
  • নির্বিচারে অনেক আয়না থাকতে পারে (কিছুই নয়)।
  • আয়নাগুলির ক্রমের বিষয়টি বিবেচনা করা উচিত নয়।
  • আপনি ধরে নিতে পারেন ইনপুটটি 4 টি সংখ্যার গুণমানে আসবে। যেমন Lx Ly tবা Lx Ly t D M1x1অবৈধ এবং পরীক্ষা করা হবে না। কোনও ইনপুটও অবৈধ।

উপরের লেআউটটি ইনপুট হতে পারে:

1 1 430 17 4.8 6.3 6.2 5.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3

(নোট করুন যে চিত্রটি মুক্ত হাতে আঁকা হয়েছিল এবং এই মানগুলি কেবল আনুমানিক are মার্টিন বাটনার এর ইনপুট মানগুলি

1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3

স্কেচের সাথে মেলে না তবে তারা আরও সংঘর্ষ দেবে))

আউটপুট ফরমেট

আউটপুট ফর্ম্যাটে stdout যেতে হবে:

Ex Ey

এগুলি ভাসমানও এবং ঘনিষ্ঠ আকারেও হতে পারে।

নোট

  • আয়না একে অপরকে ছেদ করতে পারে।
  • আয়না উভয় পক্ষই প্রতিফলিত হয়।
  • মরীচি একই আয়নায় বহুবার আঘাত করতে পারে।
  • মরীচি চিরকাল চলে।

অপরিজ্ঞাত মামলা

আপনি ধরে নিতে পারেন যে ক্ষেত্রে

  • লেজারটি মিরর লাইন বিভাগে শুরু হয়
  • লেজার মরীচিটি একটি আয়নাটির শেষ প্রান্তকে আঘাত করে
  • লেজার মরীচিটি দুটি আয়নাগুলির মধ্যে ছেদ করে

অপরিজ্ঞাত এবং পরীক্ষা করা হবে না। ত্রুটি নিক্ষেপ সহ এগুলি ঘটলে আপনার প্রোগ্রামটি কিছু করতে পারে।

বোনাস

কেবল মজাদার জন্য, আমি সর্বোচ্চ ভোটগ্রহণ জমা দেওয়ার জন্য 200 বন্টি পয়েন্ট দেব যা সমস্যার গ্রাফিকাল প্রতিনিধিত্ব করে (আপনি এমনকি একটি ইন্টারেক্টিভ স্ক্রিপ্টও লিখতে পারেন)। এই বোনাস জমা দেওয়ার জন্য গল্ফ করার দরকার নেই এবং কীভাবে ইনপুট এবং আউটপুট পরিচালনা করা হয় তার সাথে সামঞ্জস্য হতে পারে। এগুলি প্রকৃত গল্ফযুক্ত জমাগুলি থেকে পৃথক তবে উভয়কে একই উত্তরে জমা দেওয়া উচিত

দ্রষ্টব্য: কেবলমাত্র একটি বোনাস উত্তর জমা দেওয়া ভাল, আপনি গ্রহণযোগ্য উত্তর হতে পারবেন না। গ্রহণযোগ্য হতে আপনাকে অবশ্যই অবশ্যই ইনপুট / আউটপুট স্পেক অনুসরণ করতে হবে (যেমন আউটপুটটিতে কেবল Ex Eyচিত্রগুলি জড়িত না) এবং সংক্ষিপ্ততম হতে হবে।


1
একটি প্রশ্নে গল্ফযুক্ত এবং নিরবচ্ছিন্ন সাবমিশন থাকা ইমো হ'ল একটি বিশাল গণ্ডগোল হয়ে উঠছে। 200 উদ্যানের পয়েন্টগুলি এত আকর্ষণীয় যে গল্ফিংটি গৌণ বিন্দুতে পরিণত হয়।
হাওয়ার্ড

1
@ পিটারটেলর আপনি প্রসঙ্গের বাইরে আমাকে উদ্ধৃত করছেন। দু'টি জমা সম্পূর্ণ স্বতন্ত্র হলেও একই পোস্টে অন্তর্ভুক্ত হওয়ায় ওপি'র বিভাগের বোনাসের উত্তরগুলি পড়েছি, যদি উভয়ের চেষ্টা করা হয় (যার অর্থ কেবল পপকন উত্তরটিও ঠিক থাকবে)। যাইহোক, এগুলি আপনার ভোট এবং আপনি কীভাবে এগুলি ব্যবহার করেন তা আপনার উপর নির্ভর করে এবং আমি সম্ভবত কোনও সময়ে কোনও গল্ফযুক্ত সংস্করণ যুক্ত করব। তবে আমি অনুমান করি যে ওপি সে উদ্দেশ্য করে কিনা তা পরিষ্কার করে দিতে পারে, পপকন-কেবলমাত্র উত্তর বৈধ হবে কি না।
মার্টিন এন্ডার

1
@ মার্টিনব্যাটনার, " বোনাস " এর অর্থ " অতিরিক্ত, অতিরিক্ত "। এটি মূল চ্যালেঞ্জের অংশ নয়। এবং প্রশ্নের কেবল একটি ট্যাগ রয়েছে, কোড-গল্ফ
পিটার টেলর

2
@ পিটারটেলর মার্টিনবাটনার ঠিক আছে। প্রশ্নের শুধুমাত্র বোনাস অংশ উত্তর দেওয়া ঠিক আছে। আমি বলেছিলাম যে বোনাসের উত্তরগুলি অ-গল্ফ এবং আই / ও-র সাথে হালকা হতে পারে এবং বর্তমানের সমস্ত বোনাস জমা আমার কাছে দুর্দান্ত দেখাচ্ছে। সবচেয়ে কম জমা যে নেই ঠিক বৈশিষ্ট অনুসরণ গৃহীত উত্তর হতে হবে। বর্তমানে কোনও জমা দেওয়া হচ্ছে না, তবে এটি আমার কাছে ঠিক আছে।
ক্যালভিনের শখ 14

1
সেক্ষেত্রে " বোনাস " হ'ল ভুল শব্দটি ব্যবহার করা এবং আপনি লোককে নিয়ম ভাঙতে বলছেন , যা সহায়ক নয়।
পিটার টেলর 15

উত্তর:


39

রুবি, 327 বাইট

(নীচে স্ক্রোল)

গণিত, বোনাস উত্তর

এখানে চিত্র বর্ণনা লিখুন

আমি এখনই কেবল গ্রাফিকাল জমা দেওয়ার জন্য যাচ্ছি। আমি পরে এটি রুবিকে পোর্ট করতে এবং যদি আমার মনে হয় তবে এটি গল্ফ করে।

(* This function tests for an intersection between the laser beam
   and a mirror. r contains the end-points of the laser, s contains
   the end-points of the mirror. *)
intersect[r_, s_] := Module[
   {lr, dr, nr, ds, ns, \[Lambda]},
   (* Get a unit vector in the direction of the beam *)
   dr = r[[2]] - r[[1]];
   lr = Norm@dr;
   dr /= lr;
   (* Get a normal to that vector *)
   nr = {dr[[2]], -dr[[1]]};

   (* The sign of dot product in here depends on whether that end-point
      of the mirror is to the left or to the right of the array. Return 
      infinity if both ends of s are on the same side of the beam. *)
   If[Apply[Times, (s - {r[[1]], r[[1]]}).nr] > 0, 
    Return[\[Infinity]]];

   (* Get a unit vector along the mirror. *)
   ds = s[[2]] - s[[1]];
   ds /= Norm@ds;
   (* And a normal to that. *)
   ns = {ds[[2]], -ds[[1]]};
   (* We can write the beam as p + λ*dr and mirror as q + μ*ds,
      where λ and μ are real parameters. If we set those equal and
      solve for λ we get the following equation. Since dr is a unit 
      vector, λ is also the distance to the intersection. *)
   \[Lambda] = ns.(r[[1]] - s[[1]])/nr.ds;
   (* Make sure that the intersection is before the end of the beam.
      This check could actually be slightly simpler (see Ruby version). *)
   If[\[Lambda] != 0 && lr/\[Lambda] < 1, Infinity, \[Lambda]]
   ];

(* This function actually does the simulation and generates the plot. *)
plotLaser[L_, t_, distance_, M_] := Module[
   {coords, plotRange, points, e, lastSegment, dLeft, \[Lambda], m, p,
     d, md, mn, segments, frames, durations},

   (* This will contain all the intersections along the way, as well
      as the starting point. *)
   points = {L};
   (* The tentative end point. *)
   e = L + distance {Cos@t, Sin@t};
   (* This will always be the currently last segment for which we need
      to check for intersections. *)
   lastSegment = {L, e};
   (* Keep track of the remaining beam length. *)
   dLeft = distance;

   While[True,
    (* Use the above function to find intersections with all mirrors
       and pick the first one (we add a small tolerance to avoid
       intersections with the most recent mirror). *)
    {\[Lambda], m} = 
     DeleteCases[
       SortBy[{intersect[lastSegment, #], #} & /@ M, #[[1]] &], 
       i_ /; i[[1]] < 1*^-10][[1]];
    (* If no intersection was found, we're done. *)
    If[\[Lambda] == \[Infinity], Break[]];
    (* Reduce remaining beam length. *)
    dLeft -= \[Lambda];
    (* The following lines reflect the beam at the mirror and add
       the intersection to our list of points. We also update the
       end-point and the last segment. *)
    p = lastSegment[[1]];
    d = -Subtract @@ lastSegment;
    d /= Norm@d;
    md = -Subtract @@ m;
    md /= Norm@md;
    mn = {md[[2]], -md[[1]]};
    AppendTo[points, p + \[Lambda]*d];
    d = -d + 2*(d - d.mn*mn);
    e = Last@points + dLeft*d;
    lastSegment = {Last@points, e};
    ];
   (* Get a list of all points in the set up so we can determine
      the plot range. *)
   coords = Transpose@Join[Flatten[M, 1], {L, e}];
   (* Turn the list of points into a list of segments. *)
   segments = Partition[points, 2, 1];
   (* For each prefix of that list, generate a frame. *)
   frames = Map[
     Graphics[
       {Line /@ M,
        Red,
        Point@L,
        Line /@ segments[[1 ;; #]]},
       PlotRange -> {
         {Min@coords[[1]] - 1, Max@coords[[1]] + 1},
         {Min@coords[[2]] - 1, Max@coords[[2]] + 1}
         }
       ] &,
     Range@Length@segments];
   (* Generate the initial frame, without any segments. *)
   PrependTo[frames,
    Graphics[
     {Line /@ M,
      Red,
      Point@L},
     PlotRange -> {
       {Min@coords[[1]] - 1, Max@coords[[1]] + 1},
       {Min@coords[[2]] - 1, Max@coords[[2]] + 1}
       }
     ]
    ];
   (* Generate the final frame including lastSegment. *)
   AppendTo[frames,
    Graphics[
     {Line /@ M,
      Red,
      Point@L,
      Line /@ segments,
      Line[lastSegment],
      Point@e},
     PlotRange -> {
       {Min@coords[[1]] - 1, Max@coords[[1]] + 1},
       {Min@coords[[2]] - 1, Max@coords[[2]] + 1}
       }
     ]];

   (*Uncomment to only view the final state *)
   (*Last@frames*)

   (* Export the frames as a GIF. *)
   durations = ConstantArray[0.1, Length@frames];
   durations[[-1]] = 1;
   Export["hardcoded/path/to/laser.gif", frames, 
    "GIF", {"DisplayDurations" -> durations, ImageSize -> 600}];

   (* Generate a Mathematica animation form the frame. *)
   ListAnimate@frames
   ];

আপনি এটি পছন্দ করতে পারেন

plotLaser[{1, 1}, 7.50492, 95, {
  {{4.8, 5.3}, {6.2, 4.3}}, {{1.5, 4.8}, {3.5, 6}}, {{6.3, 1.8}, {7.1, 3}}, 
  {{5, 1}, {4, 3}}, {{7, 6}, {5, 6.1}}, {{8.5, 2.965}, {8.4, 2}}, 
  {{8.5, 3.035}, {8.6, 4}}, {{8.4, 2}, {10.5, 3}}, {{8.6, 4}, {10.5, 3}}
}]

এটি আপনাকে গাণিতিকায় একটি অ্যানিমেশন দেবে এবং একটি জিআইএফও রফতানি করবে (এই ইনপুটটির শীর্ষে একটি)। কিছুটা আকর্ষণীয় করে তুলতে আমি এর জন্য ওপিগুলির উদাহরণটি সামান্য বাড়িয়েছি।

আরও উদাহরণ

কিছুটা নমনকারী দেয়ালযুক্ত একটি টিউব তবে একটি বদ্ধ প্রান্ত:

plotLaser[{0, 0}, 1.51, 200, {
  {{0, 1}, {20, 1.1}},
  {{0, -1}, {20, -1.1}},
  {{20, 1.1}, {20, -1.1}}
}]

এখানে চিত্র বর্ণনা লিখুন

একটি সমান্তরাল ত্রিভুজ এবং একটি প্রাথমিক দিক যা প্রায় কোনও দিকের সমান্তরাল।

plotLaser[{-1, 0}, Pi/3 + .01, 200, {
  {{-2.5, 5 Sqrt[3]/6}, {2.5, 5 Sqrt[3]/6}},
  {{0, -5 Sqrt[3]/3}, {-2.5, 5 Sqrt[3]/6}},
  {{0, -5 Sqrt[3]/3}, {2.5, 5 Sqrt[3]/6}}
}]

এখানে চিত্র বর্ণনা লিখুন

আরো একটা:

plotLaser[
 {0, 10}, -Pi/2, 145,
 {
   {{-1, 1}, {1, -1}}, {{4.5, -1}, {7.5, Sqrt[3] - 1}},
   {{11, 10}, {13, 10}}, {{16.5, Sqrt[3] - 1}, {19.5, -1}},
   {{23, -1}, {25, 1}}, {{23, 6}, {25, 4}}, {{18, 6}, {20, 4}}, {{18, 9}, {20, 11}},
   {{31, 9}, {31.01, 11}}, {{24.5, 10.01}, {25.52, 11.01}}, {{31, 4}, {31, 6}}, {{25, 4.6}, {26, 5.6}}, {{24.5, 0.5}, {25.5, -0.5}}, 
   {{31, -1}, {33, 1}}, {{31, 9}, {33, 11}}, {{38, 10.5}, {38.45, 9}}
 }
]

এখানে চিত্র বর্ণনা লিখুন

রুবি, গল্ফযুক্ত উত্তর

x,y,t,p,*m=gets.split.map &:to_f
u=q=Math.cos t
v=r=Math.sin t
loop{k=i=p
u=x+q*p
v=y+r*p
m.each_slice(4){|a,b,c,d|((a-u)*r-(b-v)*q)*((c-u)*r-(d-v)*q)>0?next: g=c-a
h=d-b
l=(h*(x-a)-g*(y-b))/(r*g-q*h)
f=(g*g+h*h)**0.5
t,k,i=g/f,h/f,l if l.abs>1e-9&&l/i<1}
i==p ?abort([u,v]*' '): p-=i
x+=q*i
y+=r*i
n=q*k-r*t
q-=2*n*k
r+=2*n*t}

এটি মূলত রুবির ম্যাথমেটিকা ​​সমাধানের সরাসরি অনুবাদ, আরও কিছু গল্ফ করে এবং নিশ্চিত করে যে এটি I / O শর্ত পূরণ করে।


প্রথম উদাহরণের শেষে আপনার কাছে কীভাবে লেজারটি আয়না ত্রিভুজটি অতিক্রম করবে?
এজেম্যানসফিল্ড

1
@ এজেম্যান্সফিল্ড ত্রিভুজটিতে একটি ছোট গর্ত রয়েছে, যা আপনি অ্যানিমেশনের শুরুতে দেখতে পাবেন।
মার্টিন ইন্ডার

এটি কীভাবে কাজ করে তা ব্যাখ্যা করে কোনও অনুচ্ছেদ লিখতে পারলে দুর্দান্ত হবে।
জেফএসবি

@ জেফএসবি আমি এখন গণিত কোড নথিভুক্ত করেছি। অস্পষ্ট পরিবর্তনশীল নাম এবং প্লট না করেই রুবি সংস্করণটি ঠিক একই কাজ করে।
মার্টিন ইন্ডার

@ মার্টিনবাটনার ধন্যবাদ অন্যান্য ব্যক্তিরা এটি কী করে তা দেখতে আকর্ষণীয়। আপনি কী শেষ হওয়ার আগেই বুঝতে পেরেছিলেন যে আপনি শেষ আয়নটি বাদ দিয়েছিলেন? আমি তা করিনি, তবে আমি খুব শীঘ্রই এটি বের করেছিলাম। আমি আপনার কোডটিতে খুব অল্প সংখ্যক লক্ষ্য করেছি এবং সে কারণেই আমি এটি কীভাবে কাজ করে তা দেখতে বলেছি।
জেফএসবি

18

পাইথন 3 (421 সি 390 সি, 366C)

builtin.complex2 ডি ভেক্টর হিসাবে ব্যবহার করুন । সুতরাং

dot = lambda a, b: (a.conjugate() * b).real
cross = lambda a, b: (a.conjugate() * b).imag

368 সি রুবি সলিউশনটি বীট করার জন্য, আমি একটি আয়না বরাবর পয়েন্ট প্রতিবিম্ব গণনা করার জন্য একটি বেশ কমপ্যাক্ট পদ্ধতি পেয়েছি। আরও অক্ষর হ্রাস করতে কিছু জটিল বীজগণিতও ব্যবহার করেছেন। এগুলি সহজেই বর্ণহীন কোডে পাওয়া যাবে।

গল্ফ সংস্করণ এখানে।

C=lambda a,b:(abs(a)**2/a*b).imag
J=1j
x,y,r,d,*a=map(float,input().split())
p=x+y*J
q=p+d*2.718281828459045**(r*J)
M=[]
while a:x,y,z,w,*a=a;M+=[(x+y*J,z-x+w*J-y*J)]
def T(m):x,y=m;d=C(y,r)+1e-9;t=C(y,x-p)/d;s=C(r,x-p)/d;return[1,t][(1e-6<t<1)*(0<s<1)]
while 1:
 r=q-p;m=f,g=min(M,key=T)
 if T(m)==1:break
 p+=r*T(m);q=(q/g-f/g).conjugate()*g+f
print(q.real,q.imag)

Ungolfed

# cross product of two vector
# abs(a)**2 / a == a.conjugate()
cross = lambda a, b: (abs(a)**2 / a * b).imag
# Parse input
x, y, angle, distance, *rest = map(float, input().split())
start = x + y * 1j
# e = 2.718281828459045
# Using formula: e**(r*j) == cos(r) + sin(r) * j
end = start + distance * 2.718281828459045 ** (angle * 1j)
mirrors = []
while rest:
    x1, y1, x2, y2, *rest = rest
    # Store end point and direction vector for this mirror
    mirrors.append((x1 + y1 * 1j, (x2 - x1) + (y2 - y1) * 1j))

def find_cross(mirror):
    # a: one end of mirror
    # s: direction vector of mirror
    a, s = mirror
    # Solve (t, r) for equation: start + t * end == a + r * s
    d = cross(s, end - start) + 1e-9 # offset hack to "avoid" dividing by zero
    t = cross(s, a - start) / d
    r = cross(end - start, a - start) / d
    return t if 1e-6 < t < 1 and 0 < r < 1 else 1

def reflect(p, mirror):
    a, s = mirror
    # Calculate reflection point:
    #  1. Project r = p - a onto a coordinate system that use s as x axis, as r1.
    #  2. Take r1's conjugate as r2.
    #  3. Recover r2 to original coordinate system as r3
    #  4. r3 + a is the final result
    #
    # So we got conjugate((p - a) * conjugate(s)) / conjugate(s) + a
    # which can be reduced to conjugate((p - a) / s) * s + a
    return ((p - a) / s).conjugate() * s + a

while 1:
    mirror = min(mirrors, key=find_cross)
    if find_cross(mirror) == 1:
        break
    start += (end - start) * find_cross(mirror)
    end = reflect(end, mirror)
print(end.real, end.imag)

বোনাস: এইচটিএমএল, কফিস্ক্রিপ্ট, রিয়েলটাইম সামঞ্জস্য এবং গণনা

এটি হ'ল আপনি যে কোনও শেষ পয়েন্টগুলি (বা লেজার, মিরো) টেনে আনুন, তারপরে ট্র্যাকটি রেন্ডার করা হবে। এটি দুটি ধরণের ইনপুটকে সমর্থন করে, একটি যা প্রশ্নে বর্ণিত এবং একটি যা @ মার্টিন বাটনার ব্যবহার করে।

স্কেলিংটি স্বয়ংক্রিয়ভাবেও সামঞ্জস্য হয়।

আপাতত এটিতে অ্যানিমেশন নেই। আমি পরে এটি উন্নত করব। তবে, সাদা পয়েন্টগুলি টেনে নিয়ে যাওয়া এবং আপনি অন্য ধরণের অ্যানিমেশন দেখতে পাচ্ছেন। অনলাইনে এটি এখানে চেষ্টা করে দেখুন , মজার কথা!

পুরো প্রকল্পটি এখানে পাওয়া যাবে

মামলা 1 কেস 2

হালনাগাদ

এখানে আমি একটি আকর্ষণীয় কেস সরবরাহ করি:

0 0.6 -0.0002 500.0 0.980785280403 -0.195090322016 1.0 0.0 1.0 0.0 0.980785280403 0.195090322016 0.980785280403 0.195090322016 0.923879532511 0.382683432365 0.923879532511 0.382683432365 0.831469612303 0.55557023302 0.831469612303 0.55557023302 0.707106781187 0.707106781187 0.707106781187 0.707106781187 0.55557023302 0.831469612303 0.55557023302 0.831469612303 0.382683432365 0.923879532511 0.382683432365 0.923879532511 0.195090322016 0.980785280403 0.195090322016 0.980785280403 6.12323399574e-17 1.0 6.12323399574e-17 1.0 -0.195090322016 0.980785280403 -0.195090322016 0.980785280403 -0.382683432365 0.923879532511 -0.382683432365 0.923879532511 -0.55557023302 0.831469612303 -0.55557023302 0.831469612303 -0.707106781187 0.707106781187 -0.707106781187 0.707106781187 -0.831469612303 0.55557023302 -0.831469612303 0.55557023302 -0.923879532511 0.382683432365 -0.923879532511 0.382683432365 -0.980785280403 0.195090322016 -0.980785280403 0.195090322016 -1.0 1.22464679915e-16 -1.0 1.22464679915e-16 -0.980785280403 -0.195090322016 -0.980785280403 -0.195090322016 -0.923879532511 -0.382683432365 -0.923879532511 -0.382683432365 -0.831469612303 -0.55557023302 -0.831469612303 -0.55557023302 -0.707106781187 -0.707106781187 -0.707106781187 -0.707106781187 -0.55557023302 -0.831469612303 -0.55557023302 -0.831469612303 -0.382683432365 -0.923879532511 -0.382683432365 -0.923879532511 -0.195090322016 -0.980785280403 -0.195090322016 -0.980785280403 -1.83697019872e-16 -1.0 -1.83697019872e-16 -1.0 0.195090322016 -0.980785280403 0.195090322016 -0.980785280403 0.382683432365 -0.923879532511 0.382683432365 -0.923879532511 0.55557023302 -0.831469612303 0.55557023302 -0.831469612303 0.707106781187 -0.707106781187 0.707106781187 -0.707106781187 0.831469612303 -0.55557023302 0.831469612303 -0.55557023302 0.923879532511 -0.382683432365 0.923879532511 -0.382683432365 0.980785280403 -0.195090322016

এবং ফলাফল: বৃত্ত


-1 ইনপুট বা আউটপুট জন্য অনুমান পূরণ করে না।
পিটার টেলর

@ রে বোনাস উত্তর হিসাবে এটি ঠিক আছে। কোড-গল্ফ উত্তর হয়ে উঠতে কেবল ঠিক এটি অবশ্যই মেনে চলা উচিত।
ক্যালভিনের শখ 14

@ পিটারটেলর মিট এখনই আলোচনা।
রায়

এটি সত্যিই দুর্দান্ত আপনি কীভাবে আয়নাগুলিকে চারপাশে সরিয়ে নিতে পারেন! তোমার আমার প্রথম +1 ভোট।
জেফএসবি

17

এইচটিএমএল জাভাস্ক্রিপ্ট, 10.543, 947 889

আমি একটি বাগ স্থির করেছি এবং নিশ্চিত করেছি আউটপুটটি প্রশ্নটির সাথে মিলছে। নীচের ওয়েবপৃষ্ঠায় গল্ফযুক্ত সংস্করণ এবং গ্রাফিকাল বোনাস সংস্করণ রয়েছে। আমি @ রায়ের দ্বারা নির্দেশিত একটি বাগও ঠিক করেছি যা 58 টি অক্ষর সংরক্ষণ করেছে। (ধন্যবাদ রে।) আপনি একটি জাভাস্ক্রিপ্ট কনসোলে গল্ফ কোডটি চালাতে পারেন। (এখন আমি একটি 2 মেগাওয়াট সবুজ লেজার ব্যবহার করছি))

গল্ফ কোড

a=prompt().split(" ").map(Number);M=Math,Mc=M.cos,Ms=M.sin,P=M.PI,T=2*P,t=true;l=new S(a[0],a[1],a[0]+a[3]*Mc(a[2]),a[1]+a[3]*Ms(a[2]));m=[];for(i=4;i<a.length;)m.push(new S(a[i++],a[i++],a[i++],a[i++]));f=-1;for(;;){var h=!t,d,x,y,n,r={};for(i=0;i<m.length;i++)if(i!=f)if(I(l,m[i],r))if(!h||r.d<d){h=t;d=r.d;x=r.x;y=r.y;n=i}if(h){l.a=x;l.b=y;l.e-=d;l.f=2*(m[f=n].f+P/2)-(l.f+P);l.c=l.a+l.e*Mc(l.f);l.d=l.b+l.e*Ms(l.f);}else break;}alert(l.c+" "+l.d);function S(a,b,c,d){this.a=a;this.b=b;this.c=c;this.d=d;this.e=D(a,b,c,d);this.f=M.atan2(d-b,c-a)}function D(a,b,c,d){return M.sqrt((a-c)*(a-c)+(b-d)*(b-d))}function I(l,m,r){A=l.a-l.c,B=l.b-l.d,C=m.a-m.c,L=m.b-m.d,E=l.a*l.d-l.b*l.c,F=m.a*m.d-m.b*m.c,G=A*L-B*C;if(!G)return!t;r.x=(E*C-A*F)/G;r.y=(E*L-B*F)/G;H=r.d=D(l.a,l.b,r.x,r.y),O=D(l.c,l.d,r.x,r.y),J=D(m.a,m.b,r.x,r.y),K=D(m.c,m.d,r.x,r.y);return(H<l.e)&&(O<l.e)&&(J<m.e)&&(K<m.e);} 

ইনপুট

1 1 7.50492 17 4.8 6.3 6.2 5.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3

আউটপুট

14.743305098514739 3.759749038188634


আপনি এটি এখানে পরীক্ষা করতে পারেন: http://goo.gl/wKgIKD

এখানে চিত্র বর্ণনা লিখুন

ব্যাখ্যা

ওয়েবপৃষ্ঠায় কোডটি মন্তব্য করা হয়েছে। মূলত আমি লেজার এবং আয়নাগুলি অসীম দীর্ঘ বলে ধরে নিয়ে প্রতিটি আয়না দিয়ে লেজারের ছেদটি গণনা করি। তারপরে আমি পরীক্ষা করলাম যে ছেদটি আয়না এবং লেজারের সীমাবদ্ধ দৈর্ঘ্যের মধ্যে রয়েছে। তারপরে আমি নিকটতম চৌরাস্তাটি নিয়েছি, লেজারটিকে সেই বিন্দুতে নিয়ে যেতে পারি এবং যতক্ষণ না লেজার সমস্ত আয়না মিস করে।

খুব মজাদার প্রকল্প। এই প্রশ্ন জিজ্ঞাসা করার জন্য ধন্যবাদ!

পঠনযোগ্য কোড

// a = input array
// M = Math, Mc = M.cos, Ms = M.sin, P=M.PI, T=2*P, t=true
// l = laser segment
// m = array of mirror segments
// i = loop variable
// S = segment class (this.a=x1,b=y1,c=x2,d=y2,e=len,f=theta)
// D = distance function
// I = intersect function
// f = last mirror bounced from
// h = hits a mirror
// n = next intersecing mirror
// d = distance to mirror
// x = intersection point x
// y = intersection point y
// r = mirror intersection result (d,x,y)
// b = number of bounces (FOR DEBUGGING)
// A,B,C,E,F,G,H,J,K,L,O temp variables
// s = laser segment array

// get input array
var a = prompt().split(" ").map(Number);

// some constants
var M = Math, Mc = M.cos, Ms = M.sin, P = M.PI, T = 2 * P, t = true;

// laser segment
var l = new S(a[0], a[1], a[0] + a[3] * Mc(a[2]), a[1] + a[3] * Ms(a[2])), s = [];

// mirror segments
var m = []; for (var i = 4; i < a.length;) m.push(new S(a[i++], a[i++], a[i++], a[i++]));

// bounce until miss
var f = -1, b = 0; for (; ;) {

    // best mirror found
    var h = !t, d, x, y, n, r = {};

    // loop through mirrors, skipping last one bounced from
    for (var i = 0; i < m.length; i++)
        if (i != f)
            if (I(l, m[i], r))
                if (!h || r.d < d) { h = t; d = r.d; x = r.x; y = r.y; n = i }

    // a mirror is hit
    if (h) {

        // add to draw list, inc bounces
        s.push(new S(l.a, l.b, x, y)); b++;

        // move and shorten mirror
        l.a = x; l.b = y; l.e -= d;

        // calculate next angle
        l.f = 2 * (m[f = n].f + P / 2) - (l.f + P);

        // laser end point
        l.c = l.a + l.e * Mc(l.f); l.d = l.b + l.e * Ms(l.f);

    } else {

        // add to draw list, break
        s.push(new S(l.a, l.b, l.c, l.d));
        break;
    }
}
// done, print result
alert("X = " + l.c.toFixed(6) + ",  Y = " + l.d.toFixed(6) + ",  bounces = " + b);
PlotResult();

// segment class
function S(a, b, c, d) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = D(a, b, c, d); this.f = M.atan2(d - b, c - a) }

// distance function
function D(a, b, c, d) { return M.sqrt((a - c) * (a - c) + (b - d) * (b - d)) }

// intersect function
function I(l, m, r) {

    // some values
    var A = l.a - l.c, B = l.b - l.d, C = m.a - m.c, L = m.b - m.d, E = l.a * l.d - l.b * l.c, F = m.a * m.d - m.b * m.c, G = A * L - B * C;

    // test if parallel
    if (!G) return !t;

    // intersection
    r.x = (E * C - A * F) / G; r.y = (E * L - B * F) / G;

    // distances
    var H = r.d = D(l.a, l.b, r.x, r.y), O = D(l.c, l.d, r.x, r.y), J = D(m.a, m.b, r.x, r.y), K = D(m.c, m.d, r.x, r.y);

    // return true if intersection is with both segments
    return (H < l.e) && (O < l.e) && (J < m.e) && (K < m.e);
}

খুব সুন্দর, আমি ওয়েব ইন্টারফেসটি পছন্দ করি। আরেকটি মজা ইনপুট: 0 0 0.4 100 1 1 1 -1 1 -1 -1 -1 -1 -1 -1 1 -1 1 1 1
ক্যালভিনের

1
আসল প্রোগ্রামটি কোথায়?
পিটার টেলর

এটি এখানে ওয়েব পৃষ্ঠায় রয়েছে: goo.gl/wKgIKD
জেফএসবি

এই সাইটের উত্তরগুলিতে সাধারণত প্রশ্নের উত্তর দেওয়ার জন্য প্রয়োজনীয় সমস্ত কোড অন্তর্ভুক্ত করা উচিত। এই প্রশ্নের ক্ষেত্রে, এটি এমন একটি প্রোগ্রাম যা স্টিডিন থেকে পড়ে এবং স্টাডআউটকে লেখেন। উপরন্তু, যেহেতু এটি একটি কোড-গল্ফ প্রশ্ন আপনার কোডটি যথাসম্ভব ন্যূনতম করা উচিত: খুব কমপক্ষে, মন্তব্যগুলি এবং অপ্রয়োজনীয় শ্বেত স্পেস অপসারণ এবং যেখানে সম্ভব সেখানে একটি-চরিত্র সনাক্তকারী ব্যবহার করা using
পিটার টেলর

@ জেফএসবি এই জমাটি বোনাস উত্তরের জন্য বৈধ, কেবলমাত্র গৃহীত উত্তর নয়। (যদিও আপনি আপনার সমস্ত কোড অন্তর্ভুক্ত করতে চাইতে পারেন))
ক্যালভিনের

6

পাইথন - 765

ভাল চ্যালেঞ্জ। এটি আমার সমাধান যা স্টিডিন এবং স্টপআউট আউটপুট থেকে ইনপুট পায়। @ মার্টিন বাটনার উদাহরণ ব্যবহার করে:

python mirrors.py 1 1 70.00024158332184 95 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3     5 1 4 3 7 6 5 6.1 8.5 2.965 8.4 2 8.5 3.035 8.6 4 8.4 2 10.5 3 8.6 4 10.5 3

7.7094468894 3.84896396639

গল্ফড কোডটি এখানে:

import sys;from cmath import*
l=[float(d) for d in sys.argv[1:]];c=180/pi;p=phase;q=exp;u=len;v=range
def o(l):
 L=l[0]+1j*l[1];t=l[2]/c;D=l[3];S=[L,L+D*q(1j*t)];N=[[l[i]+1j*l[i+1],l[i+2]+1j*l[i+3]] for i in v(4,u(l),4)];a=[];b=[]
 for M in N:
  z=S[1].real-S[0].real;y=M[0].real-M[1].real;x=S[1].imag-S[0].imag;w=M[0].imag-M[1].imag;d=M[0].real-S[0].real;f=M[0].imag-S[0].imag;g=z*w-x*y;h=w/g;j=-y/g;m=-x/g;n=z/g;a.append(h*d+j*f);b.append(m*d+n*f)
 i=1;e=-1
 for k in v(u(N)):
  if 1>b[k]>0:
   if i>a[k]>1e-14:
    i=a[k];e=k
 if e>-1:
  L=S[0]+i*(S[1]-S[0]);M=N[e];l[0]=L.real;l[1]=L.imag;l[2]=c*(p(M[1]-M[0])+p(q(1j*p(M[1]-M[0]))*q(1j*-t)));l[3]=D*(1-i)
  return l
 J=S[0]+i*(S[1]-S[0]) 
 print J.real, J.imag   
 return J.real, J.imag   
while u(l)>2:
 l=o(l)

এবং এখানে একটি বোনাস ফিগার সহ অরোগল্ড কোড

আয়না

import sys
from cmath import*
import matplotlib
import matplotlib.pyplot as plt
l=[float(d) for d in sys.argv[1:]]
def nextpos(l):
    L=l[0]+1j*l[1]
    t=l[2]/180*pi
    D=l[3]
    S=[L,L + D * exp(1j * t)]
    MM=[[l[i]+1j*l[i+1],l[i+2]+1j*l[i+3]] for i in range(4,len(l), 4)]    
    a=[]
    b=[]
    for M in MM:
        #determine intersections
        a11 = S[1].real-S[0].real 
        a12 = M[0].real-M[1].real
        a21 = S[1].imag-S[0].imag
        a22 = M[0].imag-M[1].imag
        b1  = M[0].real-S[0].real
        b2  = M[0].imag-S[0].imag
        deta = a11*a22-a21*a12
        ai11 = a22/deta
        ai12 = -a12/deta
        ai21 = -a21/deta
        ai22 = a11/deta        
        a.append(ai11*b1+ai12*b2)
        b.append(ai21*b1+ai22*b2)
    #determine best intersection    
    mina = 1
    bestk = -1
    for k in range(len(MM)):
        if 1>b[k]>0:
            if mina>a[k]>1e-14:
                mina=a[k]
                bestk=k
    if bestk>-1:
        #determine new input set
        L=S[0]+mina*(S[1]-S[0])
        M=MM[bestk]
        l[0]=L.real
        l[1]=L.imag
        angr=phase(exp(1j*phase(M[1]-M[0]))*exp(1j *-t))
        l[2]=180/pi*(phase(M[1]-M[0])+angr)
        l[3]=D*(1-mina)
        return l
    J= S[0]+mina*(S[1]-S[0]) 
    print J.real, J.imag   
    return J.real, J.imag   
#plotting
xL = [l[0]]
yL = [l[1]]
fig = plt.figure()
ax = fig.add_subplot(111,aspect='equal')
for i in range(4,len(l), 4):
    plt.plot([l[i],l[i+2]],[l[i+1],l[i+3]], color='b')
while len(l)>2:
    #loop until out of lasers reach
    l = nextpos(l)
    xL.append(l[0])
    yL.append(l[1])
plt.plot(xL,yL, color='r')
plt.show()

-1: অনুমান পূরণ হয় না। নির্দিষ্ট আউটপুট দুটি সংখ্যা নয়, দুটি সংখ্যা এবং একটি চিত্র।
পিটার টেলর

@ পিটারটেলর তাই আপনার মানে স্টিডিন / স্টাডাউট?
রায়

@ উইলেম একটি বোনাস উত্তর হিসাবে এটি ঠিক আছে। কোড-গল্ফ উত্তর হয়ে উঠতে কেবল ঠিক এটি অবশ্যই মেনে চলা উচিত।
ক্যালভিনের শখ 14

আমি কোডটি আপডেট করেছি
উইলিয়াম

নোট যে sys.argvস্টিডিন নয়।
রায়

6

মতলব (388)

চক্রান্ত

চক্রান্ত plot2

ধারণা

প্রতিবিম্ব পয়েন্টস

প্রতিবিম্ব পয়েন্টগুলি গণনা করার জন্য আমাদের মূলত দুটি সরল রেখা আন্তঃসংযোগ করতে হয়। একটি বিন্দু p0 এবং ভেক্টর v সহ, অন্যটি দুটি পয়েন্টের মধ্যে p1, p2। সুতরাং সমাধানের সমীকরণটি হ'ল (গুলি, টি পরামিতি): p0 + t v = s p1 + (1-s) * p2।

প্যারামিটার গুলি এরপরে আয়নাটির একটি বারিসেন্ট্রিক সমন্বয় সুতরাং যদি 0 হয়

মিরর

ভি এর মিররিংটি বেশ সহজ। আসুন আমরা ধরে নিই যে || ভি || = || এন || = 1 যেখানে এন বর্তমান আয়নাটির সাধারণ ভেক্টর। তারপরে আপনি কেবল সূত্রটি v: = v-2 ** n ব্যবহার করতে পারেন যেখানে <,> বিন্দু পণ্য।

পদক্ষেপের বৈধতা

নিকটতম 'বৈধ' আয়না গণনার সময় আমাদের কিছু মানদণ্ড বিবেচনা করতে হবে যা এটিকে বৈধ করে তোলে। প্রথমে আয়নাটির বাধা বিধিটি অবশ্যই দুটি প্রান্তের মধ্যে থাকা উচিত, সুতরাং এটি 0 হবে

কার্যক্রম

p = [1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3];
hold on
grid on
for i=2:length(p)/4
    i = i*4+1-4
    p2=p(i+2:i+3)';
    p1=p(i:i+1)'
    plot([p1(1),p2(1)],[p1(2),p2(2)],'r-')
    text(p1(1),p1(2),['m' num2str((i+3)/4-1)])
end
%hold off

history = p(1:2)';


currentPosition = p(1:2)';%current
currentDirection=[cos(p(3)*pi/180);sin(p(3)*pi/180)];
while p(4)>0%as long as we do not have finished our distance
   distanceBuffer = Inf%distance next point buffer
   intersectionBuffer = NaN %next point buffer
   for i=2:length(p)/4%number of mirrors
       i = i*4+1-4 %i is now the index of the firs coordinate of the mirror
       %calculate all crosspoints
       p2=p(i+2:i+3)';
       mirrorVector = p2-p(i:i+1)';
       % idea: p0+s*currentDirection = s*p1+(1-s)*p2 solving for s,t
       r=[currentDirection,mirrorVector]\[p2-currentPosition];
       if r(1)<distanceBuffer && 0.001< r(1) && r(1)<p(4) &&0<=r(2) && r(2)<=1 %search for the nearest intersection
           distanceBuffer=r(1);
           intersectionBuffer=r(1)*currentDirection+currentPosition;
           mirrorBuffer = mirrorVector
       end
   end
   if distanceBuffer == Inf %no reachable mirror found
       endpoint = currentPosition+p(4)*currentDirection;
       counter = counter+1
       history = [history,endpoint];
       break
   else %mirroring takes place
       counter = counter+1
       history = [history,intersectionBuffer];
       currentPosition=intersectionBuffer;
       normal = [0,-1;1,0]*mirrorBuffer;%normal vector of mirror
       normal = normal/norm(normal)
       disp('arccos')
       currentDirection = currentDirection-2*(currentDirection'*normal)*normal;
       %v = v/norm(v)
       p(4)=p(4)-distanceBuffer
   end
end
history
plot(history(1,:),history(2,:))

সামান্য গল্ফড (388)

p=[1 1 430 17 4.8 5.3 6.2 4.3 1.5 4.8 3.5 6 6.3 1.8 7.1 3];
c=p(1:2)'
b=pi/180
v=[cos(p(3)*b);sin(p(3)*b)]
f=p(4)
while f>0
q=Inf
for i=2:length(p)/4
b=p(i+2:i+3)'
u=b-p(i:i+1)'
r=[v,u]\[b-c]
s=r(1)
t=r(2)
if s<q&&0.001<s&&s<f&&0<=t&&t<=1 
q=s
n=s*v+c
m=u
end
end
if q==Inf
disp(c+f*v)
break
else 
c=n
g=[0,-1;1,0]*m
g=g/norm(g)
v=v-2*(v'*g)*g
f=f-q
end
end

এটি আমাকে ফিরিয়ে নেয়। মতলবের সাথে আমার প্রথম অভিজ্ঞতাটি আমার স্নাতকোত্তর অধ্যয়নের সময় গবেষণার অবস্থানে থাকা অবস্থায় মিরর এবং লেন্সগুলির মাধ্যমে একটি লেজারের পথে মডেলিং করছিল। আপনার গ্রাফিক্স বিশেষভাবে দেখতে খুব পরিচিত। :) যাইহোক, ঠিক একপাশে। এখানে দুর্দান্ত কাজ, +1।
অ্যালেক্স এ।

হা হা ধন্যবাদ! আপনার মন্তব্যটি পপ আপ করতে দেখে আমি কেবল এটি করেছিলাম তা আমি এখনও মনে করি নি =)
flawr

হাহা তাহলে আমার মন্তব্য সম্ভবত আপনাকে ফিরিয়ে নেবে ! (আপনি কখন এটি পোস্ট করেছেন To)
অ্যালেক্স এ।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.