लेजर कहां जाता है


34

दर्पणों का प्रतिनिधित्व करने के लिए 2-आयामी ग्रिड लें और उस पर कई रेखाखंड बनाएं। अब एक सैद्धांतिक लेजर और कोण को इंगित करने के लिए दिशा को इंगित करने के लिए एक बिंदु चुनें। सवाल यह है: यदि आपका लेजर बीम पथ कुछ निर्दिष्ट दूरी के लिए अनुसरण करता है, तो आप किस समन्वय बिंदु पर हैं?

उदाहरण:

लेजर उदाहरण

इस छवि में, L, लेजर का स्थान है tयह कोण (सकारात्मक एक्स अक्ष से मापा जाता है), है 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

(ध्यान दें कि छवि मुक्तहस्त से खींची गई थी और ये मान केवल अनुमानित हैं। मार्टिन बंटनर के इनपुट मान हैं

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

अधिक टकराव देंगे, हालांकि वे स्केच से मेल नहीं खाते हैं।)

आउटपुट स्वरूप

आउटपुट को प्रारूप में स्टडआउट जाना चाहिए:

Ex Ey

ये भी फ्लोट हैं और घातीय रूप में हो सकते हैं।

टिप्पणियाँ

  • दर्पण एक-दूसरे को काट सकते हैं।
  • दर्पणों के दोनों किनारे चिंतनशील होते हैं।
  • बीम एक ही दर्पण को कई बार मार सकता है।
  • बीम हमेशा के लिए चला जाता है।

अपरिभाषित मामले

आप मान सकते हैं कि जहाँ के मामले

  • लेजर मिरर लाइन सेगमेंट पर शुरू होता है
  • लेजर बीम एक दर्पण के समापन बिंदु को हिट करता है
  • लेजर बीम दो दर्पणों के बीच चौराहे से टकराती है

अपरिभाषित हैं और उनका परीक्षण नहीं किया जाएगा। आपका प्रोग्राम कुछ भी कर सकता है यदि ये होते हैं, जिसमें एक त्रुटि भी शामिल है।

बोनस

सिर्फ मनोरंजन के लिए, मैं सर्वोच्च मतदान प्रस्तुत करने के लिए 200 इनाम अंक प्रदान करूंगा जो समस्या के चित्रमय प्रतिनिधित्व को आउटपुट करता है (आप एक इंटरैक्टिव स्क्रिप्ट भी लिख सकते हैं)। ये बोनस जमा करने की आवश्यकता नहीं है कि इसे कैसे इनपुट और आउटपुट के साथ संभाला जा सकता है। वे वास्तविक गोल्फिंग सबमिशन से अलग हैं, लेकिन दोनों को एक ही उत्तर में प्रस्तुत किया जाना चाहिए

नोट: केवल बोनस उत्तर प्रस्तुत करना ठीक है, आप केवल स्वीकृत उत्तर नहीं देंगे। स्वीकार किए जाने के लिए आपको वास्तव में इनपुट / आउटपुट कल्पना (उदाहरण के लिए आउटपुट में केवल Ex Eyचित्र शामिल हैं ) का पालन करना चाहिए , और सबसे छोटा होना चाहिए।


1
एक सवाल में गोल्फ और ungolfed प्रस्तुतियाँ होने imho एक बड़ी गड़बड़ बनने जा रहा है। 200 बाउंटी पॉइंट इतने आकर्षक हैं कि गोल्फ छोटी बात बन जाती है।
हावर्ड

1
@PeterTaylor आप मुझे संदर्भ से अच्छी तरह अवगत करा रहे हैं। मैं ओपी के सेक्शन बोनस के जवाबों को पढ़ता हूं क्योंकि दोनों प्रस्तुतियाँ पूरी तरह से अलग हैं लेकिन एक ही पोस्ट से संबंधित हैं यदि दोनों का प्रयास किया जाता है (जिसका मतलब होगा कि बस पॉपकॉन उत्तर ठीक होगा)। वैसे भी, वे आपके वोट हैं और यह आपके ऊपर है कि आप उनका उपयोग कैसे करते हैं, और मैं शायद किसी समय किसी भी तरह एक गोल्फ संस्करण जोड़ूंगा। लेकिन मुझे लगता है कि ओपी स्पष्ट कर सकता है कि वह इरादा करता है, केवल पॉपकॉन जवाब देने के लिए वैध है या नहीं।
मार्टिन एंडर

1
@ मार्टिनबटनर, " बोनस " का अर्थ है " अतिरिक्त, अतिरिक्त "। यह मुख्य चुनौती का हिस्सा नहीं है। और सवाल केवल एक टैग, कोड-गोल्फ है
पीटर टेलर

2
@PeterTaylor मार्टिनबटनर सही है। प्रश्न के केवल बोनस भाग का उत्तर देना ठीक है। मैंने कहा कि बोनस उत्तर i / o के साथ अन-गोल्फ और लीनियर हो सकते हैं, और सभी मौजूदा बोनस सबमिशन मुझे ठीक लगते हैं। सबसे छोटा सबमिशन जो वास्तव में कल्पना का पालन करता है, स्वीकृत उत्तर होगा। वर्तमान में कोई सबमिशन नहीं करता है, लेकिन यह मेरे साथ ठीक है।
कैल्विन के

1
उस स्थिति में " बोनस " उपयोग करने के लिए गलत शब्द है और आप लोगों से नियम तोड़ने के लिए कह रहे हैं , जो मददगार नहीं है।
पीटर टेलर

जवाबों:


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}

यह मूल रूप से रूबी के लिए मैथेमेटिका समाधान का प्रत्यक्ष अनुवाद है, साथ ही कुछ गोल्फिंग और यह सुनिश्चित करता है कि यह आई / ओ मानदंडों को पूरा करता है।


आप पहले उदाहरण के अंत में मेज़ के त्रिकोण को कैसे पार करते हैं?
AJMansfield

1
@AJMansfield त्रिकोण में एक छोटा सा छेद है, जिसे आप एनीमेशन की शुरुआत में देख सकते हैं।
मार्टिन एंडर

यह बहुत अच्छा होगा यदि आप एक पैराग्राफ लिखकर बता सकते हैं कि यह कैसे काम करता है।
जेएफएसबी

@JeffSB मैंने अब गणितज्ञ कोड का दस्तावेज तैयार किया है। रूबी संस्करण अस्पष्ट चर नामों और साजिश रचने के साथ बिल्कुल वैसा ही करता है।
मार्टिन एंडर

@ मार्टिनबटनर धन्यवाद। यह देखना दिलचस्प है कि अन्य लोग इसे कैसे करते हैं। क्या आपको एहसास हुआ कि ऐसा होने से पहले आपको उस अंतिम दर्पण को बाहर करना होगा जिसे आपने बाउंस किया था? मैंने नहीं किया, लेकिन मैंने इसे जल्द ही समझ लिया। मैंने आपके कोड में बहुत कम संख्या देखी है और इसलिए मैंने यह देखने के लिए कहा कि यह कैसे काम करता है।
जेफएसबी

18

पायथन 3 (421C 390C है, 366C)

builtin.complex2d वेक्टर के रूप में उपयोग करें । इसलिए

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

368C रूबी समाधान को हरा करने के लिए, मैंने दर्पण के साथ बिंदु प्रतिबिंब की गणना करने के लिए एक काफी कॉम्पैक्ट विधि ढूंढी है। और अधिक वर्णों को कम करने के लिए कुछ जटिल बीजगणित का भी उपयोग किया। इन्हें आसानी से अनलॉक्ड कोड में पाया जा सकता है।

यहाँ गोल्फ संस्करण है।

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)

बोनस: HTML, कॉफ़ीस्क्रिप्ट, रीयलटाइम समायोजन और गणना

यह है, आप किसी भी अंतिम बिंदु (या लेज़र, मिरोस) को खींचते हैं, फिर ट्रैक का प्रतिपादन किया जाता है। यह दो प्रकार के इनपुट का भी समर्थन करता है, एक प्रश्न में वर्णित है और एक @Martin Büttner द्वारा उपयोग किया जाता है।

स्केलिंग भी अपने आप समायोजित हो जाती है।

अभी के लिए इसमें एनीमेशन नहीं है। शायद मैं इसे बाद में सुधार करूंगा। हालांकि, सफेद बिंदुओं को खींचना और आप एक अन्य प्रकार का एनीमेशन देख सकते हैं। इसे यहाँ ऑनलाइन आज़माएँअपने आप को , यह मज़ेदार है!

पूरी परियोजना यहां पाई जा सकती है

मामला एक मामला 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 इनपुट या आउटपुट के लिए कल्पना को पूरा नहीं करता है।
पीटर टेलर

@ रे बोनस के उत्तर के रूप में यह ठीक है। यह केवल कोड-गोल्फ उत्तर बनने के लिए कल्पना को पूरा करना चाहिए।
केल्विन के

@PeterTaylor अब कल्पना से मिलो।
रे

यह वास्तव में अच्छा है कि आप दर्पण को कैसे घुमा सकते हैं! तुम्हारा मेरा पहला +1 वोट है।
जेएफएसबी जूल

17

HTML जावास्क्रिप्ट, 10,543, 947 889

मैंने एक बग तय किया और सुनिश्चित किया कि आउटपुट प्रश्न युक्ति से मिलता है। नीचे दिए गए वेबपेज में गोल्फ संस्करण और ग्राफिकल बोनस संस्करण भी है। मैंने @ रे द्वारा बताए गए एक बग को भी ठीक किया जिसने 58 वर्णों को बचाया। (धन्यवाद रे।) आप एक गोल्फ कंसोल में गोल्फ कोड भी चला सकते हैं। (अब मैं एक 2mW हरी लेजर का उपयोग कर रहा हूँ।)

गोल्फ कोड

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
JeffSB

इस साइट पर उत्तर में आम तौर पर प्रश्न का उत्तर देने के लिए आवश्यक सभी कोड शामिल होने चाहिए। इस सवाल के मामले में, यह एक कार्यक्रम है जो स्टड से पढ़ता है और स्टडआउट को लिखता है। इसके अलावा, चूंकि यह एक कोड-गोल्फ प्रश्न है, आपको कोड को जितना संभव हो उतना कम से कम करना चाहिए: बहुत कम से कम, टिप्पणियों और अनावश्यक व्हाट्सएप को हटाने और जहां संभव हो, एक-चरित्र पहचानकर्ताओं का उपयोग करके।
पीटर टेलर

@JeffSB यह सबमिशन बोनस आंसर के लिए मान्य है, केवल स्वीकृत उत्तर के लिए नहीं। (हालांकि आप अपने सभी कोड को शामिल करना चाह सकते हैं।)
केल्विन के शौक

6

अजगर - 765

अच्छी चुनौती। यह मेरा समाधान है जो स्टड से इनपुट प्राप्त करता है और स्टडआउट को आउटपुट देता है। @Martin Büttner के उदाहरण का उपयोग करना:

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: कल्पना को पूरा नहीं करता है। निर्दिष्ट आउटपुट दो संख्याएँ हैं, दो संख्याएँ और एक छवि नहीं।
पीटर टेलर

@PeterTaylor तो आपका मतलब है स्टड / स्टडआउट?
रे

@willem एक बोनस उत्तर के रूप में यह ठीक है। यह केवल कोड-गोल्फ उत्तर बनने के लिए कल्पना को पूरा करना चाहिए।
केल्विन के शौक

मैंने कोड अपडेट किया है
विलेम

ध्यान दें कि sys.argvस्टडिन नहीं है।
रे

6

मतलाब (388)

भूखंड

भूखंड plot2

अवधारणाओं

परावर्तन अंक

परावर्तन बिंदुओं की गणना के लिए हमें मूल रूप से दो सीधी रेखाओं का परस्पर संबंध बनाना होता है। एक बिंदु p0 और वेक्टर v के साथ, दूसरा दो बिंदु p1, P2 के बीच। तो हल करने के लिए समीकरण (s, t पैरामीटर हैं): p0 + t v = s p1 + (1-s) * P2।

पैरामीटर s तो ​​दर्पण का एक द्विसंयोजक समन्वय है इसलिए यदि 0

मिररिंग

V का मिररिंग बहुत सरल है। हम मान लेते हैं कि || v || = || n || = 1 जहां n वर्तमान दर्पण का सामान्य वेक्टर है। तब आप केवल सूत्र 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।
एलेक्स ए।

हा हा धन्यवाद! मुझे अभी याद नहीं आया कि मैंने ऐसा तब किया जब मैंने आपकी टिप्पणी को देखा =)
त्रुटिपूर्ण

हाहा तब मेरी टिप्पणी शायद आपको ले जाए वापस जाए! (जब आप इसे पोस्ट करते हैं।)
एलेक्स ए।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.