Гра в більярд


17

У цьому коді гольфу вам доведеться визначити напрямок найкоротшого пострілу, який вражає рівно n подушок, перш ніж потрапити в кишеню.

Більярдний стіл - це 6-ти кишеньковий столик із такими характеристиками:

  • Розміри змінні ( a x b )
  • Без тертя: куля буде котитися вічно, поки не потрапить у кишеню
  • Розміри кишень і кульок майже дорівнюють нулю. Це означає, що куля впаде в кишеню, лише якщо вони мають однакове положення.
  • Куля розміщується в нижньому лівому отворі на початку (але не потрапляє в нього)

3 каре

Створіть повну програму або функцію, яка приймає розміри ( a , b ) таблиці та кількість подушок, щоб потрапити на n як вхід, і повертає кут у градусах найкоротшого шляху, вражаючи рівно n подушок, перш ніж потрапити в кишеню.

  • a > 0
  • b > 0
  • 0 <= n <10000000
  • 0 < альфа <90 (у градусах) точність: не менше 10 ^ -6

приклади:

при a = 2, b = 1, n = 1 є три можливі шляхи: (1) (2) (3) на наступному малюнку. число (1) є найкоротшим, тому вихід повинен бути атан (2) = 63,43494882292201 градусів

1кашон

Рішення для a = 2, b = 1, n = 4 - атан (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 подушок
Дамієн

хіба не найкоротший шлях завжди вперед-назад між лівою стороною вгорі та внизу, а потім в один із середніх отворів?
Евмель

ні, подивіться на приклад 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
  • -16 байт завдяки @Dschoni

Пояснення: замість обчислення показів подушок я додаю 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
Morgan Thrapp

Я поняття не маю, як працює ваша відповідь (математично), але я думаю, ви можете отримати 1 байт, видаливши пробіл після двокрапки. :) (Що сказав @MorganThrapp)
базилік-Генрі

2
Цей шлях є дійсним, але він не найкоротший у всіх випадках, наприклад, з 2 1 4 ..
Дамієн

Це також передбачає, що b < a. Це можна легко виправити, отримуючи мінімум / максимум aі bхоча.
користувач81655

виправлено (сорта)
пруд

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.