Beri aku golf

15

Jika Anda belum pernah bermain golf sebelumnya, berikut adalah daftar istilah terkait golf yang saya gunakan dalam pertanyaan ini

  • Tembakan , juga disebut stroke : Setiap kali bola dipukul, ini adalah tembakan.
  • Lubang : Lapangan golf dibagi menjadi beberapa lubang, di mana tujuannya adalah untuk memukul bola dari satu lokasi yang ditentukan ke lokasi yang lain dengan sesedikit mungkin tembakan.
  • Tee : Di mana Anda memulai sebuah lubang.
  • Pin atau Bendera : Di mana Anda menyelesaikan lubang
  • Fairway , Rough , Water , dan Green : Fitur di lapangan golf yang memengaruhi cara seseorang memainkan bola di kehidupan nyata. (Bagaimana mereka mempengaruhi program ditentukan di bawah ini)

Saya akan pergi bermain golf besok, dan saya menemukan bahwa kadang-kadang, saya mengalami kesulitan mencari tahu klub apa yang akan digunakan untuk memukul yardage tertentu. Jadi saya memutuskan untuk menuliskan klub saya dan halamannya per tembakan.

Asumsi Pertama: Semua lubang ada di sebelah utara kotak tee mereka.

Semua yardage ini mengukur kemungkinan sejauh mana perjalanan bola ke utara. Bola akan menempuh jarak bilangan bulat acak antara batas yang ditentukan untuk masing-masing klub (termasuk).

Sebagai pegolf utama, tidak ada satu pun pukulan saya yang memiliki pergeseran horizontal. Ini berarti bahwa semua bidikan saya masuk dalam garis lurus langsung di bendera.

Club #     Club        Yardage
1          Driver      300-330
2          3-Wood      270-299
3          5-Wood      240-269
4          3-Iron      220-239
5          4-Iron      200-219
6          5-Iron      180-199
7          6-Iron      160-179
8          7-Iron      140-159
9          8-Iron      120-139
10         9-Iron      100-119
11         P-Wedge     80-99
12         S-Wedge     50-79
13         L-Wedge     0-49
14         Putter      (only on green)

Sebagai orang yang suka pemrograman, saya memutuskan bahwa saya ingin membuat model golf dan menetapkan tujuan seberapa baik yang ingin saya lakukan besok. Namun, seperti programmer amatir, setelah sepuluh menit, saya menyerah dan meminta bantuan pada Stack Overflow (hanya bercanda). Berikut adalah beberapa data tentang kursus ini.

Asumsi Kedua: Geografi Lubang

  • Semua angka yang menggambarkan jarak pada kursus adalah bilangan bulat.

  • Setiap lubang adalah garis lurus. Jarak garis lurus antara setiap lubang dan pin (ujung lubang) adalah Length.

  • Fairways adalah segmen dengan panjang yang ditentukan oleh flen. Nilai yang tercantum untuk flenadalah jarak pekarangan utara dari tee tempat fairway berada.

  • Bahaya air adalah segmen yang panjangnya ditentukan oleh wlen, yang memiliki sifat sama dengan flen.

  • Hijau memiliki panjang yang ditentukan oleh glen.

  • Semua bagian dari jalur yang tidak fairway, air, atau hijau adalah kasar.

Berikut adalah bagan yang menggambarkan setiap lubang di lapangan.

Hole #     Length      flen               wlen        glen   
1          401         54-390                         391-425
2          171                            1-165       166-179
3          438         41-392             393-420     421-445
4          553         30-281,354-549     282-353     550-589
5          389         48-372                         373-404
6          133                                        125-138
7          496         37-413             414-484     484-502
8          415         50-391                         392-420
9          320         23-258             259-303     304-327

Cara bermain Golf (untuk program ini)

  • Selalu arahkan tepat ke bendera.
  • Memukul bola sedekat mungkin dengan pin, mencoba menjaga bola di fairway atau (lebih disukai) di green.
  • Ketika Anda mendaratkan tembakan ke dalam air, tembakan Anda berikutnya harus dimainkan dari tempat yang sama dengan tembakan yang masuk ke dalam air.
  • Setelah bola mendarat di hijau, hanya putter yang bisa digunakan. Jika bola mendarat lebih dari 5 meter dari pin, maka saya putt dua kali. Kalau tidak, saya putt sekali.
  • Dimungkinkan untuk melakukan tembakan melewati pin.

Mencetak gol

Skor saya pada hole adalah jumlah tembakan yang saya ambil, ditambah satu pukulan untuk setiap kali saya mendarat di air atau kasar.

Program

Oke, itu banyak peraturan, sekarang mari kita bicara tentang programnya.

Kursus harus didefinisikan seperti di atas dalam program , karena kursusnya konstan. Namun, pegolf yang berbeda memiliki jarak yang berbeda untuk setiap pukulan, sehingga input ke STDIN harus berupa serangkaian jarak pekarangan, diatur dalam urutan peningkatan jumlah klub dan dipisahkan dengan koma (tanpa spasi putih).

Keluarannya adalah bagaimana saya "memainkan" putaran golf. Nomor penahanan harus ditentukan pada awal setiap baris karena di Hole #:mana #lubang saat ini. Setiap tembakan yang tidak putt adalah dari bentuk berikut: {club,distance of shot,condition of ball,distance to pin}. Detail bidikan harus dipisahkan dengan koma tetapi tidak ada spasi putih dalam urutan di atas. Tembakan itu sendiri harus ditulis dalam urutan bagaimana mereka dimainkan dan dipisahkan oleh spasi. Setelah bola mendarat di hijau, program harus mencetak berapa banyak putt yang saya ambil, dalam format {# putts}. Pada akhir setiap baris, jumlah tembakan yang saya ambil pada lubang harus dipisahkan dari tembakan lainnya dengan spasi dan dicetak sebagai(#). Setiap lubang harus pada barisnya sendiri dan ditulis berurutan. Akhirnya, pada baris terakhir (kesepuluh) program, jumlah total tembakan untuk putaran harus dicetak sebagai Total: # shots.

Tidak ada "strategi" yang harus diambil oleh program Anda. Anda dapat menulis program dengan strategi apa pun yang Anda inginkan. Contoh strategi termasuk memaksimalkan peluang persen mendarat di hijau dan memaksimalkan jarak setiap tembakan sampai mencapai lubang.

INPUT SAMPEL

300-330,270-299,240-269,220-239,200-219,180-199,160-179,140-159,120-139,100-119,80-99,50-79,0-49

OUTPUT SAMPEL

Hole 1: {Driver,324,Fairway,77} {S-Wedge,70,Green,7} {Two putts} (4)
Hole 2: {6-Iron,162,Water,171} {6-Iron,168,Green,3} {One putt} (4)
Hole 3: {Driver,301,Fairway,137} {8-Iron,131,Green,6} {Two putts} (4)
Hole 4: {3-Wood,288,Water,553} {3-Wood,276,Fairway,277} {3-Wood,291,Green,14} {Two putts} (6)
Hole 5: {Driver,322,Fairway,67} {S-Wedge,62} {One putt} (3)
Hole 6: {8-Iron,120,Rough,18} {L-Wedge,10,Green,8} {Two putts} (5)
Hole 7: {Driver,325,Fairway,171] {6-Iron,170,Green,1} {One putt} (3)
Hole 8: {Driver,306,Fairway,109} {9-Iron,100,Green,9} {Two putts} (4)
Hole 9: {Driver,308,Green,12} {Two putts} (3)
Total: 36 shots

Saya akui, ini adalah tantangan yang agak ambisius untuk posting pertama di CG.SE, jadi saya akan senang berbicara tentang cara meningkatkan tantangan ini dalam komentar. Terima kasih untuk bantuannya.

Arcturus
sumber
2
Saya akan sangat menghargai jika, bagi kami yang bukan pemain golf, Anda tidak menggunakan istilah golf sebanyak (misalnya "kotak tee" dan "pergeseran horizontal"). :)
kirbyfan64sos
Saya akan menambahkan daftar istilah terkait golf. Saat bermain golf, bola tidak selalu lurus, jadi saya hanya mengatakan bahwa bola selalu mengarah langsung ke lubang, dan dengan demikian tidak memiliki pergeseran horizontal.
Arcturus
Katakanlah pin berada di 301 yard, dan ada fairway dari 0~299yard, hijau dari 300~315yard, dan air dari 316~330yard. Klub apa yang akan dipilih? Bagaimana jika air diganti dengan kasar?
lirtosiast
Idealnya, program harus dapat memunculkan strategi sendiri.
Arcturus
Apa yang Anda maksud dengan "strategi optimal"? Meminimalkan jumlah rata-rata pukulan? Sedangkan untuk kriteria menang saya akan pergi dengan kode-golf.
lirtosiast

Jawaban:

9

Python 2.7: 43 Rata-rata tembakan 40,5

Ini adalah posting pertama saya di sini jadi bersabarlah.

Karena poster itu berpikir memperlakukan ini seperti tantangan pemrograman, bukan kode golf, saya menganggapnya lebih sebagai tantangan pemrograman. Saya berusaha untuk menjaga solusi saya dan menembakkan logika sederhana tetapi ternyata lebih jelek karena segalanya menjadi rumit dengan cepat.

Kode Saya

Beberapa hal yang perlu dipikirkan saat membaca: program membuat daftar klub yang digunakan disebut 'klub', dan daftar yang disebut 'jarak' yaitu jarak yang ditempuh bola dari tee, hlen adalah panjang lubang, d1s adalah jarak setiap tembakan bergerak.

Pertama saya mendefinisikan kursus. Setiap fairway, air, dan panjang hijau harus ditentukan sehingga nantinya program dapat memeriksa kondisi bola, jadi saya menambahkan nilai non-integer untuk bagian-bagian dari jalur yang tidak ada.

from random import randint
import numpy as np

#Hole      Length     flen               wlen           glen    Name 
hole1 = [    401,     54, 390,       390.5, 390.5,    391, 425, 'Hole 1']
hole2 = [    171,    0.5, 0.5,           1, 165,      166, 179, 'Hole 2']
hole3 = [    438,     41, 392,         393, 420,      421, 445, 'Hole 3']
hole4 = [    553,     30, 549,         282, 353,      550, 589, 'Hole 4']
hole5 = [    389,     48, 372,         1.5, 1.5,      373, 404, 'Hole 5']
hole6 = [    133,    0.5, 0.5,         1.5, 1.5,      125, 138, 'Hole 6']
hole7 = [    496,     37, 413,         414, 484,      484, 502, 'Hole 7']
hole8 = [    415,     50, 391,         1.5, 1.5,      392, 420, 'Hole 8']
hole9 = [    320,     23, 258,         259, 303,      304, 327, 'Hole 9']

holes = [hole1, hole2, hole3, hole4, hole5, hole6, hole7, hole8, hole9]

Di sini saya mendefinisikan logika utama untuk memilih klub. Program ini mencoba untuk memaksimalkan jarak dengan memilih driver untuk semua panjang lebih besar dari jarak driver max dan memilih klub dengan jangkauan yang berisi jarak ke lubang sebaliknya. Ini membutuhkan kisaran yang disediakan oleh input klub untuk kontinu, yaitu tidak ada jarak dalam jarak tembakan. Persyaratan realistis karena seseorang dapat mengenai klub tanpa backswing penuh untuk membatasi jarak tembakan mereka ke jarak maksimum klub terkuat berikutnya.

def stroke(distance):
    Length = abs(hlen - distance)
    if Length >= Driver_a:
        club = 'Driver'
        d = randint(Driver_a,Driver_b)
    elif Length >= Wood3_a and Length <= Wood3_b:
        club = '3-Wood'
        d = randint(Wood3_a,Wood3_b)
    elif Length >= Wood5_a and Length <= Wood5_b:
        club = '5-Wood'
        d = randint(Wood5_a,Wood5_b)
    elif Length >= Iron3_a and Length <= Iron3_b:
        club = '3-Iron'
        d = randint(Iron3_a,Iron3_b)
    elif Length >= Iron4_a and Length <= Iron4_b:
        club = '4-Iron'
        d = randint(Iron4_a,Iron4_b)
    elif Length >= Iron5_a and Length <= Iron5_b:
        club = '5-Iron'
        d = randint(Iron5_a,Iron5_b)
    elif Length >= Iron6_a and Length <= Iron6_b:
        club = '6-Iron'
        d = randint(Iron6_a,Iron6_b)
    elif Length >= Iron7_a and Length <= Iron7_b:
        club = '7-Iron'
        d = randint(Iron7_a,Iron7_b)
    elif Length >= Iron8_a and Length <= Iron8_b:
        club = '8-Iron'
        d = randint(Iron8_a,Iron8_b)
    elif Length >= Iron9_a and Length <= Iron9_b:
        club = '9-Iron'
        d = randint(Iron9_a,Iron9_b)
    elif Length >= Pwedge_a and Length <= Pwedge_b:
        club = 'P wedge'
        d = randint(Pwedge_a,Pwedge_b)
    elif Length >= Swedge_a and Length <= Swedge_b:
        club = 'S wedge'
        d = randint(Swedge_a,Swedge_b)
    elif Length >= Lwedge_a and Length <= Lwedge_b:
        club = 'L wedge'
        d = randint(Lwedge_a,Lwedge_b)        
    else : print 'stroke error'
    return club, d

Selanjutnya, saya mendefinisikan fungsi put yang dua putt untuk semua panjang lebih dari 5 meter ke lubang dan satu putt untuk 5 dan kurang. Saya juga menyertakan opsi untuk memukul bola secara langsung ke dalam lubang yang disebut 'chip in'.

def putt(distance):
    Length = abs(hlen - distance)
    if Length > 5:
        club = '2 putts'
    elif Length == 0:
        club = 'chip in'
    else:
        club = '1 putt'
    return club

Di sinilah strategi menjadi sedikit funky. Agar tetap sederhana dan juga mencegah terjebak dalam lingkaran mengemudi ke dalam air hanya untuk menjatuhkan bola di lokasi tembakan sebelumnya dan mengemudi ke dalam air lagi, saya benar-benar mundur, memukul bola mundur dengan irisan pasir dan kemudian minta kode mengevaluasi bidikan lagi kali ini semoga syuting tepat di depan air sehingga bidikan berikutnya dapat membersihkannya. Strategi ini dihukum oleh hukuman kasar tetapi efektif untuk membersihkan air.

def water():
    club = 'S wedge'
    d = randint(50,79)
    return club, d

Program ini menghitung jumlah pukulan per lubang setelah lubang itu dimainkan. Ini menambahkan hukuman untuk tembakan dalam kasar dan menambahkan hukuman untuk memukul ke dalam air dengan menjumlahkan array yang disebut air yang ditambahkan setelah setiap tembakan air. Ini mengambil keuntungan dari fakta bahwa fairway selalu mengarah ke air atau ke hijau untuk setiap lubang di lapangan. Itu harus diubah untuk kursus yang berisi kasar di tengah fairway.

def countstrokes(clubs, distances, waters):
    distances = np.array(distances)
    mask1 = distances < flen1
    mask2 = distances > grn2
    extra = sum(mask1*1)+sum(mask2*1) + sum(waters)
    if clubs[-1] == 'chip in' : strokes = len(clubs)-1+extra
    elif clubs[-1] == '2 putts' : strokes = len(clubs) +1+extra
    elif clubs[-1] == '1 putt' : strokes = len(clubs)+extra
    else : print 'strokes error'
    return strokes

Setelah kode utama berjalan, kondisi melihat jarak bola pada saat lubang dan melaporkan kondisi bola. Saya mengalami satu masalah dengan kondisi karena cara saya memperlakukan memukul bola ke dalam air di program utama. Dalam program itu, jika bola ditabrak ke dalam air, itu segera dipindahkan kembali ke lokasi di mana tembakan itu mengenai. Jarak direkam setelah bola dipindahkan kembali sehingga kondisi bola tidak bisa 'air'. Jika Anda memukul bola dari tee pada hole 4 ke dalam air, program akan mencetak jarak yang Anda memukul bola dan klub tetapi panjang lubang tidak akan berubah dan kondisinya akan 'kasar' karena bola dijatuhkan di 0 jarak yang kasar. Anda dapat menghapus tanda komentar 'air' cetak

def condition(distances):
    conditions=[]
    for distance in distances:
        if distance >= grn1 and distance <= grn2:
            conditions.append('green')
        elif distance >= flen1 and distance <= flen2:
            conditions.append('fair')
        else:
            conditions.append('rough')
    return conditions

Inilah bagian utama dari kode yang memuat lubang dan memainkan permainan. Setelah menginisialisasi beberapa kondisi kode berjalan 'memukul' memukul bola ke arah lubang, termasuk membalikkan jika lubang itu melampaui, sampai baik air atau hijau ditemukan. Jika air ditemukan, itu menambah penghitung penalti dan menjalankan air program dan setelah memindahkan bola kembali ke lokasi itu terkena. Jika hijau ditemukan, put dipanggil dan lubang diakhiri. Setelah jarak dan klub dianalisis untuk menentukan kondisi setiap tembakan dan tembakan dihitung.

def golf(driver_a, driver_b, wood3_a, wood3_b, wood5_a, wood5_b, iron3_a, iron3_b, iron4_a, iron4_b, iron5_a, iron5_b, iron6_a, iron6_b, iron7_a, iron7_b, iron8_a, iron8_b, iron9_a, iron9_b, pwedge_a, pwedge_b, swedge_a, swedge_b, lwedge_a, lwedge_b):
    global Driver_a, Driver_b, Wood3_a, Wood3_b, Wood5_a, Wood5_b, Iron3_a, Iron3_b, Iron4_a, Iron4_b, Iron5_a, Iron5_b, Iron6_a, Iron6_b, Iron7_a, Iron7_b, Iron8_a, Iron8_b, Iron9_a, Iron9_b, Pwedge_a, Pwedge_b, Swedge_a, Swedge_b, Lwedge_a, Lwedge_b
    Driver_a, Driver_b, Wood3_a, Wood3_b, Wood5_a, Wood5_b, Iron3_a, Iron3_b, Iron4_a, Iron4_b, Iron5_a, Iron5_b, Iron6_a, Iron6_b, Iron7_a, Iron7_b, Iron8_a, Iron8_b, Iron9_a, Iron9_b, Pwedge_a, Pwedge_b, Swedge_a, Swedge_b, Lwedge_a, Lwedge_b = driver_a, driver_b, wood3_a, wood3_b, wood5_a, wood5_b, iron3_a, iron3_b, iron4_a, iron4_b, iron5_a, iron5_b, iron6_a, iron6_b, iron7_a, iron7_b, iron8_a, iron8_b, iron9_a, iron9_b, pwedge_a, pwedge_b, swedge_a, swedge_b, lwedge_a, lwedge_b
    totals =[]
    for hole in holes:
        distance = 0
        strokes = 0
        clubs = []
        distances = []
        d1s = []
        waters=[]
        global hlen, flen1, flen2, wtr1, wtr2, grn1, grn2
        hlen, flen1, flen2, wtr1, wtr2, grn1, grn2, name = hole
        while True:
            club1, d1 = stroke(distance)
            clubs.append(club1)
            if distance > hlen:
                d1 = -d1
            distance = distance + d1
            d1s.append(d1)
            if distance >= wtr1 and distance <= wtr2:
                #print 'water'
                waters.append(1)
                distance = distance - d1
                distances.append(distance)
                club1, d1 = water()
                if distance < wtr1:
                    d1 = - d1
                distance = distance + d1
                d1s.append(d1)
                clubs.append(club1)
            distances.append(distance)
            if distance >= grn1 and distance <= grn2:
                club1 = putt(distance)
                clubs.append(club1)
                break
        strokes =  countstrokes(clubs, distances, waters)
        totals.append(strokes)
        conditions = condition(distances)
        shots = len(d1s)
        print name, ':',
        for x in xrange(0,shots):
            print '{', clubs[x], ',', d1s[x],',', conditions[x],',', hlen-distances[x], '}',
        print '{',clubs[-1], '}', '{',strokes ,'}'
    print 'Total:', sum(totals), 'shots'
    return sum(totals)

Kode dijalankan seperti

golf(300,330,270,299,240,269,220,239,200,219,180,199,160,179,140,159,120,139,100,119,80,99,50,79,0,49)

dan keluar seperti ini:

Hole 1 : { Driver , 308 , fair , 93 } { P wedge , 96 , green , -3 } { 1 putt } { 3 }
Hole 2 : { 6-Iron , 166 , green , 5 } { 1 putt } { 2 }
Hole 3 : { Driver , 321 , fair , 117 } { 9-Iron , 105 , green , 12 } { 2 putts } { 4 }
Hole 4 : { Driver , 305 , rough , 553 } { S wedge , -62 , rough , 615 } { Driver , 326 , fair , 289 } { 3-Wood , 293 , green , -4 } { 1 putt } { 8 }
Hole 5 : { Driver , 323 , fair , 66 } { S wedge , 73 , green , -7 } { 2 putts } { 4 }
Hole 6 : { 8-Iron , 125 , green , 8 } { 2 putts } { 3 }
Hole 7 : { Driver , 314 , fair , 182 } { 5-Iron , 181 , green , 1 } { 1 putt } { 3 }
Hole 8 : { Driver , 324 , fair , 91 } { P wedge , 91 , green , 0 } { chip in } { 2 }
Hole 9 : { Driver , 317 , green , 3 } { 1 putt } { 2 }
Total: 31 shots

Ini adalah salah satu skor terendah dari banyak percobaan, dengan nilai terendah absolut dari 26 dalam 100.000 percobaan. Tetapi masih di bawah par khas 34-36 bahkan dengan 8 pukulan pada lubang 4.

Saya akan memasukkan kode yang saya gunakan untuk menemukan distribusi permainan dengan klub yang ditentukan di atas.

import matplotlib.pyplot as plt
class histcheck(object):

    def __init__(self):
        self = self

    def rungolf(self, n=10000):
        results=[]
        for x in xrange(0,n):
            shots = golf(300,330,270,299,240,269,220,239,200,219,180,199,160,179,140,159,120,139,100,119,80,99,50,79,0,49)
            results.append(shots)
        self.results = results

    def histo(self, n=20):
        plt.figure(figsize=(12,12))
        plt.hist(self.results, bins=(n))
        plt.title("Histogram")
        plt.xlabel("Shots")
        plt.ylabel("Frequency")
        plt.show()

Lari

play = histcheck()
play.rungolf()
play.hist()

memberikan histogram berikut Histogram Golf

dan mean dan median dapat ditemukan menggunakan

np.mean(play.results)
np.meadian(play.results)

rata-rata sekitar 43 dan median 41. Tidak terlalu buruk untuk 9 lubang dengan optimasi tembakan sederhana.

Itu milikmu sekarang

Teruskan dan salin dan atur program saya dan evaluasi dengan menggunakan alat saya untuk menurunkan jumlah rata-rata pemotretan. Beri tahu saya jika ada skenario apa pun yang tidak saya pertanggungjawabkan atau lanjutkan dan buat versi golf. Saya pikir program terbaik adalah yang menghasilkan rata-rata tembakan terendah untuk sejumlah input klub. Kode saya bukan pilihan terbaik untuk itu, tetapi saya pikir saya akan mendapatkan bola yang menggelinding.

Memperbarui

def water():
    if clubs[-1] =='S wedge':
        club = 'S wedge'
        d = randint(50,79)
    elif clubs[-1] !='S wedge':
        club = 'S wedge'
        d = -randint(50,79)
    else: print 'water error'
    return club, d

Dengan mengubah logika air sehingga berusaha memukul bola ke depan dengan jumlah kecil setelah menemukan air, bukannya mundur jika klub sebelumnya yang digunakan bukan baji pasir, itu meningkatkan rata-rata menjadi 40,5 dan median menjadi 39 setelah pengujian dengan satu juta berjalan. Minimal 23, maksimal 135. Terkadang Anda beruntung, terkadang tidak. Lihat histogram baru.

Histogram2

Adam
sumber