Mini Golf Code Golf


18

To jest minigolf:

Zewnętrzna granica to okrąg o promieniu 10 i środku (0,0). Wewnętrzna granica to okrąg o promieniu 3 i środku (0,5). Trójnik ma wartość (0, -8). Załóżmy, że piłka jest tylko punktem o promieniu 0.

Dynamika piłki podlega następującym zasadom:

  • Piłka jest początkowo uderzona energią 50 i pod danym kątem.

    • Kąt jest odwrócony w układzie współrzędnych kartezjańskich, więc 0 ° oznacza bezpośrednio w prawo, 90 ° jest bezpośrednio w górę i tak dalej.
  • Gdy piłka uderza w krawędź wewnętrznego lub zewnętrznego koła, odbija się od koła, stosując zasadę odbicia.

    • Kąt zderzenia z okręgiem w tym punkcie jest równy kątowi odbicia. (Tutaj kąty odnoszą się do linii stycznej koła w punkcie zderzenia).

    • Aby uzyskać wyjaśnienie, zobacz to lub to (w notacji drugiego łącza R_0 = 0 w tym wyzwaniu).

  • Piłka traci energię podczas ruchu.

    • Za każdą jednostkę ziemi, którą pokrywa, traci 1 jednostkę energii.

    • Za każdym razem, gdy odbija się od ściany, traci 5 jednostek energii.

  • Piłka zatrzymuje się, gdy skończy jej się energia lub wpadnie do dziury.

    • Jeśli piłka uderzy w ścianę z <= 5 jednostek energii, zatrzymuje się.

    • Wpada do dziury, jeśli ma energię <10, gdy znajduje się w odległości 1 od dziury, w przeciwnym razie nadal się porusza.

Wyzwanie

Biorąc pod uwagę współrzędne xy otworu, zwróć kąt, pod którym możesz uderzyć piłkę, aby piłka wpadła do otworu (jeśli taki kąt istnieje).

Wejście

Jako dane wejściowe weź współrzędne xiy osi środka otworu w dowolnej dogodnej formie. Dane wejściowe mogą być pobierane z STDIN (lub najbliższej alternatywy), parametrów wiersza poleceń lub argumentów funkcji.

Wynik

Wydrukuj lub zwróć kąt w stopniach, pod którym można uderzyć piłkę z trójnika, tak aby wpadła do otworu. Jeśli taki kąt istnieje, dane wyjściowe powinny mieścić się w zakresie [0, 360), w przeciwnym razie dane wyjściowe powinny wynosić -1.


Możesz określić, w jaki sposób powinny być odczytywane wartości xiy (standardowe wejście, argument funkcji itp.).
Loovjo,

Co należy zwrócić, jeśli taki kąt nie istnieje?
Alex A.,

Określmy, że funkcja zwróci wartość w [0,360), jeśli istnieje rozwiązanie, i w przeciwnym razie zwróci -1.
Eric Brooks,

Dokonałem kilku zmian. Jeśli nie pasuje do twoich zamiarów, cofnij edycję.
Alex A.,

Czy możesz również podać co najmniej jeden przypadek testowy?
Alex A.,

Odpowiedzi:


4

C 415 430

EDYCJA: Jak wspomniano @Winny, wartości wyjściowe powyżej 255 nie są możliwe, więc musiałem zwiększyć ten rozmiar kodu, aby wydrukować wartości do 360.

Przyjmuje 2 (i tylko 2) wejścia wiersza poleceń (xy) jako ints. Odpowiedź w stopniach jest drukowana lub -1, jeśli nie ma stopnia.

#include <math.h>
#define E(z) {if((e-=5)<0)break;q=n/sqrt(n*n+pow(m-z,2));w=(m-z)/sqrt(n*n+pow(m-z,2));d=(t=d)*(1-2*q*q)-2*f*q*w;f=f*(1-2*w*w)-2*t*q*w;}
main(a,v)char**v;{float D=.01,e,d,f,n,m,p=.0174,q,t,w;a-=4;while(++a<360){n=0,m=-8,d=D*cos(a*p),f=D*sin(a*p),e=50;while(e>0){if((pow(n-atoi(v[1]),2)+pow(m-atoi(v[2]),2)<1)&(e<10)&&printf("%d",a))return;n+=d,m+=f,e-=D;if(n*n+m*m>100)E(0)if(n*n+pow(m-5,2)<9)E(5)}}puts("-1");}

Dawny.

>./golfed 0 2; echo $?
90
>./golfed 0 10; echo $?
0
>./golfed -2 -7; echo $?
12

Pierwszy raz golfista; prawdopodobnie można by go trochę poprawić. Jeśli potrzebujemy większej precyzji, mam wersję, która przyjmuje xy i zwraca kąt przy podwójnej pracy z precyzją 0,01 stopnia przy 449 znakach.

Wersja do odczytu:

#include <math.h>
int main(int argc, char** argv)
{
    // p is roughly pi/180 and q, t, and w are temp vars
    float Delta=.01, energy, delta_x, f(delta_y), n(cur_x), m(cur_y), p=.0174, q, t, w;
    argc -= 4; /*using argc as int for angle*/
    // iterate through each degree
    while (++argc < 360)
    {
        n=0, m=-8, d=D*cos(a*p), f=D*sin(a*p), e=50;
        // then move in discrete .01 steps
        while (e > 0)
        {
            // check to see if we're inside the hole
            if ((pow(n-atoi(v[1]),2) + pow(m-atoi(v[2]),2) < 1) 
                & (e<10) && printf("%d",a)) return;
            // move forward
            n += d, m += f, e -= D;
            // check if we've hit the outer wall
            if (n * n + m * m > 100)
            {
                // if too slow, finish this iteration
                // if not, find reflection vector
                if ((e -= 5) < 0) break;
                q = n / sqrt(n * n + pow(m,2));
                w = (m) / sqrt(n * n + pow(m,2));
                d = (t = d) * (1 - 2 * q * q) - 2 * f * q * w;
                f = f * (1 - 2 * w * w) - 2 * t * q * w;
            }
            // check inner wall collision
            if (n * n + pow(m - 5,2) < 9)
            {
                // if too slow, finish this iteration
                // if not, find reflection vector
                if ((e -= 5) < 0) break;
                q = n / sqrt(n * n + pow(m - 5,2));
                w = (m - 5) / sqrt(n * n + pow(m - 5,2));
                d = (t = d) * (1 - 2 * q * q) - 2 * f * q * w;
                f = f * (1 - 2 * w * w) - 2 * t * q * w;
            }
        }
    }
    // if an angle not found, return -1
    puts("-1");
}

Nie sądzę, że możesz zwrócić wartości większe niż 255 za pośrednictwem exit(code). Testowane na Linux i FreeBSD przez echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?.
Winny
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.