골프 좀 줘


15

이전에 골프를 치지 않았다면이 질문에 사용한 골프 관련 용어 목록이 있습니다.

  • 슛 ( 스트로크 라고도 함) : 볼을 칠 때마다이 샷입니다.
  • 구멍 : 골프 코스는 구멍으로 나뉘며, 목표는 가능한 한 적은 샷으로 지정된 위치에서 다른 위치로 공을 치는 것입니다.
  • : 당신이 구멍을 시작하는 곳.
  • 또는 깃발 : 구멍을 뚫는 곳
  • 페어웨이 , 러프 , 워터그린 : 골프 공의 특징으로 실제 생활에서 볼을 플레이하는 방법에 영향을줍니다. (프로그램에 미치는 영향은 아래에 명시되어 있습니다)

나는 내일 골프를하려고하는데 가끔은 어떤 클럽을 어떤 야드에 부딪 치기 위해 어떤 클럽을 사용할지 알아내는 데 어려움을 겪는다는 것을 알았습니다. 그래서 나는 클럽들과 그들의 야드 수를 기록 할 것을 결정했습니다.

첫 가정 : 모든 홀은 티 박스 북쪽에 있습니다.

이 모든 야드 수는 공이 북쪽으로 얼마나 멀리 이동할 수 있는지 측정합니다. 공은 각 클럽에 대해 지정된 범위 사이의 임의의 정수 거리를 여행합니다 (포함).

마스터 골퍼로서, 어떤 샷도 수평 이동이 없습니다. 이것은 모든 샷이 깃발에서 직접 직선으로 간다는 것을 의미합니다.

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)

프로그래밍을 좋아하는 사람으로서, 나는 골프 라운드를 모델링하고 내일 얼마나 잘하고 싶은지 목표를 설정하기로 결정합니다. 그러나 아마추어 프로그래머와 마찬가지로 10 분 후에 포기하고 스택 오버 플로우 (농담)에 대한 도움을 요청했습니다. 코스에 대한 더 많은 데이터가 있습니다.

두 번째 가정 : 홀 지리

  • 코스의 거리를 나타내는 모든 숫자는 정수입니다.

  • 각 구멍은 직선입니다. 각 구멍과 핀 (구멍의 끝) 사이의 직선 거리는입니다 Length.

  • 페어웨이는에 의해 정의 된 길이의 세그먼트입니다 flen. 에 대한 값 flen은 페어웨이가있는 티에서 북쪽으로 야드 범위입니다.

  • 물 위험은로 정의 된 길이를 가진 세그먼트로 wlen, 속성은와 동일합니다 flen.

  • 녹색의 길이는에 의해 정의됩니다 glen.

  • 페어웨이, 물 또는 녹색이 아닌 코스의 모든 부분이 거칠습니다.

다음은 코스의 각 구멍을 설명하는 차트입니다.

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

골프를하는 방법 (이 프로그램을 위해)

  • 항상 깃발을 겨냥하십시오.
  • 공을 페어웨이 나 (바람직하게는) 녹색으로 유지하려고 노력하면서 가능한 한 핀 가까이에 공을칩니다.
  • 물에 샷을 넣을 때 다음 샷은 물에 들어간 샷과 같은 곳에서 플레이해야합니다.
  • 공이 녹색에 떨어지면 퍼터 만 사용할 수 있습니다. 볼이 핀에서 5 야드 이상 떨어지면 두 번 퍼팅합니다. 그렇지 않으면, 나는 한 번 퍼팅했다.
  • 핀을 지나쳐 샷을 칠 수 있습니다.

채점

구멍에 대한 내 점수는 내가 촬영 한 샷 수와 거친 물 또는 물에 착륙 할 때마다 한 번의 스트로크입니다.

프로그램

자, 그것은 많은 규칙이었습니다. 이제 프로그램에 대해 이야기합시다.

과정은 일정하기 때문에 과정은 프로그램에서 위와 같이 정의해야합니다 . 그러나 골퍼마다 샷마다 거리가 다르기 때문에 STDIN으로의 입력은 클럽 번호 순서에 따라 정렬되고 공백없이 쉼표로 구분 된 일련의 야드 범위 여야합니다.

결과는 내가 골프 라운드를 "플레이"하는 방법이어야합니다. 홀 수는 각 구멍 의 시작 부분에 현재 구멍이있는 Hole #:위치 로 지정해야합니다 #. 퍼팅이 아닌 각 샷의 형식은 다음과 같습니다 {club,distance of shot,condition of ball,distance to pin}. 샷의 세부 사항은 쉼표로 구분되지만 위 순서의 공백은 없어야합니다. 샷 자체는 공간별로 어떻게 재생되고 분리되는지 순서대로 작성해야합니다. 공이 녹색에 떨어지면 프로그램은 내가 몇 개의 퍼팅을하는지 형식으로 인쇄해야합니다 {# putts}. 각 줄의 끝에서 내가 홀에서 찍은 샷 수는 공백으로 다른 샷과 분리되어 다음과 같이 인쇄되어야합니다.(#). 각 구멍은 자체 줄에 있어야하며 순서대로 작성해야합니다. 마지막으로, 프로그램의 마지막 (10 번째) 줄에서 라운드의 총 샷 수는로 인쇄되어야합니다 Total: # shots.

프로그램에 필요한 "전략"은 없습니다. 원하는 전략으로 프로그램을 작성할 수 있습니다. 예를 들어 전략은 녹색에 착륙 할 확률을 최대화하고 홀에 도달 할 때까지 각 샷의 거리를 최대화합니다.

샘플 입력

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

샘플 출력

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

CG.SE의 첫 번째 게시물에는 다소 야심 찬 도전이라는 점을 인정할 것입니다. 도와 주셔서 감사합니다.


2
우리가 골퍼가 아닌 사람들에게 당신이 많은 골프 용어 (예 : "티 박스"와 "수평 이동")를 사용하지 않았다면 정말 감사하겠습니다. :)
kirbyfan64sos

골프 관련 용어 목록을 추가하겠습니다. 골프를 할 때 공이 항상 똑바로 가지는 않으므로 공이 항상 구멍을 향해 직접 이동하므로 수평 이동이 없습니다.
Arcturus

핀이 301 야드이고 야드에서 페어웨이가 있고 0~299, 마당에서 녹색, 300~315마당에서 물 이 있다고 가정하십시오 316~330. 어떤 클럽이 선택됩니까? 물을 거칠게 교체하면 어떻게됩니까?
lirtosiast

이상적으로 프로그램은 자체 전략을 수립 할 수 있어야합니다.
Arcturus

"최적의 전략"은 무엇을 의미합니까? 평균 스트로크 횟수를 최소화 하시겠습니까? 승리 기준에 관해서는 코드 골프와 함께 갈 것입니다.
lirtosiast

답변:


9

파이썬 2.7 : 43 40.5 발의 평균

이것은 여기의 첫 번째 게시물이므로 나와 함께하십시오.

포스터는 이것을 코드 골프가 아닌 프로그래밍 문제로 취급하려고 생각했기 때문에 프로그래밍 문제로 다루었습니다. 나는 솔루션을 유지하고 논리를 간단하게 유지하려고 시도했지만 일이 빨리 복잡 해져서 더 추악한 것으로 판명되었습니다.

내 코드

읽을 때 고려해야 할 사항 :이 프로그램은 '클럽'이라는 클럽 목록과 볼이 티에서 이동 한 거리 인 '거리'라는 목록을 생성합니다. 각 샷이 이동하는 거리.

먼저 코스를 정의합니다. 각 페어웨이, 물 및 녹색 길이를 정의해야 나중에 프로그램에서 볼의 상태를 확인할 수 있으므로 존재하지 않는 코스 부분에 정수가 아닌 값을 추가했습니다.

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]

여기에서는 클럽을 선택하는 주요 논리를 정의했습니다. 이 프로그램은 최대 운전자 거리보다 큰 모든 길이의 운전자를 선택하여 거리를 최대화하려고 시도하고 그렇지 않으면 홀까지의 거리가 포함 된 범위를 가진 클럽을 선택합니다. 이를 위해서는 클럽 입력에서 제공하는 범위가 연속적이어야합니다. 즉, 샷 거리에 차이가 없습니다. 샷의 거리를 차기 가장 강력한 클럽의 최대 거리로 제한하기 위해 전체 백스윙없이 클럽을 칠 수 있기 때문에 현실적인 요구 사항입니다.

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

다음으로, 5 야드보다 큰 모든 길이의 퍼팅 2 개와 홀 1 개를 퍼팅하는 퍼팅 함수를 정의합니다. 또한 '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

여기 전략이 약간 펑키 해집니다. 간단하게 유지하고 이전 샷의 위치에서 볼을 떨어 뜨리고 물로 다시 운전하기 위해서만 물에 몰아 넣는 루프에 갇히는 것을 방지하기 위해 실제로 모래로 쐐기로 뒤로 공을 쳤다. 그런 다음 코드가 다시 한번 샷을 평가하게하여 다음 샷이이를 클리어 할 수 있도록 물 앞에서 바로 촬영하십시오. 이 전략은 거친 벌칙에 의해 벌칙을 받지만 물 정화에 효과적입니다.

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

이 프로그램은 해당 홀이 재생 된 후 홀당 스트로크 수를 계산합니다. 러프에서 샷에 대한 처벌을 추가하고 각 워터 샷 후에 추가되는 물이라는 배열을 합산하여 물에 부딪히는 것에 대한 처벌을 추가합니다. 이것은 페어웨이가 항상 코스의 모든 구멍에 대해 물이나 녹색으로 이어진다는 사실을 이용합니다. 페어웨이 중간에 거친 코스가 있으면 변경해야합니다.

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

메인 코드가 실행 된 후, 상태는 공이 홀 중에 있던 거리를보고 공의 상태를보고합니다. 나는 메인 프로그램에서 공을 물에 부딪히는 것을 치료하는 방식 때문에 한 가지 문제가 발생했습니다. 프로그램에서 공이 물에 부딪히면 즉시 공이 맞은 위치로 다시 이동했습니다. 공이 뒤로 이동 한 후 거리가 기록되어 공의 상태가 '물'이 될 수 없습니다. 당신이 구멍 4의 티에서 공을 물에 부딪히면, 프로그램은 공과 클럽에 부딪힌 거리를 인쇄하지만 구멍까지의 길이는 변하지 않고 공을 떨어 뜨려서 상태가 '거칠게'됩니다. 거칠기에 0 거리. 인쇄물 '물'의 주석을 해제 할 수 있습니다

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

다음은 구멍을로드하고 게임을하는 코드의 주요 부분입니다. 몇 가지 조건을 초기화 한 후 코드는 구멍에 구멍을 치는 '스트로크'를 실행합니다. 물이 발생하면 페널티 카운터에 추가되어 프로그램 워터를 실행하고 볼을 원래 위치로 이동 한 후 공을 다시 움직입니다. 녹색이 발견되면 put이 호출되고 구멍이 종료됩니다. 거리와 클럽을 분석 한 후 각 샷의 상태를 결정하고 샷을 계산합니다.

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)

코드는 다음과 같이 실행됩니다

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)

아웃은 다음과 같습니다.

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

이것은 많은 시행에서 가장 낮은 점수 중 하나였으며, 100,000 회 실행에서 절대적으로 26 개였습니다. 그러나 여전히 홀 4에서 8 스트로크로도 34-36의 일반적인 수준 아래에 있습니다.

위에서 지정한 클럽과의 게임 배포를 찾는 데 사용한 코드를 포함하겠습니다.

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

달리는

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

다음 히스토그램을 제공합니다 골프 히스토그램

평균과 중앙값은

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

간단한 샷 최적화로 9 홀의 경우 나쁘지 않습니다.

이제 다 너야

계속해서 프로그램을 복사 및 조정하고 평균 샷 수를 줄이기 위해 도구를 사용하여 프로그램을 평가하십시오. 내가 설명하지 않았거나 진행하지 않은 시나리오가 있는지 알려주고 골프 버전을 만드십시오. 최고의 프로그램은 많은 클럽 입력에 대해 가장 낮은 평균 샷을 반환하는 것이라고 생각합니다. 내 코드는 최선의 선택은 아니지만 볼을 굴릴 것이라고 생각했습니다.

최신 정보

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

이전에 사용했던 클럽이 모래 웨지가 아닌 경우 물을 마주 친 후 뒤로 물을 마신 후 소량으로 공을 치기 위해 물 논리를 변경하여 하나의 테스트로 평균을 40.5로, 중앙값을 39로 개선했습니다. 백만 실행. 최소 23, 최대 135. 때로는 운이 좋으며 때로는 그렇지 않습니다. 새로운 히스토그램을 확인하십시오.

히스토그램 2

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.