Ice Cream Forecast Check
A beach kiosk uses a small model to guess how many ice creams it will sell each day, so it knows how much stock to order. At the end of the week the owner has two lists: what the model predicted and what actually sold.
She wants one number that says how far off the model was. A miss of 40 cones means melted stock or angry customers, so big misses should count much more than small ones. Training a model means making a number like this smaller, step by step.
Your task
Write forecastError(predicted, actual). For each day, the miss is predicted[i] - actual[i]. Square every miss, then return the average of those squares.
The two lists always have the same length. If both are empty, return 0.
forecastError(predicted: float[], actual: float[]) → float Numbers are accepted within 1e-6.
Examples
predicted = [120, 80, 150] actual = [100, 90, 150]
166.66666666666666
The misses are 120 - 100 = 20, 80 - 90 = -10 and 150 - 150 = 0. Their squares are 400, 100 and 0. The average is 500 / 3 = 166.666…
predicted = [50, 70] actual = [60, 60]
100
The misses are -10 and +10. If you averaged the misses first you would get 0 and think the model was perfect. Squaring each miss first gives 100 and 100, so the answer is 100.
Constraints
- 0 ≤ predicted.length = actual.length ≤ 10,000
- -1,000,000 ≤ predicted[i], actual[i] ≤ 1,000,000
- Answers within 0.000001 of the expected value (or relatively that close) are accepted.
Start with brute force
There is no slow way here: one loop over the days is already the best you can do, because you have to look at every day at least once.
The traps are wrong formulas, not slow ones. Averaging the misses and then squaring lets misses cancel. Using the absolute value gives a different measure (mean absolute error) that does not punish big misses as much. Forgetting to divide gives a total that grows with the number of days, so a long week always looks worse than a short one.
Hints
0 of 4 shown- Hint 1
In the second example the model guessed 10 too low one day and 10 too high the next. What happens if you add the misses up before doing anything else to them?
- Hint 2
Positive and negative misses cancel out when you add them. Squaring each miss on its own makes every miss count as a cost, whatever its sign.
- Hint 3
Squaring also makes a miss of 20 cost 400 while a miss of 10 costs only 100. That is why this measure punishes big misses more.
- Hint 4
Loop over the days once. Keep a running total of
(predicted[i] - actual[i])², then divide by the number of days. Handle the empty case before you divide.
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.
How to solve it
Mean squared error is three small steps: find each miss, square it, average the squares. The order matters. Square before you add, or opposite misses cancel.
Trace predicted = [120, 80, 150], actual = [100, 90, 150]:
- Day 0: miss 20, square 400. Total 400.
- Day 1: miss -10, square 100. Total 500.
- Day 2: miss 0, square 0. Total 500.
- Divide by 3 days: 166.666…
Look at how the 20-cone miss produced 400 of the 500. Squaring makes the model care most about its worst days. When a model trains on this loss, it is pushed hardest to fix exactly those days.
function forecastError(predicted, actual) {
const n = predicted.length;
if (n === 0) return 0;
let total = 0;
for (let i = 0; i < n; i++) {
const miss = predicted[i] - actual[i];
total += miss * miss; // square each miss on its own
}
return total / n;
}def forecast_error(predicted, actual):
n = len(predicted)
if n == 0:
return 0.0
total = 0.0
for p, a in zip(predicted, actual):
miss = p - a
total += miss * miss # square each miss on its own
return total / nRun your code to see results here. Run checks the examples. Submit checks every test, including hidden edge cases.