打台球


17

在此代码高尔夫球中,您将必须确定在落入口袋中之前恰好击中n个垫子的最短击球的方向。

台球桌是具有以下特征的6口袋台球桌:

  • 尺寸可变(a x b
  • 无摩擦:球将永远滚动直到落入口袋
  • 口袋和球的大小几乎为零。这意味着仅当球具有相同的位置时,球才会落在口袋中。
  • 球在开始时放置在左下角的孔中(但不会掉进去)

3个靠垫

创建一个完整的程序或函数,该函数将表的尺寸(ab)和要击中n个垫子的数量作为输入,并返回以最短路径度数精确击中n个垫子然后落入口袋的角度。

  • > 0
  • b > 0
  • 0 <= n <10000000
  • 0 < alpha <90(以度为单位)精度:至少10 ^ -6

例子 :

a = 2,b = 1,n = 1的情况下,存在三种可能的路径:下图为(1)(2)(3)。数字(1)最短,因此输出应为atan(2)= 63.43494882292201度

1个靠垫

对于该解决方案一个 = 2,b = 1,Ñ = 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个靠垫
Damien

是不是最短的路径总是总是在左侧顶部和底部之间来回,然后进入中间孔之一?
Eumel 2015年

不,请看2 1 4示例。该路径为sqrt(25)= 5长,而您的解决方案为sqrt(26)
Damien 2015年

Answers:


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
  • -16个字节,感谢@Dschoni

说明:代替计算缓冲命中,我添加n个表并将新的孔视为有效: 台球 黑色边框/孔是原始的,绿色边框/孔对n = 1的有效,红色边框/孔对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
摩根Thrapp

我不知道您的答案是如何工作的(按数学方法),但是我认为您可以通过删除冒号后面的空格来获得1个字节。:)(@ MorganThrapp说了什么)
basile-henry

2
该路径有效,但并非在所有情况下都最短,例如2
Damien 2015年

这也假设b < a。这可以很容易地通过获得的最小/最大的固定ab虽然。
user81655

固定(sorta)

3

Haskell,133117字节

这是我的实现:

对于2x1的桌子,如果(x-1)/ 2 +(y-1)== n并且x,y是互质的,那么在进入口袋之前,路径将恰好碰到n个垫子。其中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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.