Bermain Biliar

17

Dalam kode golf ini, Anda harus menentukan arah tembakan terpendek yang hits persis n bantal sebelum jatuh ke dalam saku.

Meja biliar adalah meja biliar 6 saku dengan karakteristik sebagai berikut:

  • Dimensi adalah variabel ( a x b )
  • Tanpa gesekan: bola akan bergulir selamanya hingga jatuh ke dalam saku
  • Ukuran kantong dan bola hampir nol. Ini berarti bahwa bola akan jatuh di saku hanya jika mereka memiliki posisi yang sama.
  • Bola ditempatkan di lubang kiri bawah di awal (tetapi tidak jatuh di dalamnya)

3 bantal

Buat program atau fungsi penuh yang mengambil dimensi ( a , b ) dari tabel dan jumlah bantal untuk menekan n sebagai input dan mengembalikan sudut dalam derajat jalur terpendek yang memukul tepat n bantal sebelum jatuh ke saku.

  • a > 0
  • b > 0
  • 0 <= n <10000000
  • 0 < alpha <90 (dalam derajat) presisi: setidaknya 10 ^ -6

contoh:

dengan a = 2, b = 1, n = 1 ada tiga jalur yang mungkin: (1) (2) (3) pada gambar berikut. angka (1) adalah yang terpendek sehingga output harus atan (2) = 63.43494882292201 derajat

1 bantal

Solusi untuk a = 2, b = 1, n = 4 adalah atan (4/3) = 53.13010235415598 derajat

4 bantal

sampel uji:

a = 2,    b = 1,    n = 1,       -> alpha = 63.43494882292201
a = 2,    b = 1,    n = 2,       -> alpha = 71.56505117707799
a = 2,    b = 1,    n = 3,       -> alpha = 75.96375653207353
a = 2,    b = 1,    n = 4,       -> alpha = 53.13010235415598
a = 2,    b = 1,    n = 5,       -> alpha = 59.03624346792648
a = 2,    b = 1,    n = 6,       -> alpha = 81.86989764584403
a = 4.76, b = 3.64, n = 27,      -> alpha = 48.503531644784466
a = 2,    b = 1,    n = 6,       -> alpha = 81.86989764584403
a = 8,    b = 3,    n = 33,      -> alpha = 73.24425107080101
a = 43,   b = 21,   n = 10005,   -> alpha = 63.97789961246943

Ini golf kode / biliar: kode terpendek menang!

Damien
sumber
Apakah bola harus tepat memukul nbantal, atau setidaknya n bantal?
Peter Taylor
@PeterTaylor persisnya bantal
Damien
bukankah jalan terpendek selalu bolak-balik antara sisi kiri atas dan bawah dan kemudian ke salah satu lubang tengah?
Eumel
tidak, lihat contoh 2 1 4. Jalur ini adalah sqrt (25) = 5 panjang sedangkan solusi Anda adalah sqrt (26)
Damien

Jawaban:

11

Python 2.7, 352 344 281 byte

from math import*
def l(a,b,n):
 a*=1.;b*=1.
 r=set()
 for i in range(1,n+3):
  t=[]
  for k in range(1,i):
   for h in[0,.5]:
    x=(i-k-h)
    if 1-(x/k in r):r.add(x/k);t+=(x*a,k*b),
 d=(a*n+1)**2+(b*n+1)**2
 for x,y in t:
  if x*x+y*y<d:d=x*x+y*y;o=degrees(atan(y/x))
 return o
  • -16 byte berkat @Dschoni

Penjelasan: alih-alih menghitung hit bantal, saya menambahkan n tabel dan mengambil lubang baru sebagai valid: billard Perbatasan hitam / lubang adalah yang asli, perbatasan hijau / lubang adalah valid untuk n = 1, perbatasan merah / lubang adalah valid untuk n = 2 dan seterusnya. Lalu saya menghapus lubang yang tidak valid (misalnya panah biru untuk n = 1). Saya akan memiliki daftar lubang yang valid dan koordinatnya, lalu saya menghitung jaraknya dari titik awal, dan kemudian sudut jarak yang lebih kecil.
Catatan:
a = 4.76, b = 3.64, n = 27 - beri 52.66286, mencoba mencari tahu mengapa diperbaiki, dan menyimpan 8 byte dalam proses = D
a = 43, b = 21, n = 10005 - membutuhkan ~ 80 detik ( tapi berikan sudut kanan)

versi yang dapat dibaca:

from math import *
def bill(a,b,n):
    a=float(a)
    b=float(b)
    ratios = set()
    for i in range(0,n+2): # Create the new boards
        outter = []
        j=i+1
        for k in range(1,j): # Calculate the new holes for each board
            #y=k
            for hole_offset in [0,0.5]:
                x=(j-k-hole_offset)
                if (x/k) not in ratios:
                    ratios.add(x/k)
                    outter.append((x*a,k*b))
    min_dist = (a*n+1)**2+(b*n+1)**2
    for x,y in outter:
        if x*x+y*y<min_dist:
            min_dist = x*x+y*y
            min_alpha=degrees(atan(y/x))
    return min_alpha
tongkat
sumber
Anda dapat menghemat satu byte dengan menghapus spasi di : degrees
Morgan Thrapp
Saya tidak tahu bagaimana jawaban Anda bekerja (secara matematika) tetapi saya pikir Anda bisa mendapatkan 1 byte dengan menghapus spasi setelah titik dua. :) (Apa yang dikatakan @MorganThrapp)
basile-henry
2
Jalur ini valid, tapi ini bukan yang terpendek dalam semua kasus, misalnya dengan 2 1 4 ..
Damien
Ini juga mengasumsikan itu b < a. Itu bisa dengan mudah diperbaiki dengan mendapatkan minimum / maksimum adan bmeskipun.
user81655
diperbaiki (agak)
Rod
3

Haskell, 133 117 byte

Ini implementasi saya:

Dengan tabel 2x1, jalan akan mencapai tepat n bantal sebelum masuk ke saku jika: (x-1) / 2 + (y-1) == n dan x, y adalah bilangan prima yang saling menguntungkan. di mana x, y adalah jarak bola di atas sumbu horizontal / vertikal.

Paths sama dengan ukuran tabel arbitrer, jadi kita hanya perlu memperbarui panjang dan sudut dengan (a, b) dan tetap terpendek. Panjang jalur adalah sqrt ((x * a / 2) ^ 2 + (y * b) ^ 2) dan sudut adalah atan ((y * b) / (x * a / 2))

z=toEnum
f a b n=minimum[[z x^2+r^2,180/pi*atan(r/z x)]|x<-[1..2*n+2],y<-[n+1-div(x-1)2],r<-[2*b/a*z y],gcd x y<2]!!1
Damien
sumber