Código Golf Golf Simulado

13

Dada una lista de yardas de hoyo, tamaños verdes, un ángulo de corte y una distancia máxima, calcule una puntuación de golf .

Supuestos

  • La tierra es plana
  • Todos los greens son circulares.
  • El ángulo de corte estará entre -45 y 45 grados y se dará en grados
  • Todas las distancias en la misma métrica (yardas o metros, no importa)
  • Sin límites, obstrucciones o doglegs.
  • La puntuación máxima en cualquier hoyo es 8
  • Todos los disparos recorren la menor distancia máxima o la distancia al hoyo, en una dirección definida por el ángulo del hoyo más el ángulo de corte.
  • La distancia se mide como la línea recta o la distancia euclidiana entre el punto inicial y el punto final.
  • La distancia máxima y el ángulo de corte son los mismos para todos los disparos en todos los agujeros
  • El golfista siempre dos putts una vez en el green (o exactamente en el borde del green).

Ejemplo

Miremos al pirata informático del caso de prueba # 5 a continuación para el hoyo # 2. El hacker puede golpear la pelota 320 yardas, pero siempre corta 30 grados. Si suponemos sin pérdida de generalidad que el tee box está en {0,0} y el green está en {497,0}, entonces golpeará los tiros a los siguientes puntos, llegando al green con el 7 ° tiro:

{{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}}

En este punto, su puntaje sería 9 debido a los dos putts requeridos, por lo que el puntaje final para él se limita a 8, según los supuestos.

Gráficamente, se verá así: ingrese la descripción de la imagen aquí

Casos de prueba

Todos los casos de prueba tienen campos estándar de 18 hoyos.

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

Reglas

  • Se puede usar cualquier formato para la entrada. La salida es simplemente el número de trazos simulados, por lo que debe ser un número entero.
  • Este es el por lo que gana la respuesta más corta en bytes. Se aplican lagunas estándar.
Kelly Lowder
fuente
55
¿Por qué "la Tierra es plana" bajo supuestos?
Jo King el
¿Podemos suponer que nunca se necesitarán más de 6 tiros para que la pelota entre dentro MaxDistancedel hoyo?
ETHproductions
1
@JoKing Principalmente, de modo que se utiliza la geometría plana en lugar de la esférica; segundo porque no había necesidad de asumir pollos esféricos :)
Kelly Lowder
@ETHproductions, bueno, podrías pero eso es innecesario. Creo que tal vez te refieres GreenDiameter/2, en cuyo caso sí, ya que el puntaje está limitado a 8 y siempre hay 2 putts.
Kelly Lowder
No se preocupe, formulé esa pregunta como lo dije en serio ;-) Mi técnica que se basa en esto no parece ser tan corta como mi respuesta actual, así que no importa, supongo ...
ETHproductions

Respuestas:

10

JavaScript (ES7), 128 126 bytes

(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

Pruébalo en línea!

Explicación

Debido a que solo importa la distancia desde la pelota hasta el hoyo y no las coordenadas de la pelota, podemos escribir un algoritmo que calcule qué tan cerca llega la pelota al hoyo con cada disparo, y luego ejecutarlo repetidamente hasta que la pelota llegue al green. ¿Pero cómo hacemos esto?

Reutilizando el útil diagrama de OP que explica el movimiento de la pelota, con modificaciones de MS Paint:

la ciencia del golf

Tenemos acceso a estos números:

  • d , la distancia actual de la bola al hoyo;
  • θ , el ángulo de corte; y
  • l , la longitud del disparo (mínimo de d y la longitud máxima del disparo).

Y el objetivo es encontrar x , la distancia de la pelota al hoyo después de que se realiza el disparo.

Primero notamos que a y b son simplemente l cos θ y l sin θ , respectivamente. Podemos ver que mediante el teorema de Pitágoras, x puede representarse como sqrt (b 2 + (da) 2 ) . Expandiendo esto, obtenemos

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(θ))

Y así, la nueva distancia de la bola al hoyo será sqrt (l 2 + d 2 - 2dl cos θ) . Luego contamos las iteraciones que se necesitan para obtener esta distancia dentro del radio del green, sumar 2 y limitar a 8 para obtener el puntaje final para ese hoyo.

(Gracias a @ LegionMammal978 por señalar que todos los cálculos que hice son un resultado directo de la ley de cosenos ...)


Curiosamente, cuando la pelota está más cerca del hoyo que su tiro máximo, l = dy podemos simplificar la fórmula un poco más:

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(θ))

Para encontrar el número de iteraciones restantes, podríamos simplemente encontrar d / r (donde r = el radio del verde) y dividirlo por sqrt (2 - 2cos (θ)) , luego tomar el techo del resultado y sumar 2 Desafortunadamente, esto no parece ser tan corto como solo encontrar el menor d y la longitud máxima del disparo.

ETHproductions
fuente
Esto se ve bastante sólido. ¿Podría publicar un enlace TIO cuando tenga la oportunidad?
Kelly Lowder
1
@KellyLowder Claro, listo.
ETHproductions
2
¿No sería su ecuación final una consecuencia directa de la ley de cosenos?
LegionMammal978
@ LegionMammal978 Supongo que sí ... Lo siento, mi trigonometría está un poco oxidada: P
ETHproductions
1
@ kamoroso94 Esa podría ser una buena idea. El uso .0174533da un error de solo 2.38e-7 en el coseno de 45 grados, por lo que podría ser lo suficientemente insignificante como para funcionar. En realidad, ahora que lo miro, 71/4068(= 355/113 / 180) es aún mejor, dando un error de solo 4.135e-10 ...
ETHproductions
3

Perl 5 , 144 138 + 12 ( -MMath::Trig) = 150 bytes

afeitó algunos bytes usando la simplificación de la fórmula de @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}

Pruébalo en línea!

Cambió un poco el formato de entrada:

Hole 1 distance
Hole 2 distance
...
Hole 18 distance
Hole 1 green diameter
...
Hole 18 green diameter
Maximum distance
Slice angle
Xcali
fuente
2

Julia 0.6 , 106 bytes

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)))

Pruébalo en línea!

Basado en la respuesta de ETHproductions .

Explicación

  • s(m,d,g,v=2)=...Defina la función sque calcula la puntuación de un hoyo de forma recursiva.
  • sum(s.([m],D,G))Solicite scada hoyo y sume el resultado. .es una aplicación de función por elementos con expansión singleton. P.ej: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
Lucas
fuente