Facebook Pixel

3921. Score Validator

Easy
LeetCode ↗

Problem Description

You are given a string array events.

Initially, you have two values: score = 0 and counter = 0. As you read through the array, each element tells you what action to take:

  • If the element is one of the number strings "0", "1", "2", "3", "4", or "6", you add that number's value to score.
  • If the element is "W", you increase counter by 1, but you do not change score.
  • If the element is "WD", you add 1 to score.
  • If the element is "NB", you add 1 to score.

You process the elements one by one, from left to right. You stop processing as soon as either of these conditions becomes true:

  • You have processed every element in events, or
  • The counter reaches 10.

In other words, once counter hits 10, you immediately stop and ignore any remaining events.

Your task is to return an integer array [score, counter], where:

  • score is the final total score after processing stops.
  • counter is the final counter value after processing stops.
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

How We Pick the Algorithm

Why Simulation / Basic DSA?

This problem maps to Simulation / Basic DSA through a short path in the full flowchart.

DirecttransformationoryesComplexdatastructure?noSimulation /Basic DSA

Following the described procedure step by step produces the solution.

Open in Flowchart

Intuition

The problem gives us a clear set of rules and asks us to follow them step by step. There is no hidden trick or clever formula to find — we just need to do exactly what the problem describes. This naturally points us toward a simulation approach.

The key idea is to keep track of two running values, score and counter, and update them as we walk through the array from left to right. For each event, we simply check which category it falls into:

  • A numeric string contributes its value to score.
  • A "W" increases counter by 1.
  • Anything else ("WD" or "NB") adds 1 to score.

The only thing we must be careful about is the stopping condition. Besides reaching the end of the array, we also need to stop the moment counter becomes 10. So right after we increase counter, we check whether it has hit 10, and if it has, we break out of the loop immediately. This ensures we ignore any events that come after the counter reaches 10.

Since we only pass through the array once and do constant work for each element, this straightforward simulation is both simple to write and efficient.

Solution Approach

Solution 1: Simulation

We can directly simulate the process described in the problem to calculate the final score and counter value.

First, we initialize two variables score and counter, both set to 0, representing the current total score and counter value respectively. Then we iterate through each event in the array events and update score and counter based on the event type:

  • If the event is a numeric string (checked using event.isdigit()), we convert it to an integer with int(event) and add it to score.
  • If the event is the string "W", we increment counter by 1 and check whether it has reached 10; if so, we immediately break out of the loop to stop processing.
  • Otherwise (the event is "WD" or "NB"), we add 1 to score.

After processing all events, or after stopping early when the counter reaches 10, we return an array [score, counter] containing the final values.

The time complexity is O(n), where n is the length of the array events, since we traverse the array at most once. The space complexity is O(1), as we only use a constant amount of extra space.

Example Walkthrough

Let's trace through a small example to see how the simulation works.

Suppose events = ["4", "W", "WD", "6", "W", "NB"].

We start with score = 0 and counter = 0, then process each element from left to right:

  1. "4" — This is a numeric string. We convert it to the integer 4 and add it to score.

    • score = 0 + 4 = 4, counter = 0
  2. "W" — This is a wicket. We increment counter by 1, then check if it reached 10. It hasn't, so we continue.

    • score = 4, counter = 1
  3. "WD" — This is neither a number nor "W", so we add 1 to score.

    • score = 4 + 1 = 5, counter = 1
  4. "6" — This is a numeric string. We add 6 to score.

    • score = 5 + 6 = 11, counter = 1
  5. "W" — Another wicket. We increment counter by 1, then check if it reached 10. It hasn't (it's 2), so we continue.

    • score = 11, counter = 2
  6. "NB" — This is neither a number nor "W", so we add 1 to score.

    • score = 11 + 1 = 12, counter = 2

We've now processed every element in the array, so we stop. The final result is [12, 2].

Notice how the stopping condition never triggered here because counter only reached 2. If instead the array had enough "W" events to push counter to 10, we would have broken out of the loop right at that moment — ignoring any events that came afterward. This is exactly why we check counter == 10 immediately after each increment, rather than only at the end.

Solution Implementation

1class Solution:
2    def scoreValidator(self, events: list[str]) -> list[int]:
3        # Running total of points accumulated from the events
4        total_score: int = 0
5        # Number of warning ("W") events encountered
6        warning_count: int = 0
7
8        for event in events:
9            if event.isdigit():
10                # Numeric event: add its integer value to the score
11                total_score += int(event)
12            elif event == "W":
13                # Warning event: increase the warning counter
14                warning_count += 1
15                # Stop processing once warnings reach the limit of 10
16                if warning_count == 10:
17                    break
18            else:
19                # Any other event contributes a single point
20                total_score += 1
21
22        # Return the final score together with the warning count
23        return [total_score, warning_count]
24
1class Solution {
2    public int[] scoreValidator(String[] events) {
3        // Accumulates the total score derived from numeric and other events
4        int score = 0;
5        // Tracks how many times the special "W" event has occurred
6        int counter = 0;
7
8        // Iterate through each event in the input array
9        for (String event : events) {
10            // Case 1: the event is a sequence of one or more digits
11            if (event.matches("\\d+")) {
12                // Convert the numeric string to an int and add it to the score
13                score += Integer.parseInt(event);
14            } else if (event.equals("W")) {
15                // Case 2: the event is "W"
16                // Pre-increment the counter, then check if it reached 10
17                if (++counter == 10) {
18                    // Stop processing further events once the limit is hit
19                    break;
20                }
21            } else {
22                // Case 3: any other (non-numeric, non-"W") event
23                // Increment the score by one
24                score++;
25            }
26        }
27
28        // Return both the final score and the "W" counter as a two-element array
29        return new int[] {score, counter};
30    }
31}
32
1class Solution {
2public:
3    vector<int> scoreValidator(vector<string>& events) {
4        int score = 0;     // Accumulated total score
5        int counter = 0;    // Counts consecutive "W" events
6
7        // Iterate over every event string in the input list
8        for (const string& event : events) {
9            // Case 1: The event represents a numeric value (its first char is a digit)
10            if (isdigit(event[0])) {
11                score += stoi(event);   // Add the parsed integer to the score
12            }
13            // Case 2: The event is a "W" marker
14            else if (event == "W") {
15                // Increment the counter; if it reaches 10, stop processing further events
16                if (++counter == 10) {
17                    break;
18                }
19            }
20            // Case 3: Any other event contributes a single point
21            else {
22                ++score;
23            }
24        }
25
26        // Return the final score together with the "W" counter
27        return {score, counter};
28    }
29};
30
1/**
2 * Processes a list of events and computes a cumulative score along with a counter.
3 *
4 * Rules for each event:
5 *  - If the event is a numeric string, its integer value is added to the score.
6 *  - If the event is 'W', the counter is incremented; processing stops once the counter reaches 10.
7 *  - For any other event, the score is incremented by 1.
8 *
9 * @param events - The list of event strings to process.
10 * @returns A tuple [score, counter] representing the final score and the counter value.
11 */
12function scoreValidator(events: string[]): number[] {
13    // Accumulated score across all processed events.
14    let score: number = 0;
15
16    // Number of 'W' events encountered so far.
17    let counter: number = 0;
18
19    // Matches strings that consist solely of one or more digits.
20    const numericPattern: RegExp = /^\d+$/;
21
22    for (const event of events) {
23        if (numericPattern.test(event)) {
24            // Numeric event: add its integer value to the score.
25            score += parseInt(event, 10);
26        } else if (event === 'W') {
27            // 'W' event: increment the counter and stop early at 10.
28            counter++;
29            if (counter === 10) {
30                break;
31            }
32        } else {
33            // Any other event: increment the score by one.
34            score++;
35        }
36    }
37
38    return [score, counter];
39}
40

Time and Space Complexity

  • Time Complexity: O(n), where n is the length of the array events. The code iterates through the events list a single time with one for loop. For each element, the operations performed—isdigit() check, comparison, and arithmetic updates to score and counter—all take constant time O(1). In the worst case (when the counter == 10 break condition is never triggered), every element is processed exactly once, yielding linear time. The early break only reduces the number of iterations and does not affect the upper bound.

  • Space Complexity: O(1). The algorithm uses only a constant amount of extra space, namely the variables score and counter. The returned list [score, counter] always contains exactly two elements regardless of the input size, so it does not contribute to the asymptotic space growth.

Common Pitfalls

Pitfall 1: Forgetting to break before processing more events when the counter reaches 10

A frequent mistake is checking the stopping condition at the wrong time, or not checking it at all after incrementing the counter. The problem clearly states that as soon as the counter reaches 10, you must stop immediately and ignore any remaining events.

If you increment warning_count but forget to break right after it hits 10, the loop will keep processing subsequent events and add extra points to score that should have been ignored.

Incorrect version:

for event in events:
    if event.isdigit():
        total_score += int(event)
    elif event == "W":
        warning_count += 1  # No break check here!
    else:
        total_score += 1
# Counter may exceed 10, and extra events get processed incorrectly

Solution: Always check if warning_count == 10: break immediately after incrementing, as the provided code does. This guarantees no further events are processed once the limit is reached.


Pitfall 2: Misusing str.isdigit() to detect numeric events

The code relies on event.isdigit() to identify numeric events. While this works for the given inputs ("0""6"), there are two subtle issues to be aware of:

  1. "WD" and "NB" are correctly excluded because they contain letters, so isdigit() returns False. This is fine.
  2. However, if the problem's input set ever expanded, isdigit() can return True for unexpected Unicode characters (e.g., superscripts like "²"), which would cause int(event) to fail or behave unexpectedly.

Solution: For maximum robustness, explicitly match against the allowed numeric strings rather than relying on isdigit():

numeric_values = {"0", "1", "2", "3", "4", "6"}

for event in events:
    if event in numeric_values:
        total_score += int(event)
    elif event == "W":
        warning_count += 1
        if warning_count == 10:
            break
    else:  # "WD" or "NB"
        total_score += 1

This makes the intent explicit and avoids edge cases with unusual characters.


Pitfall 3: Using counter >= 10 vs counter == 10 incorrectly

Since warning_count increases by exactly 1 each time and we break the moment it equals 10, it can never exceed 10. Therefore == 10 and >= 10 behave identically here.

The pitfall arises if you remove the immediate break but keep a >= 10 check elsewhere—then you might process extra events before stopping. As long as the break happens right at the increment, == 10 is correct and clear. Mixing up the stop logic (e.g., checking the condition only at the top of the loop on the next iteration) can let one extra event slip through.

Solution: Keep the increment and the boundary check tightly coupled so the loop exits at the exact moment the counter reaches the limit.

Ready to land your dream job?

Unlock your dream job with a 5-minute quiz for a personalized study roadmap!

Get My Roadmap
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Get a Personalized Study Roadmap:

In a binary min heap, the maximum element can be found in:


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More