Skip to content

Instantly share code, notes, and snippets.

@mdenson-dayspring
Last active March 30, 2022 07:09
Show Gist options
  • Select an option

  • Save mdenson-dayspring/adde4b607f575038597abec4cac4c70b to your computer and use it in GitHub Desktop.

Select an option

Save mdenson-dayspring/adde4b607f575038597abec4cac4c70b to your computer and use it in GitHub Desktop.

Revisions

  1. Matthew Denson revised this gist Mar 30, 2022. 1 changed file with 38 additions and 44 deletions.
    82 changes: 38 additions & 44 deletions bowling.py
    Original file line number Diff line number Diff line change
    @@ -49,51 +49,45 @@
    import sys

    def score_game(pins):
    num_frame = 0
    running_score = 0
    frames = []
    ball = 0
    while ball < len(pins) and num_frame < 10:
    frame = {
    "frame": num_frame + 1,
    "pins": [],
    "score": None
    }
    frame_score_complete = False
    tmp = pins[ball]
    frame["pins"].append(pins[ball])
    if len(pins) > ball + 1 and pins[ball] != 10:
    ball = ball + 1
    tmp = tmp + pins[ball]
    frame["pins"].append(pins[ball])

    if tmp == 10:
    # spare
    if len(pins) > ball + 1:
    tmp = tmp + pins[ball + 1]
    frame_score_complete = True
    else:
    frame_score_complete = True

    return score_frame([], pins)
    def score_frame(running_score, pins):
    frame_num = len(running_score) + 1
    #terminal cases
    if len(pins) == 0:
    return running_score
    elif frame_num > 10:
    running_score[9]['pins'].extend(pins)
    return running_score

    if frame_num == 1:
    prev_score = 0
    else:
    prev_score = running_score[len(running_score) - 1]['score']

    if len(pins) > 0 and pins[0] == 10:
    # strike
    if prev_score == None or len(pins) < 3:
    score = None
    else:
    score = prev_score + pins[0] + pins[1] + pins[2]
    running_score.append({"frame": frame_num, "pins": pins[:1], "score": score})
    return score_frame(running_score, pins[1:])
    elif len(pins) > 1 and pins[0] + pins[1] == 10:
    # spare
    if prev_score == None or len(pins) < 3:
    score = None
    else:
    score = prev_score + pins[0] + pins[1] + pins[2]
    running_score.append({"frame": frame_num, "pins": pins[:2], "score": score})
    return score_frame(running_score, pins[2:])
    else:
    # open
    if prev_score == None or len(pins) < 2:
    score = None
    else:
    # strike
    if len(pins) > ball + 2:
    tmp = tmp + pins[ball + 1]
    tmp = tmp + pins[ball + 2]
    frame_score_complete = True

    if num_frame == 9:
    while ball + 1 < len(pins):
    ball = ball + 1
    frame["pins"].append(pins[ball])

    if frame_score_complete:
    running_score = running_score + tmp
    frame["score"] = running_score
    frames.append(frame)
    ball = ball + 1
    num_frame = num_frame + 1
    return frames
    score = prev_score + pins[0] + pins[1]
    running_score.append({"frame": frame_num, "pins": pins[:2], "score": score})
    return score_frame(running_score, pins[2:])

    def print_game(frames):
    top_bottom = ""
  2. mdenson-dayspring revised this gist Mar 30, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion bowling.py
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    #
    # An a little over the top Bowling Score app.
    # Copyright 2020 by Matthew Denson <[email protected]>
    # Copyright 2022 by Matthew Denson <[email protected]>
    #
    # Example Usage:
    # To score a set of bowls provided in JSON format in stdin.
  3. mdenson-dayspring created this gist Mar 30, 2022.
    221 changes: 221 additions & 0 deletions bowling.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,221 @@
    #
    # An a little over the top Bowling Score app.
    # Copyright 2020 by Matthew Denson <[email protected]>
    #
    # Example Usage:
    # To score a set of bowls provided in JSON format in stdin.
    # $ echo "[1,4,4,5,6,4,5,5,10,0,1,7,3,6,4,10,2,8,9]" | python3 bowling.py stdin
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # | 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # |1 4|4 5|6 /|5 /| X|0 1|7 /|6 /| X|2 / 9|
    # | | | | | | | | | | |
    # | 5 | 14 | 29 | 49 | 60 | 61 | 77 | 97 | 117 | 136 |
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    #
    # To score a game interactively
    # $ python3 bowling.py play
    # Let's play!
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # | 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # | | | | | | | | | | |
    # | | | | | | | | | | |
    # | | | | | | | | | | |
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # Your next roll: (0-10,x,X)
    # 8
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # | 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # |8 | | | | | | | | | |
    # | | | | | | | | | | |
    # | | | | | | | | | | |
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # Your next roll: (0-2,/)
    # /
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # | 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # |8 /| | | | | | | | | |
    # | | | | | | | | | | |
    # | | | | | | | | | | |
    # +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    # Your next roll: (0-10,x,X)
    # .....

    import argparse
    import json
    import sys

    def score_game(pins):
    num_frame = 0
    running_score = 0
    frames = []
    ball = 0
    while ball < len(pins) and num_frame < 10:
    frame = {
    "frame": num_frame + 1,
    "pins": [],
    "score": None
    }
    frame_score_complete = False
    tmp = pins[ball]
    frame["pins"].append(pins[ball])
    if len(pins) > ball + 1 and pins[ball] != 10:
    ball = ball + 1
    tmp = tmp + pins[ball]
    frame["pins"].append(pins[ball])

    if tmp == 10:
    # spare
    if len(pins) > ball + 1:
    tmp = tmp + pins[ball + 1]
    frame_score_complete = True
    else:
    frame_score_complete = True

    else:
    # strike
    if len(pins) > ball + 2:
    tmp = tmp + pins[ball + 1]
    tmp = tmp + pins[ball + 2]
    frame_score_complete = True

    if num_frame == 9:
    while ball + 1 < len(pins):
    ball = ball + 1
    frame["pins"].append(pins[ball])

    if frame_score_complete:
    running_score = running_score + tmp
    frame["score"] = running_score
    frames.append(frame)
    ball = ball + 1
    num_frame = num_frame + 1
    return frames

    def print_game(frames):
    top_bottom = ""
    num = ""
    bowls = ""
    space = ""
    scores = ""
    for f in frames:
    top_bottom = top_bottom + "+-----"
    num = num + "| {frame:>2}".format(frame = f["frame"])

    pins = f["pins"]
    if f["frame"] == 10: # 10th frame (special)
    pin_str = ""
    sum = 0
    for p in pins:
    sum = sum + p
    if p == 10:
    pin_str = pin_str + "X"
    sum = 0
    elif sum == 10:
    pin_str = pin_str + "/"
    sum = 0
    else:
    pin_str = pin_str + str(p)
    pin_str = pin_str + " "
    pin_str = pin_str.strip().ljust(5)
    bowls = bowls + "|" + pin_str
    elif len(pins) == 1:
    if pins[0] == 10:
    bowls = bowls + "| X"
    else:
    bowls = bowls + "|" + str(pins[0]) + " "
    else:
    if pins[0] + pins[1] == 10:
    bowls = bowls + "|" + str(pins[0]) + " /"
    else:
    bowls = bowls + "|" + str(pins[0]) + " " + str(pins[1])

    space = space + "| "

    if f["score"]:
    scores = scores + "| {score:^3} ".format(score = f["score"])
    else:
    scores = scores + "| "

    for f in range(len(frames)+1, 11):
    top_bottom = top_bottom + "+-----"
    num = num + "| {frame:>2}".format(frame = f)
    bowls = bowls + "| "
    space = space + "| "
    scores = scores + "| "

    print(top_bottom + "+")
    print(num + "|")
    print(top_bottom + "+")
    print(bowls + "|")
    print(space + "|")
    print(scores + "|")
    print(top_bottom + "+")

    def from_stdin(args):
    print_game(score_game(json.load(sys.stdin)))

    def interactive_game(args):
    print("Let's play!")
    frame_pins = 0
    curr_frame = 1
    pins = []
    done = False
    while not done:
    score = score_game(pins)
    print_game(score)
    if (len(score) == 10 and score[9]["score"]):
    done = True
    else:
    if len(score) > 0 and score[len(score) - 1]['score'] or frame_pins == 10:
    frame_pins = 0
    first_roll = True
    elif len(score) > 0:
    first_roll = False
    else:
    first_roll = True

    keep_reading = True

    if (first_roll):
    allowed = "0-10,x,X";
    else:
    max = 10 - frame_pins;
    allowed = "0-" + str(max) + ",/";
    while keep_reading:
    print("Your next roll: (" + allowed + ")")

    count = 0
    roll = input()
    if roll in ['0','1','2','3','4','5','6','7','8','9','10','/','x','X']:
    if roll == '/' and frame_pins > 0:
    count = 10 - frame_pins
    keep_reading = False
    elif roll == 'x' or roll == 'X':
    if frame_pins == 0:
    count = 10
    keep_reading = False
    else:
    count = int(roll)
    if count + frame_pins <=10:
    keep_reading = False
    pins.append(count)
    frame_pins = frame_pins + count

    parser = argparse.ArgumentParser()
    parser.add_argument('--version', action='version', version='1.0.0')

    subparsers = parser.add_subparsers()

    stdin_parser = subparsers.add_parser('stdin')
    stdin_parser.set_defaults(func=from_stdin)

    play_parser = subparsers.add_parser('play')
    play_parser.set_defaults(func=interactive_game)

    if __name__ == '__main__':
    args = parser.parse_args()
    args.func(args)