Código de mini-golfe


18

Este é um buraco de minigolfe:

O limite externo é um círculo com raio 10 e centro (0,0). O limite interno é um círculo com raio 3 e centro (0,5). O tee está em (0, -8). Suponha que a bola seja apenas um ponto com raio 0.

A dinâmica da bola é governada pelas seguintes regras:

  • A bola é inicialmente atingida com energia 50 e com um determinado ângulo.

    • O ângulo é decrescente no sistema de coordenadas cartesianas, então 0 ° significa diretamente para a direita, 90 ° está diretamente para cima e assim por diante.
  • Quando a bola atinge a borda do círculo interno ou externo, ela ricocheteia usando a lei da reflexão.

    • O ângulo de colisão com o círculo nesse ponto é igual ao ângulo de reflexão. (Aqui, os ângulos são relativos à linha tangente do círculo no ponto de colisão.)

    • Para esclarecimentos, consulte isto ou isto (na notação do segundo link, R_0 = 0 neste desafio.)

  • A bola perde energia enquanto se move.

    • Para cada unidade de terra coberta, perde 1 unidade de energia.

    • Toda vez que bate em uma parede, perde 5 unidades de energia.

  • A bola para quando fica sem energia ou quando cai no buraco.

    • Se a bola bate em uma parede com <= 5 unidades de energia, ela para.

    • Ele cai no orifício se tiver energia <10 quando estiver dentro da distância 1 do orifício, caso contrário ele continuará se movendo.

Desafio

Dadas as coordenadas xy de um buraco, retorne um ângulo no qual você pode acertar a bola para que ela caia no buraco (se esse ângulo existir).

Entrada

Tome como entrada as coordenadas x e y do centro do furo, em qualquer forma conveniente. A entrada pode ser obtida de STDIN (ou alternativa mais próxima), parâmetros de linha de comando ou argumentos de função.

Resultado

Imprima ou retorne um ângulo em graus em que a bola pode ser atingida pelo tee, de forma que ela caia no buraco. Se esse ângulo existir, a saída deve estar no intervalo [0, 360); caso contrário, a saída deve ser -1.


Você pode especificar como os valores xey devem ser lidos (entrada padrão, argumento de função etc.).
Loovjo 18/07/2015

O que deve ser retornado se esse ângulo não existir?
Alex A.

Vamos especificar que a função retornará um valor em [0,360) se houver uma solução e retornará -1 caso contrário.
Eric Brooks

Fiz algumas edições. Se não corresponder à sua intenção, reverta a edição.
Alex A.

Além disso, você poderia fornecer pelo menos um caso de teste?
21415 Alex A.

Respostas:


4

C, 415 430

EDIT: Como o @Winny mencionou, os valores de saída acima de 255 não são possíveis, então tive que aumentar esse tamanho de código para imprimir valores até 360.

Assume 2 (e apenas 2) entradas da linha de comando (xy) como entradas. A resposta em graus é impressa ou -1 se não houver nenhum grau.

#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

Jogador de golfe pela primeira vez; provavelmente poderia ser melhorado bastante. Se precisarmos ter mais precisão, tenho uma versão que aceita xy e retorna o ângulo com dobras trabalhando com precisão de 0,01 graus a 449 caracteres.

Versão legível:

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

Eu não acho que você pode retornar valores maiores que 255 via exit(code). Testado em Linux e FreeBSD via echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?.
Winny
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.