Играя в бильярд


17

В этом коде гольф вам нужно будет определить направление самого короткого выстрела, который попадает ровно на n подушек, прежде чем попасть в карман.

Бильярдный стол представляет собой 6-ти карманный бильярдный стол со следующими характеристиками:

  • Размеры переменные ( а х б )
  • Без трения: мяч будет катиться вечно, пока не упадет в карман
  • Карманы и размеры мяча практически равны нулю. Это означает, что мяч попадет в карман только в том случае, если они имеют одинаковое положение.
  • Мяч помещается в нижнее левое отверстие в начале (но не падает в него)

3cushion

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

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

Примеры :

при a = 2, b = 1, n = 1 возможны три пути: (1) (2) (3) на следующем рисунке. число (1) самое короткое, поэтому на выходе должно быть atan (2) = 63,43494882292201 градусов

1cushion

Решение для a = 2, b = 1, n = 4 - это atan (4/3) = 53.13010235415598 градусов

4cushions

тестовые образцы:

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 подушек
Дэмиен

разве не самый короткий путь всегда назад и вперед между левой стороной сверху и снизу, а затем в одно из средних отверстий?
Eumel

нет, посмотрите на пример 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
Морган Трепп

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

2
Этот путь действителен, но он не самый короткий во всех случаях, например, с 2 1 4 ..
Дамьен

Это также предполагает это b < a. Это можно легко исправить, получив минимум / максимум aи bхотя.
user81655 16.12.15

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

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.