Міні-гольф-код Гольф


18

Це отвір для міні-гольфу:

Зовнішня межа - це коло з радіусом 10 і центром (0,0). Внутрішня межа - це коло з радіусом 3 та центром (0,5). Трійник знаходиться на рівні (0, -8). Припустимо, м'яч - це лише точка з радіусом 0.

Динаміка балу регулюється такими правилами:

  • Куля спочатку потрапляє з енергією 50, і з заданим кутом.

    • У декартовій системі координат кут занепадає, тому 0 ° означає прямо вправо, 90 ° - прямо вгору тощо.
  • Коли куля потрапляє на край внутрішнього чи зовнішнього кола, вона відскакує від кола, використовуючи закон відображення.

    • Кут зіткнення з колом у цій точці дорівнює куту відбиття. (Тут кути відносно дотичної лінії кола в точці зіткнення.)

    • Для уточнення дивіться це чи це (у позначенні другого посилання R_0 = 0 у цьому виклику.)

  • М'яч втрачає енергію під час руху.

    • За кожну одиницю землі, яку вона покриває, вона втрачає 1 одиницю енергії.

    • Щоразу, коли вона відбивається від стіни, вона втрачає 5 одиниць енергії.

  • Куля зупиняється або коли у неї не вистачає енергії, або коли вона потрапляє в отвір.

    • Якщо куля потрапила в стіну з <5 одиницями енергії, вона зупиняється.

    • Він потрапляє в отвір, якщо у нього енергія <10, коли він знаходиться в межах відстані 1 отвору, інакше він продовжує рухатися.

Виклик

Враховуючи координати xy отвору, поверніть кут, під яким можна вдарити м'яч, щоб куля потрапила в отвір (якщо такий кут існує).

Вхідні дані

Візьміть за введення координати x- і y центру отвору в будь-якій зручній формі. Введення може бути взято з STDIN (або найближчої альтернативи), параметрів командного рядка або аргументів функції.

Вихід

Роздрукуйте або поверніть кут у градусах, при якому куля може вдаритись по трійнику, щоб куля потрапила в отвір. Якщо такий кут існує, вихід повинен бути в діапазоні [0, 360), інакше вихід повинен бути -1.


Ви можете вказати, як слід читати значення x і y (стандартний ввід, аргумент функції тощо).
Loovjo

Що слід повернути, якщо такого кута немає?
Алекс А.

Зазначимо, що функція поверне значення в [0,360), якщо є рішення, і повернемо -1 в іншому випадку.
Ерік Брукс

Я зробив пару правок. Якщо це не відповідає вашим намірам, відконайте редагування.
Олексій А.

Також ви могли б надати принаймні один тестовий випадок?
Алекс А.

Відповіді:


4

C, 415 430

EDIT: Як і згадував @Winny, значення виходу вище 255 неможливі, тому мені довелося збільшити цей розмір коду, щоб надрукувати значення до 360.

Передбачає 2 (і лише 2) введення командного рядка (xy) як ints. Відповідь у градусах друкується або -1, якщо ступеня не існує.

#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");}

Вих.

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

Перший раз гольфіст; можливо, можна було б трохи покращити. Якщо нам потрібно мати більш точність, у мене є версія, яка займає xy і повертає кут з подвоєнням, що працює з точністю .01 градуса при 449 знаках.

Читаема версія:

#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");
}

Я не думаю, що ви можете повернути значення, більші за 255 через exit(code). Тестовано на Linux та FreeBSD через echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?.
Вінні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.