Mini Golf Code Golf

18

3

This is a mini golf hole:

The outer boundary is a circle with radius 10 and center (0,0). The inner boundary is a circle with radius 3 and center (0,5). The tee is at (0,-8). Assume the ball is just a point with radius 0.

The dynamics of the ball are governed by the following rules:

  • The ball is initially hit with energy 50, and with a given angle.

    • The angle is in degress in the Cartesian coordinate system, so 0° means directly to the right, 90° is directly up, and so on.
  • When the ball hits the edge of the inner or outer circle, it bounces off the circle using the law of reflection.

    • The angle of collision with the circle at that point is equal to the angle of reflection. (Here angles are relative to the tangent line of the circle at the point of collision.)

    • For clarification, see this or this (in the notation of the second link, R_0 = 0 in this challenge.)

  • The ball loses energy as it moves.

    • For every unit of ground it covers, it loses 1 unit of energy.

    • Every time it bounces off a wall it loses 5 units of energy.

  • The ball stops either when it runs out of energy or when it falls into the hole.

    • If the ball hits a wall with <= 5 units of energy, it stops.

    • It falls into the hole if it has energy < 10 when it is within distance 1 of the hole, otherwise it keeps moving.

Challenge

Given the x-y coordinates of a hole, return an angle at which that you can hit the ball in order for the ball to fall into the hole (if such an angle exists).

Input

Take as input the x- and y-coordinates of the center of the hole in any convenient form. Input may be taken from STDIN (or closest alternative), command line parameters, or function arguments.

Output

Print or return an angle in degrees at which the ball can be hit from the tee such that the ball will fall into the hole. If such an angle exists, the output should be in the range [0, 360), otherwise the output should be -1.

Eric Brooks

Posted 2015-07-18T11:19:21.230

Reputation: 293

You might want to specify how the x and y values should be read (standard input, function argument etc.). – Loovjo – 2015-07-18T20:22:54.413

What should be returned if no such angle exists? – Alex A. – 2015-07-20T20:58:47.710

Let's specify that the function will return a value in [0,360) if there is a solution, and return -1 otherwise. – Eric Brooks – 2015-07-20T21:57:39.883

I made a couple of edits. If it doesn't match your intent, please roll back the edit. – Alex A. – 2015-07-21T17:22:39.357

Also, could you provide at least one test case? – Alex A. – 2015-07-21T17:26:15.283

I'll provide one later today. – Eric Brooks – 2015-07-23T11:59:28.527

It seems to me that the simplest thing is just to aim the ball at the hole, avoiding all the rebound rules. Or am I missing something? – Level River St – 2015-07-24T13:20:23.737

I think there are two complications with that: 1. some locations can't be accessed with a straight line (because of the barrier) and 2. if you haven't yet rebounded you almost certainly have too much energy – Eric Brooks – 2015-07-24T19:08:59.230

Answers

4

C, 415 430

EDIT: Like @Winny mentioned, exit values above 255 aren't possible, so I had to increase this code size in order to print values up to 360.

Assumes 2 (and only 2) command-line inputs (x y) as ints. Answer in degrees is printed or -1 if no degree exists.

#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

First time golfer; could probably be improved quite a bit. If we need to have more precision, I have a version that takes in x y and returns the angle with doubles working with .01 degree precision at 449 chars.

Readable version:

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

somesortofguy203

Posted 2015-07-18T11:19:21.230

Reputation: 56

I don't think you can return values larger than 255 via exit(code). Tested on Linux and FreeBSD via echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?. – Winny – 2015-07-28T02:36:55.233