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 এটি প্রতিটি জোড়ের সাথে মিলিত হয়। অসীম অনেকগুলি সমাধান নেই এমন কি না তা পরীক্ষা করার জন্য কিছুটা উইগলিং করাও দরকার।