impossible

Finished
11class BowlingGame:
22 def __init__(self):
3 pass
4
3 self.rolls = []
4 self.current_roll = 0
5
56 def roll(self, pins):
6 pass
7
7 # Edge Case: Number of pins must be between 0 and 10
8 if pins < 0 or pins > 10:
9 raise ValueError("Pins must be between 0 and 10")
10
11 # Edge Case: Game is already over (10 frames completed)
12 if self.is_game_over():
13 raise ValueError("Cannot roll after game is over")
14
15 # Edge Case: In a frame, the total pins cannot exceed 10
16 if self.current_roll % 2 == 1 and not self.is_tenth_frame():
17 # This is the second roll of a frame (not tenth frame)
18 if self.rolls[-1] + pins > 10:
19 raise ValueError("Invalid roll: pins downed in a frame cannot exceed 10")
20
21 self.rolls.append(pins)
22 self.current_roll += 1
23
824 def score(self):
9 pass
25 # Edge Case: Game is not yet complete
26 if not self.is_game_over():
27 raise ValueError("Score cannot be taken until the end of the game")
28
29 total_score = 0
30 roll_index = 0
31
32 for frame in range(10):
33 # Edge Case: Not enough rolls to calculate score
34 if roll_index >= len(self.rolls):
35 raise ValueError("Invalid game state")
36
37 if self.is_strike(roll_index): # Strike
38 # Edge Case: Not enough rolls to calculate strike bonus
39 if roll_index + 2 >= len(self.rolls):
40 raise ValueError("Invalid game state")
41
42 total_score += 10 + self.strike_bonus(roll_index)
43 roll_index += 1
44 elif self.is_spare(roll_index): # Spare
45 # Edge Case: Not enough rolls to calculate spare bonus
46 if roll_index + 2 >= len(self.rolls):
47 raise ValueError("Invalid game state")
48
49 total_score += 10 + self.spare_bonus(roll_index)
50 roll_index += 2
51 else: # Open frame
52 total_score += self.sum_of_balls_in_frame(roll_index)
53 roll_index += 2
54
55 return total_score
56
57 def is_tenth_frame(self):
58 # Count complete frames
59 roll_count = len(self.rolls)
60 frame_count = 0
61 i = 0
62
63 while frame_count < 9 and i < roll_count:
64 if self.is_strike(i): # Strike
65 i += 1
66 else: # Open frame or spare
67 i += 2
68 frame_count += 1
69
70 # If we've processed 9 frames, we're now in the 10th frame
71 return frame_count == 9
72
73 def is_game_over(self):
74 # Count frames
75 roll_count = len(self.rolls)
76 frame_count = 0
77 i = 0
78
79 while frame_count < 10 and i < roll_count:
80 if frame_count < 9: # Frames 1-9
81 if self.is_strike(i):
82 i += 1
83 else:
84 i += 2
85 else: # 10th frame
86 # In the 10th frame, we need to handle special cases
87 remaining_rolls = roll_count - i
88
89 # If we haven't reached the 10th frame in the rolls yet
90 if i >= roll_count:
91 break
92
93 # Check if first roll is a strike
94 if self.rolls[i] == 10:
95 # Need 2 more rolls
96 if remaining_rolls >= 3:
97 i += 3
98 else:
99 return False
100 else:
101 # Check if it's a spare (two rolls)
102 if remaining_rolls >= 2 and self.rolls[i] + self.rolls[i+1] == 10:
103 # Need one more roll
104 if remaining_rolls >= 3:
105 i += 3
106 else:
107 return False
108 else:
109 # Open frame (two rolls)
110 if remaining_rolls >= 2:
111 i += 2
112 else:
113 return False
114 frame_count += 1
115
116 return frame_count >= 10 and i <= roll_count
117
118 def is_strike(self, roll_index):
119 return self.rolls[roll_index] == 10
120
121 def is_spare(self, roll_index):
122 return self.rolls[roll_index] + self.rolls[roll_index + 1] == 10
123
124 def strike_bonus(self, roll_index):
125 return self.rolls[roll_index + 1] + self.rolls[roll_index + 2]
126
127 def spare_bonus(self, roll_index):
128 return self.rolls[roll_index + 2]
129
130 def sum_of_balls_in_frame(self, roll_index):
131 return self.rolls[roll_index] + self.rolls[roll_index + 1]
132# Handled Edge Cases: Invalid pin count (negative or >10), rolling after game over, invalid frame pin count (>10 in a frame), scoring before game completion, insufficient rolls for strike/spare bonus calculations, invalid game state
Test NameStatus
test_all_strikes_is_a_perfect_game
Fail
test_consecutive_strikes_each_get_the_two_roll_bonus
Fail
test_points_scored_in_the_two_rolls_after_a_strike_are_counted_twice_as_a_bonus
Fail
test_the_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike
Fail
test_two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Fail
test_a_roll_cannot_score_more_than_10_points
Pass
test_a_spare_followed_by_zeros_is_worth_ten_points
Pass
test_a_spare_in_the_last_frame_gets_a_one_roll_bonus_that_is_counted_once
Pass
test_a_strike_earns_ten_points_in_a_frame_with_a_single_roll
Pass
test_a_strike_in_the_last_frame_gets_a_two_roll_bonus_that_is_counted_once
Pass
test_a_strike_with_the_one_roll_bonus_after_a_spare_in_the_last_frame_does_not_get_a_bonus
Pass
test_an_incomplete_game_cannot_be_scored
Pass
test_an_unstarted_game_cannot_be_scored
Pass
test_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated
Pass
test_cannot_roll_after_bonus_roll_for_spare
Pass
test_cannot_roll_after_bonus_rolls_for_strike
Pass
test_cannot_roll_if_game_already_has_ten_frames
Pass
test_consecutive_spares_each_get_a_one_roll_bonus
Pass
test_last_two_strikes_followed_by_only_last_bonus_with_non_strike_points
Pass
test_points_scored_in_the_roll_after_a_spare_are_counted_twice
Pass
test_rolling_a_spare_with_the_two_roll_bonus_does_not_get_a_bonus_roll
Pass
test_rolls_cannot_score_negative_points
Pass
test_second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points
Pass
test_should_be_able_to_score_a_game_with_all_zeros
Pass
test_should_be_able_to_score_a_game_with_no_strikes_or_spares
Pass
test_strikes_with_the_two_roll_bonus_do_not_get_bonus_rolls
Pass
test_two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike
Pass
test_two_rolls_in_a_frame_cannot_score_more_than_10_points
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.