Code Golf Symulowany golf

13

Biorąc pod uwagę listę odległości dołków, rozmiarów zielonych, kąta przekroju i maksymalnej odległości, oblicz wynik golfowy .

Założenia

  • Ziemia jest płaska
  • Wszystkie warzywa są okrągłe
  • Kąt plastra będzie wynosił od -45 do 45 stopni i będzie podawany w stopniach
  • Wszystkie odległości w tej samej metryki (jardy lub metry, nie ma znaczenia)
  • Żadnych ograniczeń, przeszkód i doglegów
  • Maksymalny wynik na dowolnym dołku wynosi 8
  • Wszystkie strzały pokonują mniejszą maksymalną odległość lub odległość do otworu w kierunku określonym przez kąt do otworu powiększony o kąt przekroju.
  • Odległość jest mierzona jako linia prosta lub odległość euklidesowa między punktem początkowym i końcowym.
  • Maksymalna odległość i kąt przekroju są takie same dla wszystkich strzałów na wszystkich otworach
  • Golfista zawsze stawia dwa razy jeden raz na zielonym (lub dokładnie na brzegu zielonym).

Przykład

Spójrzmy na hakera z przypadku testowego nr 5 poniżej dla dziury nr 2. Haker może uderzyć piłkę 320 jardów, ale zawsze kroi 30 stopni. Jeśli założymy bez utraty ogólności, że tee box znajduje się w {0,0}, a green w {497,0}, wtedy trafi strzały w następujące punkty, osiągając zielony z siódmym strzałem:

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

W tym momencie jego wynik wyniósłby 9 z powodu wymaganych dwóch puttów, więc ostateczny wynik dla niego zostaje ograniczony do 8, zgodnie z założeniami.

Graficznie będzie to wyglądać tak: wprowadź opis zdjęcia tutaj

Przypadki testowe

Wszystkie przypadki testowe mają standardowe kursy 18-dołkowe

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

Zasady

  • Do wprowadzenia można użyć dowolnego formatu. Dane wyjściowe to po prostu liczba symulowanych pociągnięć, więc powinna być liczbą całkowitą.
  • To jest więc wygrywa najkrótsza odpowiedź w bajtach. Obowiązują standardowe luki.
Kelly Lowder
źródło
5
Dlaczego „Ziemia jest płaska” przy założeniach?
Jo King
Czy możemy założyć, że nigdy nie zajmie więcej niż 6 strzałów, aby piłka znalazła się w MaxDistancedołku?
ETHproductions
1
@JoKing Głównie dlatego, że używana jest geometria płaska zamiast kulistej; po drugie dlatego, że nie było potrzeby zakładania kulistych kurczaków :)
Kelly Lowder
@ETHproductions, cóż, możesz, ale to nie jest konieczne. Myślę, że może masz na myśli GreenDiameter/2, w którym to przypadku tak, ponieważ wynik jest ograniczony do 8 i zawsze są 2 putty.
Kelly Lowder,
Nie martw się, sformułowałem to pytanie, co miałem na myśli ;-) Moja technika, która polega na tym, nie wydaje się być tak krótka, jak moja obecna odpowiedź, więc nieważne, myślę ...
ETHprodukcje

Odpowiedzi:

10

JavaScript (ES7), 128 126 bajtów

(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

Wypróbuj online!

Wyjaśnienie

Ponieważ liczy się tylko odległość od piłki do dołka, a nie współrzędne piłki, możemy napisać algorytm, który obliczy, jak blisko piłka zbliża się do dołka przy każdym strzale, a następnie uruchom ją kilkakrotnie, aż piłka osiągnie zielony. Ale jak to robimy?

Ponowne użycie pomocnego schematu OP wyjaśniającego ruch kulki, z modyfikacjami MS Paint:

nauka golfa

Mamy dostęp do tych numerów:

  • d , aktualna odległość od piłki do dołka;
  • θ , kąt przekroju; i
  • l , długość strzału (minimum d i maksymalna długość strzału).

A celem jest znalezienie x , odległość od piłki do dołka po strzale.

Po pierwsze zauważmy, że i b są po prostu l cos θ i l sin θ , odpowiednio. Widzimy, że według twierdzenia Pitagorasa x można przedstawić jako sqrt (b 2 + (da) 2 ) . Rozwijamy to, rozumiemy

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

I tak nowa odległość od piłki do dołka będzie wynosić sqrt (l 2 + d 2 - 2dl cos θ) . Następnie zliczamy iteracje potrzebne do uzyskania tej odległości w promieniu zieleni, dodajemy 2 i ograniczamy do 8, aby uzyskać końcowy wynik dla tego dołka.

(Podziękowania dla @ LegionMammal978 za zwrócenie uwagi, że wszystkie wykonane przeze mnie obliczenia są bezpośrednim wynikiem prawa cosinus ...)


Co ciekawe, gdy piłka jest bliżej dołka niż jej maksymalny strzał, l = d i możemy jeszcze bardziej uprościć formułę:

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

Aby znaleźć # pozostałych iteracji, moglibyśmy po prostu znaleźć d / r (gdzie r = promień zieleni) i podzielić to przez sqrt (2 - 2cos (θ)) , a następnie wziąć pułap wyniku i dodać 2 Niestety, nie wydaje się to być tak krótkie, jak znalezienie mniejszego d i maksymalnej długości strzału.

ETHprodukcje
źródło
To wygląda całkiem solidnie. Czy możesz zamieścić link do TIO, jeśli masz szansę?
Kelly Lowder
1
@ KellyLowder Pewnie, gotowe.
ETHprodukcje
2
Czy twoje końcowe równanie nie byłoby bezpośrednią konsekwencją prawa cosinusa?
LegionMammal978
@ LegionMammal978 Chyba tak ... Przepraszam, moja trygonometria jest trochę zardzewiała: P
ETHprodukcje
1
@ kamoroso94 To może być dobry pomysł. Użycie .0174533daje błąd tylko 2,38e-7 na cosinusie 45 stopni, więc może być wystarczająco znikomy do działania. Właściwie teraz, kiedy na to patrzę, 71/4068(= 355/113 / 180) jest jeszcze lepszy, dając błąd tylko 4,135e-10 ...
ETHproductions
3

Perl 5 , 144 138 + 12 ( -MMath::Trig) = 150 bajtów

ogoliłem kilka bajtów, korzystając z uproszczenia formuły @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}

Wypróbuj online!

Zmieniono nieco format wejściowy:

Hole 1 distance
Hole 2 distance
...
Hole 18 distance
Hole 1 green diameter
...
Hole 18 green diameter
Maximum distance
Slice angle
Xcali
źródło
2

Julia 0.6 , 106 bajtów

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

Wypróbuj online!

Na podstawie odpowiedzi ETHproductions .

Wyjaśnienie

  • s(m,d,g,v=2)=...Zdefiniuj funkcję, sktóra będzie rekurencyjnie obliczać wynik dla jednego dołka.
  • sum(s.([m],D,G))Zastosuj sdo każdego otworu i zsumuj wynik. .jest aplikacją funkcji elementarnych z rozszerzeniem singleton. Na przykład: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
Łukasza
źródło