Start learning free

LESSON 249 OF 569 · FUNCTIONS & CLASSES

Score Keeper in Python: A Class That Tracks Total and Best

Practice O(1) Read the full explanation

A game shows each player two numbers: their total, all the points of their turns added up, and their best single turn. Write a class ScoreKeeper that keeps both numbers up to date as the points come in, and can start over.

Implement the class ScoreKeeper:

  • ScoreKeeper() creates a keeper with no points yet.
  • add(points) records the points of one turn.
  • total() returns the sum of all the points added since the keeper was created or last reset.
  • best() returns the highest points of a single add in that time, or 0 if there was no add yet.
  • reset() starts over: afterwards total() and best() both return 0 until the next add.

The input is a list of operations, applied in order to one new ScoreKeeper. The output lists what the total and best calls return, in order. The starter code spells these names the way your language does (in Go and Rust, ScoreKeeper is a struct with methods). Give the fields names that differ from the methods' names: in several languages a field named total would clash with the method total().

 

Example 1:

Input:
    add(10)
    add(25)
    add(5)
    total()
    best()
Output: 40 25
Explanation: 10 + 25 + 5 = 40. The best single turn was the 25.

Example 2:

Input:
    best()
    total()
    add(0)
    best()
    total()
Output: 0 0 0 0
Explanation: Before any add, both numbers are 0. A turn worth 0 points changes neither.

Example 3:

Input:
    add(30)
    add(50)
    total()
    best()
    reset()
    total()
    best()
    add(20)
    best()
    total()
Output: 80 50 0 0 20 20
Explanation: After reset() the keeper starts over. The 50 from before no longer counts,
so after add(20) the best is 20, not 50.

 

Constraints:

  • 0 <= points <= 1000
  • At most 300 operations on one ScoreKeeper.

Note:

Every method should run in O(1) time: add updates the two numbers as each turn comes in, so total and best never need to look back at old turns.

STEP 1 OF 7
    Ctrl + Enter to check

    PYTHON · FUNCTIONS & CLASSES

    Score Keeper in Python, explained

    Problem overview

    A game shows each player two numbers: the total of all their turns and their best single turn. The class ScoreKeeper keeps both up to date. add(points) records one turn, total() and best() report the two numbers, and reset() starts over. Before any add, both numbers are 0.

    In the first example, the turns 10, 25 and 5 give a total of 40 and a best of 25. In the third example the keeper adds 30 and 50, reports 80 and 50, resets, reports 0 and 0, then adds 20 and reports a best of 20 and a total of 20. The 50 from before the reset no longer counts.

    Approach: update two numbers as the points arrive

    You could store every turn in a list and compute the sum and the maximum when asked. That works, but each call would look through all the old turns. A simpler idea is to keep only two numbers on the object and update them in add. Then total() and best() just report a stored value, and all four methods run in O(1) time.

    The best starts at 0. Every score is at least 0, so 0 is a safe starting value: the first add can only match or beat it.

    Why the attributes are not called total and best

    The attributes are named total_points and best_points, not total and best. In Python an attribute set on the object hides a method of the same name. If the constructor did self.total = 0, then keeper.total() would try to call the number 0 and fail with 'int' object is not callable.

    Step by step

    1. Set self.total_points to 0 in __init__: a new keeper has seen no points.
    2. Set self.best_points to 0: the highest single add so far.
    3. In add, add the points to the total with +=. The total grows with every turn.
    4. Update the best only when the new score is higher. This is the same idea as finding the largest value in a list one value at a time. With >, an equal score leaves the best unchanged, which is the same number anyway.
    5. total returns self.total_points.
    6. best returns self.best_points.
    7. reset sets both attributes back to 0, the values a new keeper starts with.

    The solution in Python

    class ScoreKeeper:
        def __init__(self):
            self.total_points = 0
            self.best_points = 0
        def add(self, points: int) -> None:
            self.total_points += points
            if points > self.best_points:
                self.best_points = points
        def total(self) -> int:
            return self.total_points
        def best(self) -> int:
            return self.best_points
        def reset(self) -> None:
            self.total_points = 0
            self.best_points = 0
    

    Using it:

    k = ScoreKeeper()
    print(k.total(), k.best())
    for p in (30, 50):
        k.add(p)
    print(k.total(), k.best())
    k.reset()
    print(k.total(), k.best())
    k.add(20)
    print(k.best(), k.total())
    
    0 0
    80 50
    0 0
    20 20
    

    Edge cases and common mistakes

    • Asking before any add. Both methods return 0, because the constructor set both attributes to 0.
    • An add of 0. The total stays the same and, since 0 is not greater than the best, so does the best.
    • Forgetting to reset the best. If reset only clears the total, the old best of 50 survives and best() returns 50 after add(20) instead of 20.
    • Naming an attribute like a method. It breaks the method, as shown above.
    • Using = instead of += in add. The total would then hold only the last turn.
    Keep going with Python500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free