Tennis Score Calculation

MediumVeeam

Prompt

Your task is to implement a JavaScript function that takes an array of strings representing the winner of each point in a single game of tennis and returns the current score or the final result of that game.

Scoring Rules

  • A player's score progresses in the following sequence: 0 → 15 → 30 → 40.
  • If a player has 40 and scores the next point, they win the game, unless their opponent also has 40.
  • If both players reach a score of 40, the state is called DEUCE.
  • From DEUCE, a player must win two consecutive points to win the game.
    • Scoring one point from DEUCE gives that player ADVANTAGE.
    • If the player with ADVANTAGE scores the next point, they WIN the game.
    • If the player with ADVANTAGE loses the next point, the score returns to DEUCE.

Function Signature

/**
* Calculates the current score or result of a single tennis game.
* @param {string[]} points - An array of strings, where each string is either 'p1' or 'p2'.
* @returns {string} The current score or result of the game.
*/
function getTennisScore(points) {
// Implementation
}

Examples

InputOutput
['p1', 'p1', 'p2', 'p1', 'p1']"Player 1 wins"
['p1', 'p1', 'p1', 'p2', 'p2', 'p2']"DEUCE"
['p1', 'p1', 'p1', 'p2', 'p2', 'p2', 'p2']"ADVANTAGE Player 2"
['p1', 'p2', 'p1']"30 - 15"

Playground

Hint 1

Right now, you might be trying to figure out the score after every single point inside your loop. This can get complicated with all the special rules like DEUCE and ADVANTAGE.

Let's simplify. Forget about the tennis score names for a moment. Can you first write a simple loop that just counts the total number of points won by Player 1 and the total for Player 2? For example, if the input is ['p1', 'p1', 'p2'], your loop should finish with p1Points = 2 abd p2Points = 1.

Once you have these final totals, then you can write a separate block of if/else statements to look at those two numbers and decide what the correct score string should be. The final state of the game depends only on the total points, not the specific order they were won in.

Solution

Explanation

The solution works by first calculating the total points for each player and then checking the game's state in a specific order of precedence, from highest (win) to lowest (standard score).

  • Tally Points: The code begins by iterating through the input points array once. It uses two counters, p1Points and p2Points, to keep a running total of the points won by each player.
  • Check for a Win: The most important condition to check first is a win. The logic p1Points >= 4 && p1Points >= p2Points + 2 elegantly covers all win scenarios:
    • Winning from 40 (e.g., 4 points to 0, 1, or 2).
    • Winning from Advantage (e.g., 5 points to 3).
    • This single rule is robust and simplifies the logic significantly.
  • Check for Deuce or Advantage: If no player has won, the code checks if the game is in the "end-game" phase (Deuce or Advantage). This state is only possible if both players have scored at least 3 points (a score of 40).
    • If their point totals are equal, the state is DEUCE.
    • If one player is ahead by a single point, they have ADVANTAGE.
  • Handle Standard Scoring: If the game is not in a win or deuce/advantage state, it must be a standard score. The code uses a scoreNames array to map the point counts (0, 1, 2, 3) to their respective tennis names ("0", "15", "30", "40") and formats the output string.

Complexity Analysis

  • Time Complexity O(n): The time complexity is linear, where n is the number of points in the input array. The function's runtime is dominated by the single for loop that must iterate through every point to determine the score. It is impossible to know the result without examining each point, making this approach asymptotically optimal.
  • Space Complexity O(1): The space complexity is constant. The function uses a fixed number of variables (p1Points, p2Points, scoreNames) to store state. The amount of memory used does not grow with the size of the input points array. This is also optimal.

Common Mistakes

  • Processing Points Sequentially Instead of Tallying First
    • Mistake: Trying to calculate the score as the loop progresses. For example, inside the loop, checking if (p1Score === 3 && p2Score === 3) to set a deuce flag.
    • Why it's wrong: This is inefficient and complex. It's much simpler to let the loop finish tallying the points and then determine the final state based on the totals. The final score only depends on the total points, not the specific order they were scored in.
  • Incorrect Deuce/Advantage Threshold:
    • Mistake: Checking for deuce with if (p1Points === p2Points && p1Points >= 4).
    • Why it's wrong: Deuce occurs when scores are tied at 3-3 (40-40) or any higher score like 4-4, 5-5, etc. The condition should be p1Points >= 3.
00:00

Table of Contents