পয়েন্টের একটি তালিকা প্রদত্ত বর্গাকার ঘূর্ণন নির্ধারণ করা


19

এই চ্যালেঞ্জে আপনাকে পয়েন্টগুলির একটি তালিকা দেওয়া হবে। এই পয়েন্টগুলি একটি কাল্পনিক বর্গক্ষেত্রের ঘের উপর অবস্থিত । আপনার লক্ষ্যটি হ'ল:

  1. যদি সম্ভব হয় তবে স্কোয়ারের আবর্তনটি মুদ্রণ করুন, যা [0, 90) থেকে একটি মান হবে যেখানে 0 উল্লম্ব এবং অনুভূমিক রেখাসমূহ সহ একটি বর্গের প্রতিনিধিত্ব করে। ঘূর্ণায়মানের বিপরীতে গণনা করা ডিগ্রিতে ঘূর্ণনটি দেওয়া উচিত।
  2. স্কোয়ারের আবর্তন যদি অস্পষ্ট হয় (যেমন কেবল 2 পয়েন্ট দেওয়া হয়), "অজানা" প্রিন্ট আউট করুন
  3. পয়েন্টগুলি প্রদত্ত একটি বর্গ তৈরি করা যদি অসম্ভব হয় তবে "অসম্ভব" প্রিন্ট আউট করুন

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

এখানে কয়েকটি পরীক্ষার কেস দেওয়া হয়েছে (সহজে দৃশ্যধারণের জন্য আমি পুরো সংখ্যাটি ব্যবহার করে বেশিরভাগটি তৈরি করেছি, তবে আপনার প্রোগ্রামটি ভাসমান পয়েন্টগুলি পরিচালনা করবে):

অজানা:

0,0                      
0,0 1,0        
0,0 1,0 0,1              
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2

অসম্ভব:

0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1

সম্ভাব্য (যদি মনোনীত না করা হয় তবে 0 এ ফিরে আসা উচিত):

0,0 1,0 2,0
0,0 0.3,0.3 0.6,0.6  (should return 45)
0,0 0.1,0.2 0.2,0.4  (should return appx 63.435 (the real value is arctan(2)))
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3 

আমি কিছু আকর্ষণীয় পরীক্ষার কেস মিস করেছি। যদি তা হয় তবে সেগুলি যুক্ত করতে দয়া করে মন্তব্য করুন।

এটি কোড-গল্ফ, তাই সংক্ষিপ্ততম কোডটি জয়ী!


ন্যূনতম প্রয়োজনীয় নির্ভুলতা আছে? সঠিক উত্তর থেকে ভুল হিসাবে গণ্য হওয়ার আগে আউটপুটটি কতদূর হতে পারে?
ট্রাইকোপলাক্স

@ ট্রাইকোপ্লেক্স আপনার ভাষার ভাসমান-পয়েন্ট নম্বর প্রয়োগের জন্য যথাযথ হবেন।
নাথান মেরিল

এর অর্থ কি এই যে যদি 2 টি সম্ভাব্য পন্থা থাকে এবং আপনার ভাষায় যদি কেউ কিছুটা আরও সঠিক ফলাফল দেয় তবে সর্বাধিক সঠিক পদ্ধতির ব্যবহার করা উচিত?
ট্রাইকোপলাক্স

পছন্দ করুন
নাথান মেরিল

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

উত্তর:


6

Rev 1: রুবি, 354 বাইট

আরও গলফিং ধন্যবাদ ব্লুটোরেঞ্জের জন্য।

->a{t=s=Math::PI/18E4
d=r=c=0
a=a.map{|e|e-a[0]}
0.upto(36E4){|i|b=a.map{|e|(e/Complex.polar(1,i*s)).rect}.transpose
m,n=b
if n.min>=f=0
l=[m.max-x=m.min,n.max].max
a.each_index{|j|f+=((l-w=n[j])*(x+l-v=m[j])*(x-v)*w)**2}
(1E-9>q=f/l**8)&&(c>0&&(i-d)%9E4%89E3>1E3?c=9E9:0;c+=1;d=i)
q<t&&(r=i)&&t=q;end}
c<101&&a[1]?c<1?'impossible':r%9E4/1.0E3:'unknown'}

রুবি, 392 বাইট

->(a){
s=Math::PI/18E4
t=1
d=r=c=0
a=a.map{|e|e-a[0]}
(0..36E4).each{|i|
b=a.map{|e|(e/Complex.polar(1,i*s)).rect}.transpose
m=b[0]
n=b[1]
x=m.min
if n.min>=0
l=[m.max-x,n.max].max
f=0
a.each_index{|j|f+=((l-n[j])*(x+l-m[j])*(x-m[j])*n[j])**2}
q=f/l**8
if q<1E-9
c>0&&(i-d)%9E4%89E3>1E3?(c=9E9):0
c+=1
d=i
end
if q<t
r=i
t=q
end
end
}
c>100||a.size<2?'unknown':c<1? 'impossible':r%9E4/1.0E3
}

অ্যালগরিদম নিম্নরূপ:

- একটি স্বেচ্ছাসেবী বিন্দু চয়ন করুন (প্রথমটি) এবং এটি উত্সে সরান (তালিকার সমস্ত পয়েন্ট থেকে এই পয়েন্টের স্থানাঙ্কগুলি বিয়োগ করুন))

-৮০ ডিগ্রি মাধ্যমে 0.001 ডিগ্রি বর্ধনে মূল সম্পর্কে স্কোয়ারের সমস্ত ঘূর্ণন চেষ্টা করুন।

-প্রদত্ত রোটেশনের জন্য, যদি সমস্ত পয়েন্ট y অক্ষরের উপরে থাকে তবে সর্বনিম্ন এবং বামতম বিন্দুকে সংযুক্ত করে সমস্ত পয়েন্টের চারপাশে সবচেয়ে ছোট সম্ভাব্য বর্গাকার আঁকুন।

- সমস্ত পয়েন্ট প্রান্তে আছে কিনা তা পরীক্ষা করুন। এটি একটি নরম গণনার সাহায্যে করা হয় যা প্রতিটি পয়েন্ট নেয়, সমস্ত প্রান্ত থেকে বর্গক্ষেত্রের দূরত্ব খুঁজে পায় এবং তাদের একসাথে বহুগুণ করে। এটি একটি হ্যাঁ / না উত্তর চেয়ে ভাল ফিট দেয়। এটি ব্যাখ্যা করা হয়েছে যে এই পণ্যটি পাশের দৈর্ঘ্য ^ 8 দ্বারা ভাগ করা যদি 1E-9 এর চেয়ে কম হয় তবে একটি সমাধান পাওয়া যায়। অনুশীলনে এটি সহনশীলতার একটি ডিগ্রির চেয়ে কম।

- সেরা ফিট 90 ডিগ্রি মডে নেওয়া হয় এবং সঠিক কোণ হিসাবে প্রতিবেদন করা হয়।

বর্তমানে যদি 100 টিরও বেশি সমাধান পাওয়া যায় (কোডটি 0.001 ডিগ্রি রেজোলিউশনে That's এটি সহনীয়তার 0.1 ডিগ্রি)

পরীক্ষা প্রোগ্রামে সম্পূর্ণরূপে প্রথম কাজ করছে

গতি যুক্তিসঙ্গত করার জন্য প্রয়োজনীয় রেজোলিউশনের 1/10 তম আমি রেজুলেশনটি ছেড়ে দিয়েছি। খুব শেষ পরীক্ষার ক্ষেত্রে 0.01 ডিগ্রাসের ত্রুটি রয়েছে।

g=->(a){
 s=Math::PI/18000
 t=1
 d=r=-1
 c=0
 a=a.map{|e| e-a[0]} 

 (0..36000).each{|i| 
    b=a.map{|e|(e/Complex.polar(1,i*s)).rect}.transpose

    m=b[0]
    n=b[1]
    x=m.min

    if n.min>=0

       l=[m.max-x,n.max].max
       f=0
       a.each_index{|j|f+=((l-n[j])*(x+l-m[j])*(x-m[j])*n[j])**2}
       q=f/l**8

       if q<1E-9

         j=(i-d)%9000
         c>0&&j>100&&j<8900?(c=9E9):0 
         c+=1
         d=i
       end  

       if q<t
         r=i
         t=q
       end

     end    
  }

 print "t=",t,"   r=",r,"     c=",c,"    d=",d,"\n"
 p c>100||a.size<2?'unknown':c<1? 'impossible':r%9000/100.0   
}


#ambiguous
#g.call([Complex(0,0)])
#g.call([Complex(0,0),Complex(1,0)])
#g.call([Complex(0,0),Complex(1,0),Complex(0,1)])
#g.call([Complex(0,0),Complex(1,0),Complex(0,1),Complex(1,1)])
#g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,3),Complex(2,0),Complex(2,3),Complex(3,1),Complex(3,2)])

#impossible
#g.call([Complex(0,0),Complex(1,0),Complex(2,0),Complex(3,1),Complex(4,2)])
#g.call([Complex(0,0),Complex(1,0),Complex(2,0),Complex(1,1)])
#g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,3),Complex(2,0),Complex(2,3),Complex(3,1),Complex(3,2),Complex(2,2)])
#g.call([Complex(2,0),Complex(0,1),Complex(2,2),Complex(0,3)])
#g.call([Complex(0,0),Complex(2,1),Complex(0,2),Complex(2,2),Complex(-1,1)])

#possible
g.call([Complex(0,0),Complex(1,0),Complex(2,0)])
g.call([Complex(0,0),Complex(0.3,0.3),Complex(0.6,0.6)]) #(should return 45)
g.call([Complex(0,0),Complex(0.1,0.2),Complex(0.2,0.4)]) #(should return appx 63.435 (the real value is arctan(2)))
g.call([Complex(0,0),Complex(0,1),Complex(2,1),Complex(2,2)])
g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,4),Complex(2,0),Complex(2,4),Complex(4,1),Complex(4,3)])

গল্ফযুক্ত সংস্করণ, অনুমানের সাথে সঙ্গতিপূর্ণ রেজোলিউশন, পরীক্ষার প্রোগ্রামে কল প্রতি এক মিনিট সময় নেয়।

শেষ পরীক্ষার ক্ষেত্রে এখনও 0.001 ডিগ্রির একটি বেদম ত্রুটি রয়েছে। আরও রেজোলিউশন বাড়ানো সম্ভবত এটিকে দূর করবে।

g=->(a){                                                            #take an array of complex numbers as input
  s=Math::PI/18E4                                                   #step size PI/180000
  t=1                                                               #best fit found so far
  d=r=c=0                                                           #angles of (d) last valid result, (r) best fit; c= hit counter
  a=a.map{|e|e-a[0]}                                                #move shape so that first point coincides with origin
  (0..36E4).each{|i|                                                #0..360000
    b=a.map{|e|(e/Complex.polar(1,i*s)).rect}.transpose             #rotate each element by dividing by unit vector of angle i*s, convert to array... 
    m=b[0]                                                          #...transpose array [[x1,y1]..[xn,yn]] to [[x1..xn],[y1..yn]]...
    n=b[1]                                                          #...and assign to variables m and n 
    x=m.min                                                         #find leftmost point
    if n.min>=0                                                     #if all points are above x axis
       l=[m.max-x,n.max].max                                        #find the sidelength of smallest square in which they will fit
       f=0                                                          #f= accumulator for errors. For each point
       a.each_index{|j|f+=((l-n[j])*(x+l-m[j])*(x-m[j])*n[j])**2}   #...add to f the product of the squared distances from each side of the smallest square containing all points
       q=f/l**8                                                     #q= f normalized with respect to the sidelength.
       if q<1E-9                                                    #consider a hit if <1E-9
         c>0&&(i-d)%9E4%89E3>1E3?(c=9E9):0                          #if at least one point is already found, and the difference between this hit and the last exceeds+/-1 deg (mod 90), set c to a high value
         c+=1                                                       #increment hit count by 1 (this catches infinitely varible cases)
         d=i                                                        #store the current hit in d
       end  
       if q<t                                                       #if current fit is better than previous one
        r=i                                                         #store the new angle
        t=q                                                         #and revise t to the new best fit.
       end             
    end
  }
  c>100||a.size<2?'unknown':c<1? 'impossible':r%9E4/1.0E3           #calculate and return value, taking special care of case where single point given.
}
#ambiguous
puts g.call([Complex(0,0)])
puts g.call([Complex(0,0),Complex(1,0)])
puts g.call([Complex(0,0),Complex(1,0),Complex(0,1)])
puts g.call([Complex(0,0),Complex(1,0),Complex(0,1),Complex(1,1)])
puts g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,3),Complex(2,0),Complex(2,3),Complex(3,1),Complex(3,2)])

#impossible
puts g.call([Complex(0,0),Complex(1,0),Complex(2,0),Complex(3,1),Complex(4,2)])
puts g.call([Complex(0,0),Complex(1,0),Complex(2,0),Complex(1,1)])
puts g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,3),Complex(2,0),Complex(2,3),Complex(3,1),Complex(3,2),Complex(2,2)])
puts g.call([Complex(2,0),Complex(0,1),Complex(2,2),Complex(0,3)])
puts g.call([Complex(0,0),Complex(2,1),Complex(0,2),Complex(2,2),Complex(-1,1)])

#possible
puts g.call([Complex(0,0),Complex(1,0),Complex(2,0)])
puts g.call([Complex(0,0),Complex(0.3,0.3),Complex(0.6,0.6)]) #(should return 45)
puts g.call([Complex(0,0),Complex(0.1,0.2),Complex(0.2,0.4)]) #(should return appx 63.435 (the real value is arctan(2)))
puts g.call([Complex(0,0),Complex(0,1),Complex(2,1),Complex(2,2)])
puts g.call([Complex(0,1),Complex(0,2),Complex(1,0),Complex(1,4),Complex(2,0),Complex(2,4),Complex(4,1),Complex(4,3)])

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


আমি দ্বিতীয় পরীক্ষার কেস ঠিক করেছি, আপনাকে ধন্যবাদ
নাথান মেরিল

@ নাথানমিরিল 0,0 1,0 2,0 1,2এখনও বর্গাকার 0,0 ... 2,2 এর বর্গক্ষেত্রের জন্য সংশোধিত কেসটি সম্ভব is আমি এটি চেষ্টা করেছি, এবং এটিও 0,0 1,0 2,0 1,1(দ্বিতীয়টি সত্যই অসম্ভব) Another আরেকটি বিষয়: আপনি কেবলমাত্র একটি মাত্র পয়েন্ট দিলে আমার কোডটি অজানা হওয়ার পরিবর্তে অসম্ভব প্রত্যাবর্তনযোগ্য তা গ্রহণযোগ্য বা অগ্রহণযোগ্য বলে মনে করেন? আমি গল্ফ শুরু করার আগে একটি উত্তরটির প্রশংসা করব।
স্তরের নদী সেন্ট

আমি বলতে চাইছিলাম 1,1। কীভাবে 1,2সেখানে পেলেন তা নিশ্চিত নয় । এটি গ্রহণযোগ্য নয়।
নাথান মেরিল

আপনি এটিকে কমপক্ষে 354 বাইটে নামিয়ে আনতে সক্ষম হবেন: পেস্টবিন.
com

টিপসটির জন্য ব্লুটোরেজ ধন্যবাদ! আমি রুবির কাছে নতুন এবং গল্ফ করতে কিছুটা সমস্যা আছে। আমি প্রচুর পরিমাণে ফেলেছি if..endকারণ রুবিতে নেস্টেড টের্নারি অপারেটরদের সাথে আমার ভীষণ সমস্যা হচ্ছে। আমি আপনাকে দেখতে পেয়েছি যে ব্যবহার করে &&
স্তর নদী সেন্ট

6

পার্ল

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

এখানে এলগরিদম

  1. বিন্দু পরীক্ষা করুন এবং দুটি বিন্দু রেকর্ড slাল, দৈর্ঘ্য, এক্স-ইন্টারসেপ্ট, ওয়াই-ইন্টারসেপ্টের মধ্যে প্রতিটি বিভাগের জন্য

  2. সরল রেখা (যেমন তিনটি বিন্দু বা দুটি সংলগ্ন অংশ) এবং স্বতন্ত্র সম্ভাব্য opালু (তাদের ঘূর্ণন বলুন) সন্ধান করুন। প্রতিটি লাইনে লম্বাতম বিভাগটি উপলব্ধ রাখুন।

  3. একটি বিভাগ এবং তৃতীয় পয়েন্টের মধ্যে সমস্ত দূরত্ব সন্ধান করুন (এটি 4 পয়েন্ট হিসাবে ব্যবহার করা উচিত)। সর্বনিম্ন অ-শূন্য দূরত্বের ট্র্যাক রাখুন।

  4. যে কোনও চারটি বিন্দুর জন্য (রাউগলি একটি আয়তক্ষেত্র) অভ্যন্তরীণ বিন্দুগুলি সন্ধান করে

সমাধানগুলি দেখান:

উ: "যদি একের অধিক অভ্যন্তরীণ বিন্দু থাকে তবে" অসম্ভব "বলুন।

বি ওয়ান লাইন:

  • অভ্যন্তরীণ বিন্দু ছাড়াই একটি লাইনে বেশিরভাগ বিন্দুর ক্ষেত্রে, "সম্ভাব্য" বলুন

  • বিন্দুগুলি খুব বেশি লাইনের কাছাকাছি থাকলে, "অসম্ভব" বলুন

    গ। দুটি লাইন:

  • "সম্ভাব্য" বলুন যখন কেবলমাত্র একটি সম্ভাব্য ঘূর্ণন থাকে

  • যখন একাধিক ঘূর্ণন থাকে তখন "অসম্ভব" বলুন

    D. কোন রেখা নেই: ঘূর্ণন সন্ধান করুন যা এটি 90। ঘোরার অংশে ফিট করে

  • "একটি সম্ভাব্য" বলুন যদি কেবলমাত্র একটির সাথে ফিট হয় বা যতগুলি ডট ফিট হয়।

  • যদি একাধিক ফিট হয় এবং বিন্দুগুলির বেশি না হয় তবে "অসম্ভব" বলুন

  • যতগুলি ঘূর্ণন মাপসই ফিট করে "অজানা" বলুন।

এখানে কোডটি (সমস্ত জ্ঞাত বাগগুলি সমাধান করা হয়েছে)

#!/usr/bin/perl
use strict ;
use warnings ;
my $PI = 4*atan2( 1, 1 ) ;
my $EPS = 0.000001 ;
while ( <DATA> ) {
    if ( /^\s*#/ ) { print ; next } # print comments
    chomp ;
    my @dot = split /\s+/ ;
    my $n = scalar @dot || next ; # skip empty lines

    # too few dots
    if ( $n < 3 ) {
        print "@dot : Unknown.\n" ;
        next
    }

    my %slop = () ; # segment --> its slope
    my %leng = () ; # segment --> its length
    my %x0   = () ; # segment --> its line's x-intercept
    my %y0   = () ; # segment --> its line's y-intercept
    my %side = () ; # slope   --> list of segments (with duplicates)

    # 1. examine dots
    for my $p (@dot) {
        my ($px,$py) = split /,/, $p ;
        for my $q (@dot) {
            next if $p eq $q ;
            next if defined ( $slop{ "$q $p" } ) ;
            my $segment_name = "$p $q" ;
            my ($qx,$qy) = split /,/, $q ;
            my $dx = $px - $qx ;
            my $dy = $py - $qy ;
            my $slope = "inf" ; $slope = $dy / $dx if abs($dx) > 0 ;
            my $sd = $dx*$dx+$dy*$dy ;
            my $x0 = ( $slope eq 'inf' ? $px : "nan" ) ;
            my $y0 = ( abs($slope) > 0 ? $px : "nan" ) ;
            $x0 = $qx - $qy / $slope if abs($slope) > 0 ;
            $y0 = $qy - $qx * $slope if $slope ne "inf" ;
            push @{ $side{ $slope } }, $segment_name ;
            $slop{ $segment_name } = $slope ;
            $leng{ $segment_name } = sqrt( $sd ) ;
            $x0{ $segment_name } = $x0 ;
            $y0{ $segment_name } = $y0 ;
        }
    }

    # 2. find straight lines and distinct possible slopes (rotation)
    my %line = () ;     # slope --> segment name
    my %rotation = () ; # slope --> slope itself
    my $a_rotation ;
    for my $slope ( keys %side ) {
        my %distinct = () ;
        for my $segment_name ( @{ $side{ $slope } } ) {
            $distinct{ $segment_name } = $slope ; 
            my $rot = $slope eq 'inf' ? '0' : abs( $slope < 0 ? 1/$slope : $slope ) ;
            $rotation{ $rot } = $rot ;
            $a_rotation = $rot ;
        }
        for my $a_segm ( keys %distinct ) {
            for my $b_segm ( keys %distinct ) {
                next if $a_segm eq $b_segm ;
                # the two segment has to be adjacent
                my ($a1,$a2) = split / /, $a_segm;
                my ($b1,$b2) = split / /, $b_segm;
                next unless $a1 eq $b1 || $a1 eq $b2 || $a2 eq $b1 || $a2 eq $b2 ;
                # the two segment has to have same intercepts
                my $x0a = $x0{ $a_segm } ;
                my $x0b = $x0{ $b_segm } ;
                my $y0a = $y0{ $a_segm } ;
                my $y0b = $y0{ $b_segm } ;
                next unless $x0a eq $x0b && $y0a eq $y0b ;
                # keep the longest segment
                my $a_len = 0 ;
                $a_len = $leng{ $line{ $slope } } if defined( $line{ $slope } ) && defined( $leng{ $line{ $slope } } ) ;
                for my $segm ("$a1 $b1", "$a1 $b2", "$a2 $b1", "$a2 $b2",
                              "$b1 $a1", "$b2 $a1", "$b1 $a2", "$b2 $a2" ) {
                    next unless defined ( $leng{ $segm } ) ;
                    if ( $a_len < $leng{ $segm } ) {
                        $a_len = $leng{ $segm } ;
                        $line{ $slope } = $segm ;
                    }
                }
            }
        }
    }

    # 3. find distance between a segment and a third point
    my %distance = () ;            # segment-point --> distance
    my %distance_mani = () ;       # distance --> array of segment-point
    my %min_distance = () ;        # segment --> min distance to other dots
    for my $segment_name ( keys %slop ) {
        my $a = $slop{ $segment_name } ;
        my $b = -1 ;
        my $c = $y0{ $segment_name } ;
        my $z = $x0{ $segment_name } ;
        for my $p (@dot) {
            next if $segment_name =~ /$p/ ; # skip dots that are in the segment
            my ($px,$py) = split /,/, $p ;
            my $d = 0 ;
            if ( $a ne 'inf' ) {
                my $num = ($b * $py) + ($a * $px) + $c ;
                my $den = sqrt( $a*$a + $b*$b ) ;
                $d = abs( $num ) / $den ;
            }
            else {
                $d = abs( $px - $z );
            }
            $distance{ "$segment_name $p" } = $d ;
            push @{ $distance_mani{ $d } }, "$segment_name $p" ;
            if ( $d > 0 ) {
                $min_distance{ $segment_name } = $d if !defined ( $min_distance{ $segment_name } ) or $d < $min_distance{ $segment_name }
            }
        }
    }

    # 4. find inner dots: pick 4 dots to form a well shaped pseudo-rectangle
    #    and check for any other dot that is too close to all the 4 sides.
    my $fail = 0 ;
    RECTANGLE:
    for my $a ( @dot ) {
        for my $b ( @dot ) {
            next if $a eq $b ;
            my ($ax,$ay) = split /,/, $a ;
            my ($bx,$by) = split /,/, $b ;
            next if $ax > $bx || $ay > $by ;
            for my $c ( @dot ) {
                next if $c eq $a or $c eq $b ;
                my ($cx,$cy) = split /,/, $c ;
                next if $bx < $cx || $by > $cy ;
                for my $d ( @dot ) {
                    next if $d eq $a or $d eq $b or $d eq $c ;
                    my ($dx,$dy) = split /,/, $d ;
                    next if $cx < $dx || $cy < $dy  ;
                    next if $dx > $ax || $dy < $ay  ;
                    for my $e ( @dot ) {
                        next if $e eq $a or $e eq $b or $e eq $c or $e eq $d ;

                        my $abe = $distance{ "$a $b $e" } || $distance{ "$b $a $e" } || next ;
                        my $bce = $distance{ "$b $c $e" } || $distance{ "$c $b $e" } || next ;
                        my $cde = $distance{ "$c $d $e" } || $distance{ "$d $c $e" } || next ;
                        my $dae = $distance{ "$d $a $e" } || $distance{ "$a $d $e" } || next ;

                        my $abd = $distance{ "$a $b $d" } || $distance{ "$b $a $d" } || next ;
                        my $abc = $distance{ "$a $b $c" } || $distance{ "$b $a $c" } || next ;
                        my $bca = $distance{ "$b $c $a" } || $distance{ "$c $b $a" } || next ;
                        my $bcd = $distance{ "$b $c $d" } || $distance{ "$c $b $d" } || next ;
                        my $cdb = $distance{ "$c $d $b" } || $distance{ "$d $c $b" } || next ;
                        my $cda = $distance{ "$c $d $a" } || $distance{ "$d $c $a" } || next ;
                        my $dac = $distance{ "$d $a $c" } || $distance{ "$a $d $c" } || next ; 
                        my $dab = $distance{ "$d $a $b" } || $distance{ "$a $d $b" } || next ; 

                        if ( $abd > $abe && $abc > $abe && 
                             $bca > $bce && $bcd > $bce &&
                             $cdb > $cde && $cda > $cde &&
                             $dac > $dae && $dab > $dae) {
                            ## print "     $a $b $c $d --> $e\n";
                            $fail ++ ;
                            last RECTANGLE ;
                        }
                    }
                }
            }
        }
    }
    if ( $fail ) {
        print "@dot : Impossible.\n" ;
        next # DATA 
    }

    my $m = scalar keys %rotation ; # how many distinct slopes
    my $r = scalar keys %line ; # how many lines i.e. >3 dots in a straight line

    print "@dot : " ;
    # most of dots lie in single line without inner dots
    if ( $r == 1 ) {
        $a_rotation = (keys %line)[0] ;
        my $a_segment = $line{ $a_rotation } ;
        my $a_dist = $min_distance{ $a_segment } || 0 ;
        if ( $a_dist && $a_dist < $leng{ $a_segment } ) {
            print "Impossible.\n"  ;
        }
        else {
            print "Possible. --> " . sprintf("%.3f deg", 180 / $PI * atan2( $a_rotation, 1 ) ) . "\n" ;
        }
        next # DATA
    }
    # two lines
    if ( $r == 2 ) {
        print "Impossible.\n" if $m > 1 ;
        print "Possible. --> " .
            sprintf("%.3f deg", 180 / $PI * atan2( $a_rotation, 1 ) ) . "\n" if $m == 1 ;  # never?
        next ; # DATA
    }
    # no lines
    if ( $r == 0 ) {
        # match between segment rotation and other side
        my $count = 0 ;
        my $numeros = 0 ;
        for my $slope ( keys %rotation ) {
            my $rot = $slope eq '0' ? 'inf' : -1/$slope ;
            if ( exists $side{ $rot } ) {
                $count++ ;
                my $u = scalar @{ $side{ $rot } } ;
                if ( $numeros < $u ) {
                    $numeros = $u ;
                    $a_rotation = $slope ;
                }
            }
        }
        print "Possible. --> " .
            sprintf("%.3f deg", 180 / $PI * atan2( $a_rotation, 1 ) ) . "\n" if $count < 2 or $count == $n ;
        print "Unknown.\n"    if $count == $m ;
        print "Impossible.\n"    if $count > 2 && $count != $n && $count != $m;
        next # DATA
    }
    # there are lines
    print "lines $r " ;
    my $shorter = 0 ;
    my $longer = 0 ;
    for my $slope ( keys %line ) {
        for my $dis ( keys %distance_mani ) {
            $shorter++ ;
            $longer++ ;
        }
    }
    print "ACK! WHAT IS THIS CASE! n=$n, m=$m, r=$r\n" ;
    1 ;
}

1;

__DATA__
# Unknown:

0,0
0,0 1,0
0,0 1,0 0,1
0,0 1,0 0,1 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2

# Impossible:

0,0 1,0 2,0 3,1 4,2
0,0 1,0 2,0 1,1
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2
2,0 0,1 2,2 0,3
0,0 2,1 0,2 2,2 -1,1

# Possible (if not designated, should return 0):

0,0 1,0 2,0 1,2
0,0 1,0 2,0 0.5,2.1

0,0 1,0 2,0
0,0 1,0 2,0 1,2
0,0 0.3,0.3 0.6,0.6
0,0 0.1,0.2 0.2,0.4
0,0 0,1 2,1 2,2
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3

এবং এখানে এটির আউটপুট

# Unknown:
0,0 : Unknown.
0,0 1,0 : Unknown.
0,0 1,0 0,1 : Unknown.
0,0 1,0 0,1 1,1 : Unknown.
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 : Unknown.
# Impossible:
0,0 1,0 2,0 3,1 4,2 : Impossible.
0,0 1,0 2,0 1,1 : Impossible.
0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2 2,2 : Impossible.
2,0 0,1 2,2 0,3 : Impossible.
0,0 2,1 0,2 2,2 -1,1 : Impossible.
# Possible (if not designated, should return 0):
0,0 1,0 2,0 1,2 : Possible. --> 0.000 deg
0,0 1,0 2,0 0.5,2.1 : Possible. --> 0.000 deg
0,0 1,0 2,0 : Possible. --> 0.000 deg
0,0 1,0 2,0 1,2 : Possible. --> 0.000 deg
0,0 0.3,0.3 0.6,0.6 : Possible. --> 45.000 deg
0,0 0.1,0.2 0.2,0.4 : Possible. --> 63.435 deg
0,0 0,1 2,1 2,2 : Possible. --> 0.000 deg
0,1 0,2 1,0 1,4 2,0 2,4 4,1 4,3 : Possible. --> 0.000 deg

শুভেচ্ছা।

Matteo।


এখানে প্রথম বাগটি রয়েছে: আপনার কেস 0,0 1,0 2,0 1,1 (অসম্ভব) আমার স্ক্রিপ্ট দ্বারা "সম্ভাব্য -> 0.000 ডিগ্রি" বলা হয়েছে is আমাকে ঠিক করতে হবে
ম্যাটস্টিল

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

আপনাকে নাথানকে ধন্যবাদ। আউটপুটটি আরও অনেক তথ্য দেখায়: এগুলি ডিবাগের উদ্দেশ্যে এবং আমি ইচ্ছাকৃতভাবে তাদের ঠিক করতে পেরেছি
ম্যাটস্টিল

দ্বিতীয় বাগ: একটি উত্সাহী "অসম্ভব। (কোনও লাইন নেই) এন = 8, এম = 6, আর = 0 সি = 6" সঠিক উত্তরের ঠিক পরে লেখা হয়েছে "0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2: অজানা। (কোনও লাইন নেই) এন = 8, এম = 6, আর = 0 সি = 6 "।
ম্যাটস্টিল

দুটি বাগ স্থির করা হয়েছে: সমস্ত ক্ষেত্রে এখন জরিমানা চলছে।
ম্যাটস্টিল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.