Storyteller Word Odds

MediumprobabilityAlso known as Softmax with Temperature

A text adventure game writes its narration with a small language model. At each step the model gives every candidate next word a raw score, and the game turns those scores into probabilities to pick from. A "creativity" slider lets players choose between safe, predictable narration and wild surprises.

The slider is the temperature. Divide every score by it, then turn the results into probabilities with softmax. A low temperature sharpens the odds toward the top word. A high temperature flattens them so unlikely words get a real chance. The temperature setting in chat assistants works this way.

Your task

Write wordOdds(scores, temperature). Let zᵢ = scores[i] / temperature. Return the list of probabilities pᵢ = e^zᵢ / (e^z₀ + e^z₁ + …), in the same order as scores.

Scores can be large, so your answer must not overflow. The probabilities must add up to 1.

wordOdds(scores: float[], temperature: float) → float[] Numbers are accepted within 1e-6.

Examples

Example 1
Input
scores = [2, 1, 0]
temperature = 1
Output
[0.6652409557748218, 0.24472847105479764, 0.09003057317038046]
Why

e² ≈ 7.389, e¹ ≈ 2.718, e⁰ = 1. Their sum is about 11.107, so the odds are about 0.665, 0.245 and 0.090.

Example 2
Input
scores = [2, 1, 0]
temperature = 0.5
Output
[0.8668133321973349, 0.11731042782619838, 0.015876239976466765]
Why

Dividing by 0.5 doubles the scores to 4, 2, 0. The gaps are now bigger, so the top word takes more of the probability: about 0.867, 0.117, 0.016. Lower temperature, safer choice.

Example 3
Input
scores = [1000, 998]
temperature = 1
Output
[0.8807970779778823, 0.11920292202211755]
Why

e^1000 is far too big for a floating-point number, so typing the formula in directly breaks. The answer is still well defined: the odds come out about 0.881 and 0.119, exactly the same as for scores [2, 0]. Only the gap between the scores matters.

Constraints

  • 1 ≤ scores.length ≤ 10,000
  • -10,000 ≤ scores[i] ≤ 10,000
  • 0.01 ≤ temperature ≤ 100
  • Answers within 0.000001 of the expected values are accepted.
Start with brute force

The textbook formula is direct: e^z for each score, add them, divide. It is already O(n), so speed is not the issue. Correctness is.

With a score of 1000, e^1000 overflows: JavaScript gives Infinity and you end up with Infinity / Infinity = NaN; Python raises an OverflowError. A low temperature makes this worse, because dividing by 0.01 multiplies every score by 100. The fix costs one extra pass to find the maximum.

Hints

0 of 4 shown

Walkthrough and solution

Unlocks when you pass every test. Stuck for a while? Looking is fine too, as long as you then close it and write the code yourself.

Ctrl+Enter runs

Run your code to see results here. Run checks the examples. Submit checks every test, including hidden edge cases.

Write code