Код Гольф Симулированный Гольф

13

С учетом списка ям, зеленых размеров, угла среза и максимального расстояния вычислите результат игры в гольф .

Предположения

  • Земля плоская
  • Вся зелень круговая
  • Угол среза будет от -45 до 45 градусов и будет дан в градусах
  • Все расстояния в одной метрике (ярды или метры, не имеет значения)
  • Запрещено, за препятствиями или изломами
  • Максимальный счет на любую лунку 8
  • Все кадры перемещаются на меньшее расстояние или максимальное расстояние до отверстия в направлении, определяемом углом к ​​отверстию плюс угол среза.
  • Расстояние измеряется как прямая линия или евклидово расстояние между начальной и конечной точкой.
  • Максимальное расстояние и угол среза одинаковы для всех снимков на всех отверстиях
  • Гольфист всегда наносит два удара один раз на зеленый (или точно на край зеленого).

пример

Давайте посмотрим на хакера из тестового примера № 5 ниже для дыры № 2. Хакер может поразить мяч 320 ярдов, но всегда нарезает 30 градусов. Если мы предположим без ограничения общности, что поле для тройника находится на уровне {0,0}, а зеленый - на {497,0}, то он выполнит выстрелы в следующие точки, достигнув зеленого с 7-м выстрелом:

{{0.,0.},{277.128,-160.},{547.543,-131.372},{569.457,7.67088},{502.872,37.2564},{479.159,7.92741},{490.646,-7.85868},{500.078,-4.22987}}

На данный момент его счет будет 9 из-за двух необходимых ударов, поэтому окончательный счет для него ограничен 8, согласно предположениям.

Графически это будет выглядеть так: введите описание изображения здесь

Тестовые случаи

Все тестовые случаи имеют стандартные 18-луночные курсы

Case#1
{MaxDistance->280,SliceAngle->10,HoleDistances->{181,368,161,416,158,526,377,427,509,148,405,443,510,494,396,388,483,172},GreenDiameters->{26,18,17,23,27,23,21,23,25,21,19,24,21,23,25,24,22,22}}
Scores: 
{4,5,4,5,4,5,5,5,5,4,5,5,5,5,5,5,5,4}
Output: 85

Case#2 (same course as Test Case #1, shorter more accurate golfer)
{MaxDistance->180,SliceAngle->5,HoleDistances->{181,368,161,416,158,526,377,427,509,148,405,443,510,494,396,388,483,172},GreenDiameters->{26,18,17,23,27,23,21,23,25,21,19,24,21,23,25,24,22,22}}
Scores:
{4,5,4,5,4,6,5,5,6,4,5,5,6,6,5,5,5,4}
Output: 89

Case#3 (Same golfer as test case #1, shorter course)
{MaxDistance->280,SliceAngle->10,HoleDistances->{147,497,110,528,409,118,196,154,134,514,374,491,131,138,523,478,481,494},GreenDiameters->{32,16,36,25,32,20,30,30,33,29,25,26,26,25,33,28,21,28}}
Scores:
{4,5,4,5,5,4,4,4,4,5,5,5,4,4,5,5,5,5}
Output: 82

Case#4 (Same course as test case #3)
{MaxDistance->180,SliceAngle->5,HoleDistances->{147,497,110,528,409,118,196,154,134,514,374,491,131,138,523,478,481,494},GreenDiameters->{32,16,36,25,32,20,30,30,33,29,25,26,26,25,33,28,21,28}}
Scores:
{3,6,3,6,5,4,4,3,3,5,5,5,3,3,5,5,6,5}
Output: 79

Case#5 (Hacker)
{MaxDistance->320,SliceAngle->30,HoleDistances->{147,497,110,528,409,118,196,154,134,514,374,491,131,138,523,478,481,494},GreenDiameters->{32,16,36,25,32,20,30,30,33,29,25,26,26,25,33,28,21,28}}
Scores:
{6,8,5,8,7,6,6,6,6,8,8,8,6,6,8,8,8,8}
Output: 126

правила

  • Любой формат может быть использован для ввода. Выход - это просто число смоделированных штрихов, поэтому должно быть целым числом.
  • Это поэтому выигрывает самый короткий ответ в байтах. Применяются стандартные лазейки.
Келли Лоудер
источник
5
Почему «Земля плоская» в предположениях?
Джо Кинг
Можем ли мы предположить, что для попадания мяча внутрь MaxDistanceлунки никогда не понадобится более 6 выстрелов ?
ETHproductions
1
@JoKing В основном, так что используется плоскость, а не сферическая геометрия; во-вторых, потому что не было необходимости принимать сферических цыплят :)
Келли Лоудер
@ETHproductions, ну, вы могли бы, но это не нужно. Я думаю, возможно, вы имеете GreenDiameter/2в виду , в этом случае да, так как счет ограничен до 8 и всегда есть 2 патта.
Келли Лоудер
Не волнуйтесь, я сформулировал этот вопрос так, как я это имел в виду ;-) Моя методика, которая опирается на это, похоже, не настолько коротка, как мой текущий ответ, так что не берите в голову, я думаю ...
ETHproductions

Ответы:

10

JavaScript (ES7), 128, 126 байт

(m,a,D,S,t=0)=>S.map((s,i)=>t+=(r=(f=d=>d>s/2?1+f((l=d<m?d:m,l*l+d*d-2*d*l*Math.cos(a*Math.PI/180))**.5,s):2)(D[i]))<8?r:8)&&t

Попробуйте онлайн!

объяснение

Поскольку имеет значение только расстояние от мяча до лунки, а не координаты мяча, мы можем написать алгоритм, который рассчитывает, как близко мяч попадает в лунку при каждом ударе, а затем повторять его, пока шар не достигнет зеленого цвета. Но как нам это сделать?

Повторное использование полезной диаграммы OP, объясняющей движение мяча, с модификациями MS Paint:

наука о гольфе

У нас есть доступ к этим номерам:

  • d - текущее расстояние от мяча до лунки;
  • θ - угол среза; и
  • л , длина выстрела (минимум d и максимальная длина выстрела).

И цель состоит в том, чтобы найти х , расстояние от мяча до лунки после того, как выстрел сделан.

Сначала отметим, что a и b - это просто l cos θ и l sin θ соответственно. Мы видим, что по теореме Пифагора x можно представить в виде sqrt (b 2 + (da) 2 ) . Расширяя это, мы получаем

x = sqrt(b^2 + (d - a)^2)
  = sqrt((l*sin(θ))^2 + (d - l*cos(θ))^2)
  = sqrt((l^2 * sin^2(θ)) + (d^2 - 2*d*l*cos(θ) + l^2 * cos^2(θ))
  = sqrt(l^2 * sin^2(θ) + l^2 * cos^2(θ) + d^2 - 2dl*cos(θ))
  = sqrt(l^2 * (sin^2(θ) + cos^2(θ)) + d^2 - 2dl*cos(θ))
  = sqrt(l^2 * 1 + d^2 - 2dl*cos(θ))
  = sqrt(l^2 + d^2 - 2dl*cos(θ))

И так, новое расстояние от шара до отверстия будет sqrt (l 2 + d 2 - 2dl cos θ) . Затем мы подсчитываем итерации, необходимые для того, чтобы получить это расстояние в радиусе зеленого цвета, прибавляем 2 и кепку в 8, чтобы получить окончательный счет для этой дыры.

(Спасибо @ LegionMammal978 за то, что он указал, что все мои вычисления являются прямым результатом закона косинусов ...)


Интересно, что когда мяч ближе к лунке, чем его максимальный удар, l = d, и мы можем немного упростить формулу:

x = sqrt(l^2 + d^2 - 2dl*cos(θ))
  = sqrt(d^2 + d^2 - 2d^2*cos(θ))
  = sqrt(2d^2 - 2d^2*cos(θ))
  = sqrt(d^2(2 - 2cos(θ)))
  = d * sqrt(2 - 2cos(θ))

Чтобы найти количество оставшихся итераций, мы могли бы просто найти d / r (где r = радиус зеленого цвета) и разделить его на sqrt (2 - 2cos (θ)) , затем взять потолок результата и добавить 2 К сожалению, это не так коротко, как просто найти меньшее из d и максимальную длину выстрела.

ETHproductions
источник
Это выглядит довольно солидно. Не могли бы вы опубликовать ссылку TIO, когда у вас есть шанс?
Келли Лоудер
1
@KellyLowder Конечно, готово.
ETHproductions
2
Не будет ли ваше окончательное уравнение прямым следствием закона косинусов?
LegionMammal978
@ LegionMammal978 Я думаю, это будет ... Извините, моя тригонометрия немного ржавая: P
ETHproductions
1
@ kamoroso94 Это может быть хорошей идеей. Использование .0174533дает ошибку всего 2,38e-7 на косинусе 45 градусов, поэтому она может быть достаточно незначительной для работы. Собственно теперь, когда я на это смотрю, 71/4068(=355/113 / 180 ) еще лучше, с ошибкой всего 4.135e-10 ...
ETHproductions
3

Perl 5 , 144 138 + 12 (-MMath::Trig ) = 150 байт

побрил несколько байтов, используя упрощение формулы @ETHproductions

sub p{$_=pi/180*pop;$m=pop;for$b(@_[0..17]){$s=!++$c;1while++$s<6&&$_[17+$c]/2<($b=sqrt$b*$b+($h=$m<$b?$m:$b)**2-2*$h*$b*cos);$t+=$s+2}$t}

Попробуйте онлайн!

Немного изменил формат ввода:

Hole 1 distance
Hole 2 distance
...
Hole 18 distance
Hole 1 green diameter
...
Hole 18 green diameter
Maximum distance
Slice angle
Xcali
источник
2

Юлия 0,6 , 106 байт

S(m,t,D,G)=(s(m,d,g,v=2)=d<=g/2?v<8?v:8:(l=d<m?d:m;s(l,(d^2+l^2-2d*l*cosd(t))^.5,g,v+1));sum(s.([m],D,G)))

Попробуйте онлайн!

На основе ответа ETHproductions .

объяснение

  • s(m,d,g,v=2)=... Определить функцию s которая вычисляет счет для одной лунки рекурсивно.
  • sum(s.([m],D,G))Подать заявку sна каждую лунку и суммировать результат. .является поэлементным приложением функции с одноэлементным расширением. Например:min.([1],[2,3]) = [min(1,2), min(1,3)]
d<=g/2?v<8?v:8:(l=d<m?d:m;s(...)) #
d<=g/2?       :                   # is the ball on the green?
       v<8?v:8                    # yes -> return min(v,8)
               (l=d<m?d:m;s(...)) # no  ->
                                  # calculate new distance using ETHproductions' formula
                                  # increment current score
                                  # call s recursively
LUKEŠ
источник