20. Optimal Score Difference in a Token-Picking Game
ai-labs-coding.) Confirmed: a first-hand account from a former DeepMind Research Engineer (Aleksa Gordić, "How I Got a Job at DeepMind as a Research Engineer," Medium) describes explicitly preparing dynamic programming, among other classic algorithm chapters, for DeepMind's standard FAANG-style coding round.Problem
DeepMind's game-playing research group sanity-checks new self-play agents against a minimal reference game before scaling up to something the size of Go or an RTS. One such reference game: two players alternate turns picking a token from either end of a row of point-valued tokens (never from the middle), each trying to maximize their own total score, and both play perfectly.
Given the row of token values, return player 1's total score minus player 2's total score under optimal play from both sides. This is the same terminal-value computation a value function gets checked against on a toy game before it's trusted on a harder one.
Source: src/20_token_game_optimal_value.py
def max_score_difference(tokens: list[int]) -> int:
...
Examples:
>>> max_score_difference([1, 5, 2])
-2
>>> max_score_difference([1, 5, 233, 7])
222
Step-by-Step Approach
- Notice that tracking "whose turn is it" explicitly doubles the state space for no benefit — instead define dp[i][j] as the best score difference (current player minus opponent) achievable from the subarray tokens[i..j], regardless of which physical player that is.
- Base case: a subarray of one token, dp[i][i] = tokens[i] — the current player takes it and there is nothing left for the opponent.
- Recurrence: the current player either takes tokens[i] (leaving tokens[i+1..j] to the opponent) or takes tokens[j] (leaving tokens[i..j-1]). Whichever token they take, the opponent then plays optimally on the remainder, so subtract the opponent's best achievable diff on that remainder.
- dp[i][j] = max(tokens[i] - dp[i+1][j], tokens[j] - dp[i][j-1]).
- Fill the table by increasing subarray length, since dp[i][j] depends on two strictly shorter subarrays.
- The answer is dp[0][n-1]: a positive value means player 1 wins by that margin, negative means player 2 wins, zero is a tie.
- Handle the empty-array edge case directly (difference 0, no turns to take).
The key insight is the "relative score" reformulation: by always asking "how much better does the current mover do than whoever moves after them," you avoid tracking two separate running scores and turn parity, and the recurrence becomes symmetric regardless of which player is actually moving.
Reference solution
def max_score_difference(tokens: list[int]) -> int:
n = len(tokens)
if n == 0:
return 0
# dp[i][j] = best score difference (current player minus opponent) achievable
# over the remaining subarray tokens[i..j], for whichever player is to move there
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = tokens[i] # one token left: take it
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
# take the left token, or the right token; either way the opponent then
# plays optimally on what's left, so subtract their best achievable diff
take_left = tokens[i] - dp[i + 1][j]
take_right = tokens[j] - dp[i][j - 1]
dp[i][j] = max(take_left, take_right)
return dp[0][n - 1]
Key Functions & Tricks
dp[i][j] = max(tokens[i] - dp[i+1][j], tokens[j] - dp[i][j-1])— relative-score recurrence, avoids tracking turn parity- Length-increasing fill order — dp[i][j] always depends only on strictly shorter subarrays, so this order guarantees dependencies are ready
- Diagonal base case
dp[i][i] = tokens[i]— the one-token subgame has an obvious optimal move - Sign of the final
dp[0][n-1]— directly answers "does the first mover win," not just "by how much" - O(n²) time / O(n²) space, reducible to O(n) space with a rolling diagonal since each length only reads the previous length's row
How to Recognize This Pattern
The signal to watch for: "two players alternate optimal moves over a shared, shrinking resource, and you need the final score/outcome under perfect play" — that's a game-theory interval DP, and the trick is almost always to reformulate the state as a score difference relative to the current mover rather than tracking each player's running total and whose turn it is. Common variations include removing from the middle as well as the ends (not solvable with this exact interval DP), a game where taking more than one token per turn is allowed, or games scored by parity/count instead of value sum. A common pitfall is writing the recurrence as if the current player is always "player 1," which silently breaks the moment you try to interpret dp[i][j] for the player-2-to-move case — the relative-difference framing sidesteps that trap entirely.