Визначення обертання квадрата дано список точок


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 буде настільки точним, наскільки дозволяє ваша мова з числом плаваючої крапки.
Натан Меррілл

Чи означає це, що якщо є два можливі підходи і один дає трішки більш точний результат у вашій мові, слід використовувати найточніший підхід?
трихоплакс

@trichoplax так.
Натан Меррілл

2
@NathanMerrill Як я (або хтось) дізнається, чи існує більш точний підхід? Я думаю, було б більше сенсу просто вимагати фіксованої мінімальної точності, як-от 4 чи 6 знаків після коми. Хоча я навіть не впевнений, чи неточності представлення вхідних даних з плаваючою комою роблять багато прикладів неможливими. Можливо, для цього було б краще раціональне чи ціле введення.
Мартін Ендер

Відповіді:


6

Ред. 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 градуса. Подальше збільшення резолюції, ймовірно, усуне її.

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..ends, тому що у мене страшні проблеми з вкладеними потрійними операторами в Ruby. Я бачу, ви це зробили, використовуючи &&.
Рівень р. Св.

6

Perl

Здрастуйте, ось мій скромний вислів. Тестові приклади розміщуються в потоці DATA внизу файлу. Алгоритм виріс на основі спроби помилки.
Я визнаю, що це широкий евристичний підхід, але це дуже швидко: він вирішує всі випадки миттєво .
Я знаю, що буде помилок, але до цих пір він дає правильні відповіді на всі тестові випадки.
Я також усвідомлюю, що найкоротший код виграє, але я впевнений, що це один із найкоротших у найшвидшому значенні цього терміна.

Ось алгоритм

  1. вивчіть точки і для кожного сегмента між двома точками записуйте нахил, довжину, х-перехоплення, у-перехоплення

  2. знайти прямі лінії (тобто три крапки або два суміжні відрізки) та окремі можливі нахили (скажімо, їх обертання). Слідкуйте за найдовшим сегментом, доступним у кожному рядку.

  3. знайти всі відстані між відрізком і третьою точкою (це слід використовувати для точки 4). Слідкуйте за мінімальною ненульовою дистанцією.

  4. для будь-яких чотирьох крапок (грубо прямокутника) знайдіть внутрішні точки

Показати рішення:

А. Скажіть "Неможливо", якщо є одна чи більше внутрішніх крапок.

B. Один рядок:

  • Якщо більшість крапок в одній лінії без внутрішніх крапок, скажіть "Можливо"

  • Якщо точки занадто близькі до прямої, скажіть "Неможливо"

    C. Два рядки:

  • Скажіть "Можливо", коли можливе лише одне обертання

  • Скажіть "Неможливо", коли обертання більше

    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

З повагою

Маттео.


Ось перша помилка: ваш випадок 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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.