3522. Calculate Score After Performing Instructions
Problem Description
You have two arrays of the same size n
: instructions
and values
. You need to simulate a process that follows specific rules to calculate a final score.
Starting conditions:
- Begin at index
i = 0
- Initial score is
0
Process rules:
When at index i
, check instructions[i]
:
-
If
instructions[i]
is"add"
:- Add
values[i]
to your current score - Move to the next index (
i + 1
)
- Add
-
If
instructions[i]
is"jump"
:- Jump to index
i + values[i]
(don't change the score)
- Jump to index
Termination conditions:
The process stops when either:
- You go out of bounds (index becomes less than
0
or greater than or equal ton
) - You reach an instruction that you've already executed before (you don't execute it again)
Goal: Return the final score when the process ends.
Example walkthrough:
If instructions = ["add", "jump", "add"]
and values = [2, 1, 3]
:
- Start at index 0: instruction is "add", so add 2 to score (score = 2), move to index 1
- At index 1: instruction is "jump", so jump to index 1 + 1 = 2
- At index 2: instruction is "add", so add 3 to score (score = 5), move to index 3
- Index 3 is out of bounds, so the process ends
- Return score = 5
The solution uses a visited array to track which instructions have been executed, ensuring we stop if we encounter a previously visited instruction.
Intuition
The problem asks us to follow a sequence of instructions that either modify our score or change our position in the instruction array. This is essentially a simulation problem where we need to trace through the execution path.
The key insight is recognizing that we need to track which instructions we've already visited. Why? Because the problem states that if we try to revisit an instruction, the process terminates immediately without executing that instruction again. This prevents us from getting stuck in infinite loops.
Consider what could happen without tracking visits: if we have instructions = ["jump", "jump"]
and values = [1, -1]
, we would jump from index 0 to index 1, then from index 1 back to index 0, creating an infinite loop. The visited tracking mechanism breaks this cycle.
The natural approach is to:
- Keep a boolean array
vis
to mark which instructions we've executed - Follow the instructions sequentially, updating our position based on the instruction type
- Stop when we either go out of bounds or encounter a previously visited instruction
The simulation is straightforward because we're simply following the rules as stated:
- For "add" instructions: update score and move forward by 1
- For "jump" instructions: move by the specified offset without changing score
Since we can only visit each instruction at most once (due to the termination condition), the time complexity is O(n)
where n
is the length of the arrays. Each instruction is processed at most once, making this an efficient linear solution.
Solution Approach
The implementation follows a direct simulation approach using a visited tracking mechanism.
Data Structures Used:
- A boolean array
vis
of sizen
to track which instructions have been executed - Variables
ans
to store the accumulated score andi
to track the current instruction index
Algorithm Steps:
-
Initialize the tracking structures:
- Create a boolean array
vis = [False] * n
to mark all instructions as unvisited - Set
ans = 0
for the score andi = 0
for the starting position
- Create a boolean array
-
Main simulation loop:
- Continue while two conditions are met:
- Position is within bounds:
0 <= i < n
- Current instruction hasn't been visited:
not vis[i]
- Position is within bounds:
- Continue while two conditions are met:
-
Inside each iteration:
- Mark current instruction as visited:
vis[i] = True
- Check the instruction type by examining the first character:
- If
instructions[i][0] == "a"
(checking if it starts with 'a' for "add"):- Add the value to score:
ans += values[i]
- Move to next instruction:
i += 1
- Add the value to score:
- Otherwise (it's a "jump" instruction):
- Jump to the new position:
i = i + values[i]
- Jump to the new position:
- If
- Mark current instruction as visited:
-
Termination:
- The loop naturally exits when either:
- We go out of bounds (
i < 0
ori >= n
) - We encounter a previously visited instruction (
vis[i]
isTrue
)
- We go out of bounds (
- Return the final score
ans
- The loop naturally exits when either:
Key Implementation Details:
The solution cleverly uses instructions[i][0] == "a"
to distinguish between "add" and "jump" instructions. This is more efficient than comparing the entire string.
The visited array prevents infinite loops and ensures linear time complexity. Without it, we could potentially cycle through the same instructions indefinitely.
Time Complexity: O(n)
- Each instruction can be visited at most once
Space Complexity: O(n)
- For the visited array
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's trace through a small example to illustrate the solution approach.
Input: instructions = ["add", "jump", "add", "jump", "add"]
and values = [3, 2, 1, -4, 5]
Step-by-step execution:
Initial state:
vis = [False, False, False, False, False]
(all unvisited)ans = 0
(score)i = 0
(current position)
Iteration 1:
- Position
i = 0
, check conditions:0 <= 0 < 5
✓ andvis[0] = False
✓ - Mark visited:
vis[0] = True
→vis = [True, False, False, False, False]
- Instruction is "add" (first char is 'a')
- Add to score:
ans = 0 + 3 = 3
- Move forward:
i = 0 + 1 = 1
Iteration 2:
- Position
i = 1
, check conditions:0 <= 1 < 5
✓ andvis[1] = False
✓ - Mark visited:
vis[1] = True
→vis = [True, True, False, False, False]
- Instruction is "jump" (first char is not 'a')
- Jump:
i = 1 + 2 = 3
(no score change)
Iteration 3:
- Position
i = 3
, check conditions:0 <= 3 < 5
✓ andvis[3] = False
✓ - Mark visited:
vis[3] = True
→vis = [True, True, False, True, False]
- Instruction is "jump" (first char is not 'a')
- Jump:
i = 3 + (-4) = -1
(no score change)
Termination:
- Position
i = -1
, check conditions:0 <= -1 < 5
✗ (out of bounds) - Loop exits
Final result: Return ans = 3
This example demonstrates:
- How the visited array tracks executed instructions
- The difference between "add" (updates score and moves by 1) and "jump" (changes position by value)
- Termination when going out of bounds
- Note that indices 2 and 4 were never visited because our path jumped over them
Solution Implementation
1class Solution:
2 def calculateScore(self, instructions: List[str], values: List[int]) -> int:
3 """
4 Calculate score by following instructions and accumulating values.
5
6 Args:
7 instructions: List of instruction strings starting with 'a' or other characters
8 values: List of integer values corresponding to each instruction
9
10 Returns:
11 Total accumulated score based on instructions
12 """
13 n = len(values)
14 visited = [False] * n # Track visited indices to avoid infinite loops
15 total_score = 0
16 current_index = 0
17
18 # Process instructions while within bounds and not revisiting indices
19 while 0 <= current_index < n and not visited[current_index]:
20 # Mark current position as visited
21 visited[current_index] = True
22
23 # Check instruction type
24 if instructions[current_index][0] == "a":
25 # If instruction starts with 'a', add value to score and move forward
26 total_score += values[current_index]
27 current_index += 1
28 else:
29 # Otherwise, jump by the value amount
30 current_index = current_index + values[current_index]
31
32 return total_score
33
1class Solution {
2 /**
3 * Calculates the total score by traversing through instructions array
4 * based on the given rules.
5 *
6 * @param instructions Array of instruction strings
7 * @param values Array of integer values corresponding to each instruction
8 * @return The total accumulated score
9 */
10 public long calculateScore(String[] instructions, int[] values) {
11 int arrayLength = values.length;
12
13 // Track visited indices to avoid infinite loops
14 boolean[] visited = new boolean[arrayLength];
15
16 // Initialize total score
17 long totalScore = 0;
18
19 // Start from index 0
20 int currentIndex = 0;
21
22 // Continue traversing while:
23 // 1. Current index is within bounds (not negative and less than array length)
24 // 2. Current index hasn't been visited before (to prevent cycles)
25 while (currentIndex >= 0 && currentIndex < arrayLength && !visited[currentIndex]) {
26 // Mark current index as visited
27 visited[currentIndex] = true;
28
29 // Check the first character of the instruction
30 if (instructions[currentIndex].charAt(0) == 'a') {
31 // If instruction starts with 'a', add value to score and move to next index
32 totalScore += values[currentIndex];
33 currentIndex += 1;
34 } else {
35 // Otherwise, jump by the value at current index
36 currentIndex = currentIndex + values[currentIndex];
37 }
38 }
39
40 return totalScore;
41 }
42}
43
1class Solution {
2public:
3 long long calculateScore(vector<string>& instructions, vector<int>& values) {
4 int n = values.size();
5
6 // Track visited indices to detect cycles
7 vector<bool> visited(n, false);
8
9 // Initialize score accumulator
10 long long totalScore = 0;
11
12 // Start from index 0
13 int currentIndex = 0;
14
15 // Continue traversing while:
16 // 1. Current index is within bounds (0 to n-1)
17 // 2. Current index hasn't been visited (no cycle detected)
18 while (currentIndex >= 0 && currentIndex < n && !visited[currentIndex]) {
19 // Mark current index as visited
20 visited[currentIndex] = true;
21
22 // Check instruction type
23 if (instructions[currentIndex][0] == 'a') {
24 // "add" instruction: add value to score and move to next index
25 totalScore += values[currentIndex];
26 currentIndex += 1;
27 } else {
28 // "jump" instruction: jump by the value amount
29 currentIndex += values[currentIndex];
30 }
31 }
32
33 return totalScore;
34 }
35};
36
1/**
2 * Calculates the score by traversing through instructions based on their type.
3 * @param instructions - Array of instruction strings where each starts with 'a' or other character
4 * @param values - Array of numerical values corresponding to each instruction
5 * @returns The calculated score after processing all reachable instructions
6 */
7function calculateScore(instructions: string[], values: number[]): number {
8 // Get the length of the arrays
9 const arrayLength: number = values.length;
10
11 // Track visited indices to avoid infinite loops
12 const visited: boolean[] = Array(arrayLength).fill(false);
13
14 // Initialize the accumulated score
15 let totalScore: number = 0;
16
17 // Current index pointer for traversing instructions
18 let currentIndex: number = 0;
19
20 // Continue processing while index is valid and not previously visited
21 while (currentIndex >= 0 && currentIndex < arrayLength && !visited[currentIndex]) {
22 // Mark current index as visited
23 visited[currentIndex] = true;
24
25 // Check instruction type
26 if (instructions[currentIndex][0] === 'a') {
27 // 'a' type: add value to score and move to next instruction
28 totalScore += values[currentIndex];
29 currentIndex += 1;
30 } else {
31 // Other type: jump by the value amount
32 currentIndex += values[currentIndex];
33 }
34 }
35
36 return totalScore;
37}
38
Time and Space Complexity
Time Complexity: O(n)
The algorithm uses a while loop that traverses through the array based on instructions. Each element in the array is visited at most once, as tracked by the vis
(visited) array. Once an element is visited (vis[i] = True
), it won't be processed again. The loop continues while the index i
is within bounds (0 <= i < n
) and the current element hasn't been visited (not vis[i]
). Since each element can only be visited once, the maximum number of iterations is n
, where n
is the length of the arrays.
Space Complexity: O(n)
The algorithm uses a boolean array vis
of size n
to track which elements have been visited. This auxiliary array requires O(n)
space. The remaining variables (ans
, i
, n
) use constant space O(1)
. Therefore, the overall space complexity is O(n)
, where n
is the length of the input array values
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Jump Calculation
A frequent mistake is misunderstanding how the jump works. The jump destination is i + values[i]
, not just values[i]
.
Wrong Implementation:
if instructions[current_index][0] != "a": current_index = values[current_index] # WRONG: This jumps to absolute position
Correct Implementation:
if instructions[current_index][0] != "a": current_index = current_index + values[current_index] # Correct: Relative jump
2. Forgetting to Mark Visited Before Processing
Marking the instruction as visited must happen before processing it, not after. Otherwise, you might process the same instruction twice in edge cases.
Wrong Implementation:
while 0 <= current_index < n and not visited[current_index]: if instructions[current_index][0] == "a": total_score += values[current_index] current_index += 1 else: current_index = current_index + values[current_index] visited[current_index] = True # WRONG: Might be out of bounds here
Correct Implementation:
while 0 <= current_index < n and not visited[current_index]: visited[current_index] = True # Mark as visited first # Then process the instruction
3. Handling Negative Jump Values
The problem allows negative values in the values
array, which means jumps can go backward. Not accounting for this can lead to incorrect assumptions about the flow.
Example Case:
instructions = ["jump", "add", "add"] values = [-1, 5, 3] # Starting at index 0, jumping by -1 would take us to index -1 (out of bounds)
4. String Comparison Efficiency
Using full string comparison can be inefficient and error-prone with typos.
Less Efficient:
if instructions[current_index] == "add": # Full string comparison
More Efficient and Safer:
if instructions[current_index][0] == "a": # Just check first character
5. Not Initializing Visited Array Properly
Ensure the visited array matches the size of the input arrays exactly.
Wrong:
visited = [False] * (n + 1) # Wrong size - could mask bugs
Correct:
visited = [False] * n # Exact size matching input arrays
A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".
What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!