वर्ग की रोटेशन का निर्धारण अंक की एक सूची दी


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 

मैं कुछ दिलचस्प परीक्षण मामलों को याद कर सकता हूं। यदि हां, तो कृपया उन्हें जोड़ने के लिए टिप्पणी करें।

यह कोड-गोल्फ है, इसलिए सबसे छोटा कोड जीतता है!


क्या न्यूनतम आवश्यक सटीकता है? सही उत्तर से कितनी दूर आउटपुट गलत होने से पहले ही हो सकता है?
ट्राइकोप्लाक्स

@trichoplax आपकी भाषा के फ्लोटिंग-पॉइंट संख्या के कार्यान्वयन के रूप में सटीक है।
नाथन मेरिल

क्या इसका मतलब यह है कि अगर 2 संभावित दृष्टिकोण हैं और कोई आपकी भाषा में थोड़ा अधिक सटीक परिणाम देता है, तो सबसे सटीक दृष्टिकोण का उपयोग किया जाना चाहिए?
ट्राइकोप्लाक्स

@trichoplax हाँ।
नाथन मेरिल

2
@NathanMerrill मैं (या कोई भी) कैसे जान सकता हूं कि क्या अधिक सटीक दृष्टिकोण मौजूद है? मुझे लगता है कि यह 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 डिग्री वेतन वृद्धि में उत्पत्ति के बारे में वर्ग के सभी रोटेशन 360 डिग्री के माध्यम से लें।

-एक दिए गए रोटेशन के लिए, यदि सभी बिंदु y अक्ष से ऊपर हैं, तो सभी बिंदुओं के आसपास सबसे छोटा संभव वर्ग खींचें, जिसमें सबसे कम और सबसे बाएं बिंदु शामिल हैं।

सभी बिंदु किनारे पर हैं, तो जाँच करें। यह एक नरम गणना के साथ किया जाता है जो प्रत्येक बिंदु को लेता है, सभी किनारों से वर्ग दूरी पाता है, और उन्हें एक साथ गुणा करता है। यह हां / ना में जवाब देने के बजाय एक अच्छा फिट देता है। यह व्याख्या की जाती है कि एक समाधान पाया जाता है यदि यह उत्पाद साइडलेंग्थ ^ 8 से विभाजित है, 1E-9 से कम है। व्यवहार में यह सहिष्णुता के एक डिग्री से कम है।

-सबसे अच्छा फिट 90 डिग्री लिया जाता है और सही कोण के रूप में रिपोर्ट किया जाता है।

वर्तमान में कोड अस्पष्ट का मान लौटाता है यदि 100 से अधिक समाधान पाए जाते हैं (0.001 डिग्री रिज़ॉल्यूशन पर। यह सहिष्णुता का 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 डिग्री की एक pesky त्रुटि है। आगे बढ़ते संकल्प शायद इसे खत्म कर देंगे।

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% अधिक कोड के लिए यह एल्गोरिथ्म तेजी से काम करने के लिए अनुकूलित किया जा सकता है: यह स्पष्ट है कि समाधान की एक सीमित संख्या के साथ मामलों में, किनारों में से एक एक क्यूब के साथ सपाट है, इसलिए हम सभी को वास्तव में प्रयास करना होगा उन कोणों कि प्रत्येक जोड़ी के अनुरूप हैं। यह जांचने के लिए भी बहुत कुछ करना आवश्यक होगा कि वहाँ अनंत समाधान नहीं हैं।


मैंने दूसरा टेस्ट केस तय किया, धन्यवाद
नाथन मेरिल

@NathanMerrill संशोधित मामला 0,0 1,0 2,0 1,2विकर्ण 0,0 ... 2,2 के एक वर्ग के लिए अभी भी संभव है। मैंने कोशिश की है, और यह भी 0,0 1,0 2,0 1,1(उत्तरार्द्ध वास्तव में असंभव है।) एक और बिंदु: क्या आप इसे स्वीकार्य या अस्वीकार्य मानते हैं कि मेरा कोड अज्ञात के बजाय असंभव है जब केवल एक बिंदु दिया जाता है? गोल्फ शुरू करने से पहले मैं एक उत्तर की सराहना करता हूं।
लेवल रिवर सेंट

मेरा मतलब था 1,1। यकीन नहीं होता कि 1,2वहां कैसे पहुंचा। यह स्वीकार्य नहीं है।
नाथन मेरिल

आपको इसे कम से कम 354 बाइट्स तक नीचे लाने में सक्षम होना चाहिए: pastebin.com/jsgwMKQF
blutorange

सुझावों के लिए @blutorange धन्यवाद! मैं रूबी के लिए नया हूं और कुछ मुश्किलों को झेल रहा हूं। मैंने बहुत कुछ छोड़ दिया if..endक्योंकि मुझे रूबी में नेस्टर्ड टर्नरी ऑपरेटरों के साथ भयानक परेशानी है। मैं देख रहा हूँ कि आप गोल है कि का उपयोग करके &&
लेवल रिवर सेंट

6

पर्ल

नमस्कार, यहाँ मेरा विनम्र व्यवहार है। परीक्षण मामलों को फ़ाइल के निचले भाग में डेटा स्ट्रीम में रखा जाता है । एल्गोरिथ्म एक कोशिश-त्रुटि दृष्टिकोण द्वारा विकसित हुआ है।
मैं मानता हूं कि यह एक व्यापक रूप से विधर्मी दृष्टिकोण है, लेकिन यह वास्तव में तेज है: यह सभी मामलों को तुरंत हल करता है
मुझे पता है कि कुछ कीड़े होंगे, लेकिन अब तक यह सभी परीक्षण मामलों को सही जवाब देता है।
मुझे यह भी पता है कि सबसे छोटा कोड जीतता है, लेकिन मुझे यकीन है कि यह सबसे तेज में सबसे छोटा है शब्द अर्थ में ।

यहाँ एल्गोरिथ्म है

  1. डॉट्स की जांच करें और प्रत्येक खंड के लिए दो डॉट्स रिकॉर्ड ढलान, लंबाई, एक्स-इंटरसेप्ट, वाई-इंटरसेप्ट के बीच रखें

  2. सीधी रेखाएं खोजें (अर्थात तीन बिंदु या दो समीपवर्ती खंड) और अलग-अलग संभव ढलान (उन्हें घुमाव कहें)। प्रत्येक पंक्ति में उपलब्ध सबसे लंबे खंड पर नज़र रखें।

  3. एक खंड और एक तीसरे बिंदु के बीच की सभी दूरियों को ढूंढें (इसका उपयोग बिंदु 4 के लिए किया जाना चाहिए)। न्यूनतम गैर-शून्य दूरी का ध्यान रखें।

  4. किसी भी चार बिंदुओं के लिए (एक आयत के समान) आंतरिक बिंदु खोजें

समाधान दिखाएं:

A. "असंभव" कहें यदि एक या अधिक आंतरिक बिंदु हैं।

B. एक पंक्ति:

  • आंतरिक बिंदुओं के बिना एक ही पंक्ति में अधिकांश डॉट्स के मामले में, "संभव" कहें

  • डॉट्स के मामले में भी लाइन के करीब, "असंभव" कहें

    C. दो लाइनें:

  • "संभव" कहें जब केवल एक ही संभव रोटेशन है

  • एक से अधिक घुमाव होने पर "असंभव" कहें

    डी। कोई रेखा नहीं: रोटेशन मिला जो इसके 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

और यहाँ इसका ouptut है

# 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 डिग्री" मेरी स्क्रिप्ट के लिए। मुझे ठीक करना होगा
मैटलस्टेल

मुझे वास्तव में यह समाधान पसंद है। कोड गोल्फ के बारे में बहुत ज्यादा चिंता न करें, यह वास्तव में चुनौती के बारे में नहीं है, और यह जरूरी नहीं है कि उस व्यक्ति को इनाम मिले।
नाथन मेरिल

धन्यवाद नाथन। आउटपुट बहुत अधिक जानकारी दिखाता है: ये डिबग उद्देश्य के लिए हैं और मैंने उन्हें जानबूझकर ठीक करने में सक्षम होने के लिए छोड़ दिया है
मैटलस्टेल

दूसरा बग: एक सहज "असंभव" (कोई रेखाएं) n = 8, m = 6, r = 0 c = 6 "सही उत्तर के बाद लिखा गया है" 0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2: अज्ञात। (कोई रेखाएँ) n = 8, m = 6, r = 0 c = 6 "।
मैथ्सटील

दो बग फिक्स: सभी मामले अब ठीक चल रहे हैं।
मैटस्टील
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.