ビリヤードをする


17

このコードゴルフでは、ポケットに落ちる前に正確にn個のクッションに当たる最短ショットの方向を決定する必要があります。

ビリヤードテーブルは、次の特徴を持つ6ポケットプールテーブルです。

  • 寸法は可変です(a x b
  • 摩擦なし:ボールはポケットに落ちるまで永遠に転がります
  • ポケットとボールのサイズはほぼゼロです。これは、同じ位置にある場合にのみ、ボールがポケットに落ちることを意味します。
  • ボールは最初に左下の穴に置かれます(しかし、落ちません)

3クッション

テーブルの寸法(ab)とnをヒットするクッションの数を入力として受け取り、ポケットに落ちる前に正確にn個のクッションをヒットする最短パスの角度を度数で返す完全なプログラムまたは関数を作成します。

  • a > 0
  • b > 0
  • 0 <= n <10000000
  • 0 < アルファ <90(度)精度:少なくとも10 ^ -6

例:

で= 2、B = 1、N(1)(2)(3)次の図に:= 1三つの可能な経路が存在します。数値(1)は最短であるため、出力はatan(2)= 63.43494882292201度になります。

1クッション

a = 2、b = 1、n = 4 の解はatan(4/3)= 53.13010235415598度です

4クッション

試験サンプル:

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

これはコード/ビリヤードゴルフです。最短のコードが勝ちます!


ボールは正確に nクッションに当たる必要がありますか、それとも少なくとも nクッションに当たる必要がありますか?
ピーターテイラー

@PeterTaylor正確にnクッション
ダミアン

最短経路は常に左側の上部と下部の間を行ったり来たりしてから、中央の穴の1つに入りますか?
ユーメル

いいえ、2 1 4の例を見てください。このパスはsqrt(25)= 5の長さですが、ソリューションはsqrt(26)
ダミアン

回答:


11

Python 2.7、352 344 281バイト

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
  • @Dschoniのおかげで-16バイト

説明:クッションヒットを計算する代わりに、n個のテーブルを追加し、新しい穴を有効として取得します。 ビリヤード 黒の境界/穴は元、緑の境界/穴はn = 1、赤の境界/穴は有効ですn = 2など。次に、無効な穴を削除します(たとえば、n = 1の青い矢印)。有効な穴とその座標のリストを作成し、初期点からの距離を計算してから、より小さい距離の角度を計算します。
注:
a = 4.76、b = 3.64、n = 27-52.66286を与えて、なぜ修正されたのかを把握しようとし、プロセスで8バイトを節約した= D
a = 43、b = 21、n = 10005-約80秒かかります(しかし、直角を与えます)

読み取り可能なバージョン:

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

でスペースを削除することにより、バイトを保存できます : degrees
モーガントラップ

私はあなたの答えがどのように機能するのか分かりませんが(数学的に)、コロンの後のスペースを削除することで1バイトを得ることができると思います。:)(@MorganThrappが言ったこと)
ヘンリー

2
このパスは有効ですが、それは2 1 4 ...と、たとえば、すべての場合に最短ではありません
ダミアン

また、これも想定していb < aます。これは、最小値aと最大値を取得することで簡単に修正できbます。
user81655

修正(sorta)
ロッド

3

Haskell、133 117バイト

これは私の実装です:

2x1テーブルでは、次の場合、ポケットに入る前にパスが正確にn個のクッションにヒットします:(x-1)/ 2 +(y-1)== nおよびx、yは相互に素数です。ここで、x、yは、水平/垂直軸上のボールの距離です。

パスは任意のテーブルサイズで同じであるため、長さと角度を(a、b)で更新し、最短に保つ必要があります。パスの長さはsqrt((x * a / 2)^ 2 +(y * b)^ 2)で、角度は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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.