All challenges
Medium 0 solved 0% acceptance

Q-Learning Updates

Apply the Q-learning update to a stream of experiences and watch rewards flow back to earlier states.

What you'll learn

  • Update action values from experience
  • Use discount factors and terminal states
  • Watch rewards flow back to earlier states

Problem

Q-learning learns how good each action is in each state, Q(s, a), from experience alone. After taking action a in state s, receiving reward and landing in state s':

  • target = reward, if the episode ended (done = 1)
  • target = reward + gamma × max over a' of Q(s', a'), otherwise
  • Q(s, a) ← Q(s, a) + alpha × (target - Q(s, a))

Start with every Q value at 0 and apply the transitions in order.

Implement q_learning(num_states, num_actions, transitions, alpha, gamma).

Input

num_states, num_actions: The table size.

transitions: One row [state, action, reward, next_state, done] per step.

alpha: The learning rate.

gamma: The discount factor.

Output

Return the Q table as a matrix with one row per state and one column per action.

Constraints

1 ≤ num_states, num_actions ≤ 100, 0 ≤ number of transitions ≤ 10,000

-100 ≤ reward ≤ 100, done is 0 or 1

0 < alpha ≤ 1, 0 ≤ gamma ≤ 1

Examples

Example 1
Input:
alpha = 0.5
gamma = 0.9
num_states = 2
num_actions = 2
transitions = [
    [0, 1, 0, 1, 0],
    [1, 0, 10, 0, 1]
]

Expected output:
expected = [
    [0.0, 0.0],
    [5.0, 0.0]
]
Input:
double alpha = 0.5;
double gamma = 0.9;
long long num_states = 2;
long long num_actions = 2;
std::vector<std::vector<long long>> transitions = {
    {0, 1, 0, 1, 0},
    {1, 0, 10, 0, 1}
};

Expected output:
std::vector<std::vector<double>> expected = {
    {0.0, 0.0},
    {5.0, 0.0}
};
Input:
double alpha = 0.5;
double gamma = 0.9;
long num_states = 2;
long num_actions = 2;
long[][] transitions = new long[][] {
    new long[] {0, 1, 0, 1, 0},
    new long[] {1, 0, 10, 0, 1}
};

Expected output:
double[][] expected = new double[][] {
    new double[] {0.0, 0.0},
    new double[] {5.0, 0.0}
};

Explanation

The first step finds no reward yet: target = 0 + 0.9 × max(Q[1]) = 0, so Q[0][1] stays 0. The second step ends the episode with reward 10: Q[1][0] = 0 + 0.5 × (10 - 0) = 5.

Example 2
Input:
alpha = 0.5
gamma = 0.9
num_states = 2
num_actions = 2
transitions = [
    [1, 0, 10, 0, 1],
    [0, 1, 0, 1, 0]
]

Expected output:
expected = [
    [0.0, 2.25],
    [5.0, 0.0]
]
Input:
double alpha = 0.5;
double gamma = 0.9;
long long num_states = 2;
long long num_actions = 2;
std::vector<std::vector<long long>> transitions = {
    {1, 0, 10, 0, 1},
    {0, 1, 0, 1, 0}
};

Expected output:
std::vector<std::vector<double>> expected = {
    {0.0, 2.25},
    {5.0, 0.0}
};
Input:
double alpha = 0.5;
double gamma = 0.9;
long num_states = 2;
long num_actions = 2;
long[][] transitions = new long[][] {
    new long[] {1, 0, 10, 0, 1},
    new long[] {0, 1, 0, 1, 0}
};

Expected output:
double[][] expected = new double[][] {
    new double[] {0.0, 2.25},
    new double[] {5.0, 0.0}
};

Explanation

Same steps in the other order. Q[1][0] becomes 5 first, so the step from state 0 now sees it: target = 0 + 0.9 × 5 = 4.5 and Q[0][1] = 0.5 × 4.5 = 2.25. The reward has flowed back one state.

References

This challenge is adapted for CodeUtility. Follow the statement and constraints above.

Learn from others

Community solutions

No published solutions yet. Solve this challenge to share the first one.