Mini Golf Code Golf


18

Ceci est un mini-golf:

La limite extérieure est un cercle de rayon 10 et de centre (0,0). La limite intérieure est un cercle de rayon 3 et de centre (0,5). Le tee est à (0, -8). Supposons que la balle n'est qu'un point de rayon 0.

La dynamique du ballon est régie par les règles suivantes:

  • La balle est d'abord frappée avec une énergie de 50, et avec un angle donné.

    • L'angle est en dégressivité dans le système de coordonnées cartésiennes, donc 0 ° signifie directement à droite, 90 ° est directement vers le haut, etc.
  • Lorsque la balle touche le bord du cercle intérieur ou extérieur, elle rebondit sur le cercle en utilisant la loi de réflexion.

    • L'angle de collision avec le cercle à ce point est égal à l'angle de réflexion. (Ici, les angles sont relatifs à la tangente du cercle au point de collision.)

    • Pour plus de précisions, voir ceci ou cela (dans la notation du deuxième lien, R_0 = 0 dans ce défi.)

  • La balle perd de l'énergie lorsqu'elle se déplace.

    • Pour chaque unité de sol qu'il couvre, il perd 1 unité d'énergie.

    • Chaque fois qu'il rebondit sur un mur, il perd 5 unités d'énergie.

  • La balle s'arrête soit lorsqu'elle manque d'énergie, soit lorsqu'elle tombe dans le trou.

    • Si la balle frappe un mur avec <= 5 unités d'énergie, elle s'arrête.

    • Il tombe dans le trou s'il a une énergie <10 lorsqu'il se trouve à la distance 1 du trou, sinon il continue de bouger.

Défi

Étant donné les coordonnées xy d'un trou, renvoyez un angle auquel vous pouvez frapper la balle pour que la balle tombe dans le trou (si un tel angle existe).

Contribution

Prenez en entrée les coordonnées x et y du centre du trou sous n'importe quelle forme pratique. L'entrée peut provenir de STDIN (ou de l'alternative la plus proche), des paramètres de ligne de commande ou des arguments de fonction.

Production

Imprimer ou renvoyer un angle en degrés auquel la balle peut être frappée du tee de telle sorte que la balle tombe dans le trou. Si un tel angle existe, la sortie doit être dans la plage [0, 360), sinon la sortie doit être -1.


Vous voudrez peut-être spécifier comment les valeurs x et y doivent être lues (entrée standard, argument de fonction, etc.).
Loovjo

Que faut-il retourner s'il n'existe pas un tel angle?
Alex A.

Spécifions que la fonction renverra une valeur dans [0,360) s'il y a une solution, et renverra -1 sinon.
Eric Brooks

J'ai fait quelques modifications. Si cela ne correspond pas à votre intention, veuillez annuler la modification.
Alex A.

Pouvez-vous également fournir au moins un cas de test?
Alex A.

Réponses:


4

C, 415 430

EDIT: Comme @Winny l'a mentionné, les valeurs de sortie supérieures à 255 ne sont pas possibles, j'ai donc dû augmenter cette taille de code afin d'imprimer des valeurs jusqu'à 360.

Suppose 2 (et seulement 2) entrées de ligne de commande (xy) en tant qu'ent. La réponse en degrés est imprimée ou -1 si aucun degré n'existe.

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

Ex.

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

Golfeur pour la première fois; pourrait probablement être amélioré un peu. Si nous devons avoir plus de précision, j'ai une version qui prend en xy et retourne l'angle avec des doubles travaillant avec une précision de 0,01 degré à 449 car.

Version lisible:

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

Je ne pense pas que vous puissiez retourner des valeurs supérieures à 255 via exit(code). Testé sous Linux et FreeBSD via echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?.
Winny
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.