Bir nokta listesi verilen karenin dönüşünü belirleme


19

Bu meydan okumada size bir puan listesi verilecektir. Bu noktalar hayali bir karenin çevresinde yer alır . Amacınız:

  1. Mümkünse, 0'ın dikey ve yatay çizgileri olan bir kareyi temsil ettiği [0, 90) 'dan bir değer olacak karenin dönüşünü yazdırın. Dönüş saat yönünün tersine sayılan derecelerde verilecektir.
  2. Karenin dönüşü belirsizse (sadece 2 puan verilmesi gibi), "Bilinmeyen" yazısını yazdırın
  3. Noktalar verilen bir kare oluşturmak mümkün değilse, "İmkansız"

Size verilen puanların benzersiz olduğu garanti edilir ve belirli bir sırada değildir. Listeye girmek istediğiniz herhangi bir formatı kullanabilirsiniz, ancak örneklerim için puanlarım formatta x,yve boşlukla ayrılmış olacaktır. Sayılar kayan noktalı sayılardır ve dilinizin işleyebileceği bir aralıkta olduğunu varsayabilirsiniz. Çıktınız en az 3 ondalık basamağa kadar doğru olmalı ve dilinizin kayan nokta sayılarını mükemmel bir doğrulukla ele aldığını varsayın.

İşte bazı test örnekleri (kolay görselleştirme için tam sayıları kullanarak bunların çoğunu yaptım, ancak programınız kayan noktaları işlemelidir):

Bilinmeyen:

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

İmkansız:

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

Mümkün (belirtilmemişse 0 döndürmelidir):

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 

Bazı ilginç test senaryolarını kaçırmış olabilirim. Öyleyse, lütfen eklemek için yorum yapın.

Bu kod golf, bu yüzden en kısa kod kazanır!


Gerekli minimum doğruluk var mı? Çıktı yanlış sayılmadan önce doğru cevaptan ne kadar uzakta olabilir?
trichoplax

@trichoplax dilinizin kayan noktalı sayıların uygulanmasına izin verdiği kadar doğru olmalıdır.
Nathan Merrill

Bu, 2 olası yaklaşım varsa ve biri dilinizde biraz daha doğru bir sonuç verirse, en doğru yaklaşımın kullanılması gerektiği anlamına mı geliyor?
trichoplax

@trichoplax evet.
Nathan Merrill

2
@NathanMerrill Daha doğru bir yaklaşımın var olup olmadığını nasıl anlarım? 4 veya 6 ondalık basamak gibi sabit bir minimum doğruluk gerektirmenin daha anlamlı olacağını düşünüyorum. Her ne kadar girdinin kayan nokta gösteriminin yanlışlıklarının birçok örneği imkansız kılıp kılmadığından emin değilim. Belki rasyonel ya da tamsayı girdisi bunun için daha iyi olurdu.
Martin Ender

Yanıtlar:


6

Rev 1: Yakut, 354 bayt

blutorange sayesinde daha fazla golf.

->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'}

Yakut, 392 bayt

->(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
}

Algoritma aşağıdaki gibidir:

- Rasgele bir nokta seçin (birincisi) ve başlangıç ​​noktasına taşıyın (bu noktanın koordinatlarını listedeki tüm noktalardan çıkarın).

- Meydanın tüm dönüşlerini 0.001 derecelik artışlarla 360 dereceye kadar deneyin.

- Belirli bir döndürme için, tüm noktalar y ekseninin üzerindeyse, en düşük ve en soldaki noktayı içeren tüm noktaların etrafındaki mümkün olan en küçük kareyi çizin.

-Tüm noktaların kenarda olup olmadığını kontrol edin. Bu, her noktayı alan, tüm kenarlardan kare mesafeleri bulan ve bunları bir araya getiren yumuşak bir hesaplama ile yapılır. Bu, evet / hayır yanıtı yerine iyi bir uyum sağlar. Bu ürünün ^ 8 kenar uzunluğuna bölünmesi 1E-9'dan daha az ise bir çözüm bulunduğu anlaşılmaktadır. Uygulamada bu bir tolerans derecesinden daha azdır.

-En iyi uyum mod 90 derece alınır ve doğru açı olarak rapor edilir.

Şu anda 100'den fazla çözüm bulunursa kod belirsiz bir değer döndürür (0,001 derece çözünürlükte. 0,1 tolerans derecesi.)

ilk tam çalışma fonksiyonu, test programında

Hızı makul hale getirmek için çözünürlüğü gereken çözünürlüğün 1 / 10'unda bıraktım. En son test durumunda 0.01 derecelik bir hata var.

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)])

golf sürümü, spec ile uyumlu çözünürlük, test programında çağrı başına yaklaşık bir dakika sürer.

Son test durumunda hala 0.001 derece sinir bozucu bir hata var. Çözünürlüğü daha da artırmak muhtemelen ortadan kaldıracaktır.

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)])

Yaklaşık% 30 daha fazla kod için bu algoritmanın hızlı çalışacak şekilde uyarlanabileceğini unutmayın: sonlu sayıda çözümün olduğu durumlarda, kenarlardan birinin bir küp boyunca düz olduğu açıktır, bu yüzden gerçekten denememiz gereken tek şey bu açılardır. her köşe noktasına karşılık gelir. Sınırsız sayıda çözüm bulunmadığını kontrol etmek için biraz kıpır kıpır yapmak da gerekli olacaktır.


İkinci test vakasını düzelttim, teşekkür ederim
Nathan Merrill

@NathanMerrill, 0,0 1,0 2,0 1,20,0 ... 2,2 diyagonal bir kare için gözden geçirilmiş dava hala mümkündür. Ben denedim, ve ayrıca 0,0 1,0 2,0 1,1(ikincisi gerçekten imkansız.) Başka bir nokta: kabul edilebilir veya kabul edilemez olduğunu düşünüyor kodum sadece tek bir nokta verildiğinde bilinmeyen yerine imkansız döner? Golf oynamaya başlamadan önce bir cevabı takdir ediyorum.
Level River St

Yapmak istedim 1,1 . 1,2Oraya nasıl geldiğinden emin değilim . Kabul edilemez.
Nathan Merrill

Bunu en az 354 bayta indirebilmeniz gerekir: pastebin.com/jsgwMKQF
indirebilmeniz gerekir

@blutorange ipuçları için teşekkürler! Ruby'de yeniyim ve golf oynamakta zorlanıyorum. Çok fazla şey bıraktım if..endçünkü Ruby'deki iç içe üçlü operatörlerle korkunç bir sorunum var. Görüyorum ki bunu kullanarak dolaşıyorsun &&.
Level River St

6

Perl

Merhaba, işte benim alçakgönüllü düşüncem. Test senaryoları dosyanın altındaki DATA akışına yerleştirilir. Algoritma bir deneme-hata yaklaşımı ile büyüdü.
Geniş bir sezgisel yaklaşım olduğunu itiraf ediyorum, ama gerçekten hızlı: tüm vakaları anında çözüyor .
Bazı hatalar olacağının farkındayım, ancak şimdiye kadar tüm test senaryolarına doğru cevaplar veriyor.
Ayrıca en kısa kodun kazandığının da farkındayım , ancak bu terimin en hızlı anlamında en kısa olandan eminim .

İşte algoritma

  1. noktaları inceleyin ve iki nokta arasındaki her segment için eğim, uzunluk, x kesme, y kesme

  2. düz çizgiler (yani üç nokta veya iki bitişik segment) ve farklı olası eğimler bulun (bunları döndürün). Her satırda bulunan en uzun segmenti takip edin.

  3. bir segment ile üçüncü bir nokta arasındaki tüm mesafeleri bulun (bu, 4. maddede kullanılmalıdır). Sıfır olmayan minimum mesafeyi takip edin.

  4. herhangi bir dört nokta için (kabaca bir dikdörtgen) iç noktaları bulun

Çözümleri göster:

A. Bir veya daha fazla iç nokta varsa "İmkansız" deyin.

B. Bir Satır:

  • İç nokta olmadan tek bir satırdaki noktaların çoğunda "Mümkün" deyin

  • Noktaya çok yakın noktalar olması durumunda "İmkansız" deyin

    C. İki satır:

  • Tek bir olası dönüş olduğunda "Mümkün" deyin

  • Birden fazla dönüş olduğunda "İmkansız" deyin

    D. Çizgi yok: 90 ° döndürme segmentine uyan dönüşü bulun

  • Sadece biri uygunsa veya nokta sığabiliyorsa "Mümkün" deyin.

  • Birden fazla nokta varsa ve nokta kadar değilse "İmkansız" deyin

  • Dönüş uygunsa "Bilinmeyen" deyin.

İşte kod (bilinen tüm hatalar çözüldü)

#!/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

Ve işte onun çıkışı

# 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

Saygılarımızla.

Matteo.


İşte ilk hata: davanız 0,0 1,0 2,0 1,1 (İmkansız) senaryom tarafından "Mümkün. -> 0.000 derece" denir. Düzeltmek zorundayım
Mattsteel

Bu çözümü gerçekten çok seviyorum. Kod golf hakkında çok fazla endişelenmeyin, meydan okumanın asıl amacı bu değildir ve ödülü alacak kişi olması gerekmez.
Nathan Merrill

Çıktı çok daha fazla bilgi gösteriyor: bunlar hata ayıklama amaçlı ve onları düzeltmek için bilerek bıraktım
Mattsteel

İkinci hata: sahte "İmkansız. (Satır yok) n = 8, m = 6, r = 0 c = 6" doğru cevaptan hemen sonra yazılır "0,1 0,2 1,0 1,3 2,0 2,3 3,1 3,2: Bilinmiyor. (Satır yok) n = 8, m = 6, r = 0 c = 6 ".
Mattsteel

İki hata düzeltildi: tüm vakalar artık iyi çalışıyor.
Mattsteel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.