Golf Kode Mini Golf


18

Ini adalah lubang golf mini:

Batas luar adalah lingkaran dengan jari-jari 10 dan pusat (0,0). Batas dalam adalah lingkaran dengan jari-jari 3 dan pusat (0,5). Tee berada di (0, -8). Anggap bola hanya sebuah titik dengan jari-jari 0.

Dinamika bola diatur oleh aturan berikut:

  • Bola awalnya dipukul dengan energi 50, dan dengan sudut tertentu.

    • Sudut berada dalam tekanan dalam sistem koordinat Cartesius, jadi 0 ° berarti langsung ke kanan, 90 ° langsung ke atas, dan seterusnya.
  • Ketika bola mengenai tepi lingkaran dalam atau luar, bola memantul dari lingkaran menggunakan hukum refleksi.

    • Sudut tabrakan dengan lingkaran pada titik itu sama dengan sudut pantulan. (Di sini sudut relatif terhadap garis singgung lingkaran pada titik tabrakan.)

    • Untuk klarifikasi, lihat ini atau ini (dalam notasi tautan kedua, R_0 = 0 dalam tantangan ini.)

  • Bola kehilangan energi saat bergerak.

    • Untuk setiap unit tanah yang dicakupnya, ia kehilangan 1 unit energi.

    • Setiap kali memantul dari dinding, ia kehilangan 5 unit energi.

  • Bola berhenti ketika kehabisan energi atau ketika jatuh ke dalam lubang.

    • Jika bola mengenai dinding dengan <= 5 unit energi, bola akan berhenti.

    • Ia jatuh ke dalam lubang jika memiliki energi <10 ketika berada dalam jarak 1 dari lubang, jika tidak ia terus bergerak.

Tantangan

Dengan koordinat xy lubang, kembalikan sudut di mana Anda bisa memukul bola agar bola jatuh ke dalam lubang (jika ada sudut seperti itu).

Memasukkan

Ambil sebagai input koordinat x dan y dari pusat lubang dalam bentuk apa pun yang nyaman. Input dapat diambil dari STDIN (atau alternatif terdekat), parameter baris perintah, atau argumen fungsi.

Keluaran

Cetak atau kembalikan sudut dalam derajat di mana bola bisa mengenai tee sehingga bola akan jatuh ke dalam lubang. Jika ada sudut seperti itu, output harus dalam kisaran [0, 360), jika tidak maka output harus -1.


Anda mungkin ingin menentukan bagaimana nilai x dan y harus dibaca (input standar, argumen fungsi, dll.).
Loovjo

Apa yang harus dikembalikan jika tidak ada sudut seperti itu?
Alex A.

Mari kita tentukan bahwa fungsi akan mengembalikan nilai dalam [0,360) jika ada solusi, dan mengembalikan -1 jika tidak.
Eric Brooks

Saya membuat beberapa suntingan. Jika tidak sesuai dengan keinginan Anda, silakan putar kembali hasil edit.
Alex A.

Juga, bisakah Anda memberikan setidaknya satu test case?
Alex A.

Jawaban:


4

C, 415 430

EDIT: Seperti yang disebutkan @Winny, nilai keluar di atas 255 tidak mungkin, jadi saya harus menambah ukuran kode ini untuk mencetak nilai hingga 360.

Mengasumsikan 2 (dan hanya 2) input baris perintah (xy) sebagai int. Jawaban dalam derajat dicetak atau -1 jika tidak ada gelar.

#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

Pegolf waktu pertama; mungkin bisa diperbaiki sedikit. Jika kita perlu memiliki lebih banyak presisi, saya memiliki versi yang mengambil xy dan mengembalikan sudut dengan berfungsi ganda dengan .01 derajat presisi pada 449 karakter.

Versi yang dapat dibaca:

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

Saya tidak berpikir Anda dapat mengembalikan nilai yang lebih besar dari 255 via exit(code). Diuji di Linux dan FreeBSD via echo 'int main(){return 300;}' > test.c && cc test.c && ./a.out; echo $?.
Winny
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.