Bana biraz golf kodla


15

Daha önce golf oynamadıysanız, bu soruda kullandığım golf ile ilgili terimlerin listesi

  • Shot , ayrıca denilen inme : top isabet her zaman, bu bir fırsat.
  • Delik : Bir golf sahası deliklere ayrılmıştır, burada amaç bir yerden bir yere diğerine olabildiğince az atışla vurmaktır.
  • Tee : Bir delik açtığınız yer.
  • Pim veya Bayrak : Bir deliği bitirdiğiniz yer
  • Fairway , Rough , Water ve Green : Golf sahasındaki kişinin gerçek hayatta topu nasıl oynadığını etkileyen özellikler. (Programı nasıl etkiledikleri aşağıda belirtilmiştir)

Yarın golf oynamaya gidiyorum ve bazen, belirli bir yardağı vurmak için hangi kulübün kullanılacağını bulmakta zorlanıyorum. Bu yüzden kulüplerimi ve atışları arasındaki iplikleri yazmaya karar verdim.

İlk Varsayım: Tüm delikler, tee kutularının kuzeyinden kaynaklanmaktadır.

Tüm bu iplikler topun ne kadar kuzeye gittiğini gösterir. Top, her bir kulüp için belirtilen sınırlar (dahil) arasında rastgele bir tamsayı mesafe kat edecektir.

Usta bir golfçü olarak, hiçbir atışımın yatay kayması yok. Bu, tüm çekimlerimin doğrudan bayrağa düz bir çizgide gittiği anlamına geliyor.

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)

Programlamadan hoşlanan bir kişi olarak, bir tur golf modellemek ve yarın ne kadar iyi yapmak istediğime bir hedef koymak istediğime karar veriyorum. Ancak, herhangi bir amatör programcı gibi, on dakika sonra vazgeçtim ve Stack Overflow (sadece şaka) konusunda yardım istedim. İşte kurs hakkında daha fazla veri.

İkinci Varsayım: Delik Coğrafyası

  • Parkurdaki mesafeleri tanımlayan tüm sayılar tamsayıdır.

  • Her delik düz bir çizgidir. Her delik ve pim (deliğin ucu) arasındaki düz çizgi mesafesi Length.

  • Fairwayler, uzunluğu ile tanımlanan segmentlerdir flen. Listelenen değer flen, fairway'in bulunduğu tee'den kuzeydeki iplikler aralığıdır.

  • Su tehlikeleri, uzunluğu ile tanımlanan wlenve aynı özelliklere sahip segmentlerdir flen.

  • Yeşil, tarafından tanımlanan bir uzunluğa sahiptir glen.

  • Parkurun fairway, su veya yeşil olmayan tüm kısımları pürüzlüdür.

İşte parkurdaki her deliği açıklayan bir grafik.

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

Golf nasıl oynanır (bu program için)

  • Daima tam olarak bayrağa nişan al.
  • Topu fairway üzerinde veya (tercihen) yeşil üzerinde tutmaya çalışırken topa mümkün olduğunca yakın pime vurun.
  • Suya bir atış yaptığınızda, bir sonraki atışınız suya giren atışla aynı yerden oynanmalıdır.
  • Top yeşile indiğinde, sadece atıcı kullanılabilir. Top kesinlikle pimden 5 metreden fazla inerse, iki kez koydum. Aksi takdirde, bir kez koydum.
  • Pimi geçerek bir vuruş yapmak mümkündür.

puanlama

Bir delikteki puanım çektiğim çekim sayısı artı her kaba veya suya indiğimde bir vuruş.

Program

Tamam, bu birçok kuraldı, şimdi program hakkında konuşalım.

Kurs , programda yukarıdaki gibi tanımlanmalıdır , çünkü kurs sabittir. Bununla birlikte, farklı golfçüler her atış için farklı mesafelere sahiptir, bu nedenle STDIN'e giriş, kulüp numarası sırasına göre düzenlenmiş ve virgülle (boşluk olmadan) ayrılmış bir dizi yarda aralığı olmalıdır.

Çıktı ben golf turu nasıl "oynamak" olmalıdır. Muhafaza numarası, her satırın başında geçerli delik Hole #:olduğu gibi belirtilmelidir #. Bir vurmak değil her atış aşağıdaki şekli şöyledir: {club,distance of shot,condition of ball,distance to pin}. Çekimin detayları virgülle ayrılmalıdır, ancak yukarıdaki sırada boşluk bırakılmamalıdır. Çekimlerin kendileri, nasıl bir boşlukla oynandıkları ve ayrıldıkları sırasıyla yazılmalıdır. Top yeşile indiğinde, program kaç tane koyduğum biçiminde yazdırmalıdır {# putts}. Her çizginin sonunda, deliğe aldığım çekim sayısı bir boşlukla diğer çekimden ayrılmalı ve(#). Her delik kendi satırında olmalı ve sırayla yazılmalıdır. Son olarak, programın son (onuncu) satırında, tur için toplam atış sayısı olarak yazdırılmalıdır Total: # shots.

Programınızın alması gereken belirli bir "strateji" yoktur. İstediğiniz stratejiye sahip bir program yazabilirsiniz. Örnek stratejiler arasında yeşile iniş şansının yüzdesini en üst düzeye çıkarmak ve deliğe ulaşana kadar her atışın mesafesini en üst düzeye çıkarmak yer alır.

ÖRNEK GİRİŞ

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

ÖRNEK ÇIKTI

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

İtiraf edeceğim, bu CG.SE'deki ilk yazı için oldukça iddialı bir meydan okuma, bu yüzden yorumlarda bu zorluğun nasıl iyileştirileceği hakkında konuşmaktan memnuniyet duyarım. Yardımın için teşekkürler.


2
Bizim için golfçü olmayanlar için, çok golf terimleri (örneğin "tee kutuları" ve "yatay geçiş") kullanmak vermedi eğer gerçekten takdir ediyorum. :)
kirbyfan64sos

Golf ile ilgili terimlerin bir listesini ekleyeceğim. Golf oynarken top her zaman düz gitmez, bu yüzden topun her zaman doğrudan deliğe doğru gittiğini ve böylece yatay bir kayması olmadığını söyledim.
Arcturus

Pimin 301 yarda olduğunu ve yardalardan fairway, 0~299yardalardan yeşil ve 300~315yardalardan su olduğunu 316~330varsayalım. Hangi kulüp seçilecek? Su kaba ile değiştirilirse ne olur?
lirtosiast

İdeal olarak, program kendi stratejisini bulabilmelidir.
Arcturus

"En uygun strateji" ile ne demek istiyorsun? Ortalama vuruş sayısını en aza indirgiyor musunuz? Kazanan kriter gelince ben kod-golf ile gitmek istiyorum.
lirtosiast

Yanıtlar:


9

Python 2.7: 43 40.5 atış ortalaması

Bu benim ilk yazım, bu yüzden bana katlan.

Poster, bunu golf kodlama değil, bir programlama zorluğu gibi ele almayı düşündüğünden, daha çok bir programlama zorluğu olarak ele aldım. Çözümümü ve atış mantığımı basit tutmaya çalıştım ama işler çabucak karmaşıklaştıkça daha çirkinleşti.

Kodum

Okurken düşünülmesi gereken bazı şeyler: program, 'kulüpler' adı verilen kulüplerin bir listesini ve topun tee'den kat ettiği mesafe olan mesafeler denilen bir liste oluşturur, hlen deliğin uzunluğu, d1s her çekimin kat ettiği mesafe.

Önce kursu tanımlarım. Her fairway, su ve yeşil uzunluk tanımlanmalıydı, böylece daha sonra program topun durumunu kontrol edebilsin, bu yüzden parkurun mevcut olmayan kısımları için tamsayı olmayan değerler ekledim.

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]

Burada bir kulüp seçmek için ana mantığı tanımladım. Program, maksimum sürücü mesafesinden daha büyük tüm uzunluklar için sürücüyü seçerek mesafeyi en üst düzeye çıkarmaya çalışır ve deliğe olan mesafeyi içeren bir kulüp seçer. Bu, kulüp girdisinin sağladığı aralıkların sürekli olmasını gerektirir, yani atış mesafesinde boşluk olmaz. Gerçekçi bir gereksinim, çünkü atışlarının mesafesini bir sonraki en güçlü kulübün maksimum mesafesiyle sınırlamak için tam bir geri dönüş olmadan bir kulübe vurabilir.

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

Daha sonra, deliğe 5 metreden daha büyük tüm uzunluklar için iki ve 5 ve daha az bir putt için bir put fonksiyonu tanımlarım. Ayrıca topu doğrudan 'chip in' adı verilen deliğe vurmak için bir seçenek de ekliyorum.

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

İşte strateji biraz korkaklaşıyor. Basit tutmak ve aynı zamanda sadece önceki atışın bulunduğu yere topu düşürmek ve tekrar suya sürmek için suya sürülme döngüsünde sıkışmayı önlemek için, aslında geri izlerim, kum kama ile topa geriye doğru vurur ve daha sonra kodun bu kez tekrar değerlendirilmesini sağlayın, umarım bir sonraki atış bunu temizleyebilir. Bu strateji kaba bir ceza ile cezalandırılır ancak suyu temizlemek için etkilidir.

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

Bu program, bu delik oynatıldıktan sonra delik başına vuruş sayısını sayar. Kaba atışlar için cezalar ekler ve her su atışından sonra eklenen su denilen bir diziyi toplayarak suya çarpma cezalarını ekler. Bu, fairway'in parkurdaki her delik için her zaman suya veya yeşile yol açmasından yararlanır. Fairway'in ortasında kaba olan kurslar için değiştirilmesi gerekecektir.

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

Ana kod çalıştıktan sonra, durum topun delik sırasında bulunduğu mesafelere bakar ve topun durumunu rapor eder. Ana programda topa suya vurma muamelem yüzünden bir sorunla karşılaştım. Programda, eğer top suya vurulursa, hemen şutun vurulduğu yere geri taşındı. Mesafe, top geri hareket ettirildikten sonra kaydedildi, böylece topun durumu 'su' olamaz. Eğer topa delik 4 üzerindeki tekten suya vurursanız, program topa ve kulübe vurduğunuz mesafeyi yazdırır, ancak deliğin uzunluğu değişmeden kalacaktır ve top şut düştüğü için durum 'pürüzlü' olacaktır. Kaba olan 0 mesafe. Bir baskı 'su' önerisini kaldırabilirsiniz

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

İşte kodun delikleri yükleyen ve oyunu oynayan ana kısmı. Bazı koşullar başlatıldıktan sonra, kod, deliğin aşılması durumunda tersi de dahil olmak üzere topa su veya yeşil ile karşılaşılana kadar topa doğru vurarak 'inme' çalıştırır. Su ile karşılaşılırsa, bir ceza sayacına eklenir ve program suyunu çalıştırır ve topu vurulduğu yere geri götürdükten sonra. Yeşil ile karşılaşılırsa, koy denir ve delik sonlandırılır. Mesafeler ve kulüpler analiz edildikten sonra her atışın durumunu belirlemek için çekimler yapılır.

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)

Kod şöyle çalıştırılır

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)

ve çıkış şöyle:

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

Bu, 100.000 koşuda 26'nın mutlak en düşük olduğu birçok denemenin en düşük skoruydu. Ancak hala delik 4 üzerinde 8 vuruş ile 34-36 tipik bir par altında.

Yukarıda belirtilen kulüplerle oyunların dağılımını bulmak için kullandığım kodu ekleyeceğim.

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

Koşu

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

aşağıdaki histogramı verir Golf Histogramı

ve ortalama ve medyan kullanılarak

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

ortalama 43 ve ortalama 41. Basit atış optimizasyonu ile 9 delik için çok da kötü değil.

Şimdi hepsi senin

Devam edin ve programımı kopyalayıp düzenleyin ve ortalama çekim sayısını azaltmak için araçlarımı kullanarak değerlendirin. Hesap vermediğim bir senaryo olup olmadığını bana bildirin veya devam edin ve golf edilmiş bir versiyon yapın. En iyi programın, bir takım kulüp girdileri için en düşük ortalama çekimleri döndüren program olacağını düşünüyorum. Kodum bunun için en iyi seçenek değil ama topu yuvarlayacağımı düşündüm.

Güncelleme

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

Su mantığını değiştirerek, önceki kulüp kum takozu değilse, geriye doğru yerine su ile karşılaştıktan sonra küçük bir miktar ileri doğru vurmaya çalışır, biriyle test ettikten sonra ortalamayı 40.5'e ve medyanı 39'a yükseltti. milyon koşu. En az 23, en fazla 135. Bazen şanslı olursun, bazen yapmazsın. Yeni histogramı inceleyin.

Histogram2

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.