FA-71026 / Weather index computation / Open access
Monthly heating and cooling degree days: missing-day carry forward · case 01
Months with sensor outages report too few degree days.
ROOT CAUSE
Missing days are skipped instead of reusing the previous day mean.
VERIFIED REPAIR
Substitute the previous valid daily mean.
Unsuccessful approach: Substituting the 65 degF base contributes zero degree days for the gap.
Case contract
daily entries are [tmax_F, tmin_F] with None for missing. A day with a missing value reuses the previous valid daily mean; missing days before any valid day are skipped. Round the daily mean half up to a whole degree, then HDD += 65 - m if m < 65, CDD += m - 65 if m > 65. Return [HDD, CDD].
Why this case matters
Energy billing normalisation and utility demand models use monthly HDD/CDD.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(daily):
hdd = 0
cdd = 0
prev = None
for hi, lo in daily:
if hi is None or lo is None:
if prev is None:
continue
continue
else:
mean = (hi + lo) / 2
prev = mean
m = math.floor(mean + 0.5)
if m < 65:
hdd += 65 - m
elif m > 65:
cdd += m - 65
return [hdd, cdd]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 1', [[[83, 66], [71, 50], [49, 42], [46, 43], [92, 70], [55, 54], [55, 46], [70, 55], [64, 64], [38, 36]]], [98, 26]], ['month 2', [[[86, 69], [48, 47], [63, 47], [70, 60], [63, 42], [56, 36], [59, 43], [72, 70], [74, 59], [75, 63]]], [72, 25]], ['month 3', [[[None, None], [None, 60], [65, 60], [74, 72], [93, 69], [76, 73], [58, 43], [54, 35], [74, 52], [55, 49]]], [51, 34]], ['month 4', [[[None, 60], [64, 63], [61, 54], [73, 49], [47, 38], [49, 40], [58, 46], [77, 58], [72, 54], [74, 64]]], [69, 7]], ['month 5', [[[83, 71], [69, 53], [79, 74], [80, 71], [47, 46], [83, 64], [74, 51], [52, 52], [None, None], [48, 37]]], [72, 44]], ['month 6', [[[93, 68], [80, 74], [80, 59], [71, 70], [74, 73], [59, 57], [91, 71], [60, 51], [62, 61], [74, 73]]], [19, 73]], ['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]]], [['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]], ['month 8', [[[71, 60], [75, 67], [77, 54], [84, 71], [62, 45], [None, None], [None, None], [90, 75], [None, 60], [65, 51]]], [40, 57]], ['month 9', [[[None, None], [None, None], [67, 66], [64, 51], [None, None], [None, None], [96, 73], [None, None], [75, 50], [72, 67]]], [23, 47]], ['month 10', [[[68, 47], [71, 53], [93, 68], [78, 65], [52, 47], [53, 43], [77, 72], [84, 72], [80, 71], [67, 58]]], [44, 57]], ['month 11', [[[74, 51], [None, 60], [52, 44], [82, 69], [64, 55], [None, None], [55, 53], [81, 73], [77, 63], [45, 37]]], [66, 28]], ['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]]], [['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]], ['month 15', [[[71, 61], [None, None], [None, 60], [None, 60], [None, None], [73, 67], [61, 41], [86, 74], [None, 60], [None, 60]]], [14, 55]], ['month 16', [[[None, None], [42, 35], [49, 35], [81, 65], [50, 49], [54, 44], [64, 47], [88, 67], [71, 58], [45, 37]]], [113, 21]], ['month 17', [[[59, 59], [84, 70], [83, 63], [64, 56], [77, 66], [44, 42], [84, 62], [49, 40], [36, 36], [59, 35]]], [100, 35]], ['month 18', [[[52, 38], [66, 61], [67, 54], [87, 75], [60, 47], [58, 35], [61, 40], [79, 57], [50, 35], [54, 39]]], [108, 19]], ['month 19', [[[62, 37], [93, 74], [45, 39], [56, 53], [70, 45], [94, 75], [57, 47], [95, 72], [49, 35], [71, 66]]], [91, 62]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]]], [['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 20', [[[77, 75], [58, 55], [63, 40], [76, 57], [94, 70], [60, 45], [72, 66], [None, None], [68, 51], [72, 58]]], [38, 38]], ['month 21', [[[54, 43], [73, 63], [69, 50], [76, 62], [75, 67], [49, 37], [72, 66], [55, 49], [82, 62], [58, 56]]], [64, 24]], ['month 22', [[[65, 61], [None, 60], [75, 71], [92, 75], [76, 69], [81, 75], [81, 70], [85, 65], [58, 55], [68, 59]]], [13, 69]], ['month 23', [[[46, 42], [55, 38], [73, 63], [72, 61], [62, 37], [60, 58], [55, 52], [38, 36], [82, 69], [51, 47]]], [115, 16]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 26', [[[None, 60], [None, 60], [62, 41], [85, 67], [60, 58], [65, 42], [58, 54], [60, 37], [74, 60], [84, 63]]], [55, 22]]], [['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 28', [[[69, 55], [63, 40], [86, 63], [64, 47], [79, 69], [63, 55], [80, 67], [52, 42], [51, 46], [53, 42]]], [82, 28]], ['month 29', [[[70, 54], [68, 60], [54, 39], [None, 60], [None, None], [63, 47], [69, 63], [55, 41], [None, None], [99, 74]]], [102, 23]], ['odd sums', [[[70, 59], [66, 63], [80, 51]]], [0, 1]], ['first day missing', [[[None, None], [70, 50]]], [5, 0]], ['carry forward', [[[90, 71], [None, None], [None, 50]]], [0, 48]], ['base day', [[[65, 65]]], [0, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| month 0 | [51, 43] | [68, 76] | Failed |
| month 1 | [98, 26] | [98, 26] | Passed |
| month 2 | [72, 25] | [72, 25] | Passed |
| month 3 | [51, 34] | [51, 34] | Passed |
| month 4 | [69, 7] | [69, 7] | Passed |
| month 5 | [59, 44] | [72, 44] | Failed |
| month 6 | [19, 73] | [19, 73] | Passed |
| month 7 | [73, 40] | [73, 40] | Passed |
SHA-256 / 46450073c46d62c5b0865d8e7d6611752f903a1ce3f7b80a00b6da464e38938c
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(daily):
hdd = 0
cdd = 0
prev = None
for hi, lo in daily:
if hi is None or lo is None:
if prev is None:
continue
mean = 65.0
else:
mean = (hi + lo) / 2
prev = mean
m = math.floor(mean + 0.5)
if m < 65:
hdd += 65 - m
elif m > 65:
cdd += m - 65
return [hdd, cdd]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 1', [[[83, 66], [71, 50], [49, 42], [46, 43], [92, 70], [55, 54], [55, 46], [70, 55], [64, 64], [38, 36]]], [98, 26]], ['month 2', [[[86, 69], [48, 47], [63, 47], [70, 60], [63, 42], [56, 36], [59, 43], [72, 70], [74, 59], [75, 63]]], [72, 25]], ['month 3', [[[None, None], [None, 60], [65, 60], [74, 72], [93, 69], [76, 73], [58, 43], [54, 35], [74, 52], [55, 49]]], [51, 34]], ['month 4', [[[None, 60], [64, 63], [61, 54], [73, 49], [47, 38], [49, 40], [58, 46], [77, 58], [72, 54], [74, 64]]], [69, 7]], ['month 5', [[[83, 71], [69, 53], [79, 74], [80, 71], [47, 46], [83, 64], [74, 51], [52, 52], [None, None], [48, 37]]], [72, 44]], ['month 6', [[[93, 68], [80, 74], [80, 59], [71, 70], [74, 73], [59, 57], [91, 71], [60, 51], [62, 61], [74, 73]]], [19, 73]], ['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]]], [['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]], ['month 8', [[[71, 60], [75, 67], [77, 54], [84, 71], [62, 45], [None, None], [None, None], [90, 75], [None, 60], [65, 51]]], [40, 57]], ['month 9', [[[None, None], [None, None], [67, 66], [64, 51], [None, None], [None, None], [96, 73], [None, None], [75, 50], [72, 67]]], [23, 47]], ['month 10', [[[68, 47], [71, 53], [93, 68], [78, 65], [52, 47], [53, 43], [77, 72], [84, 72], [80, 71], [67, 58]]], [44, 57]], ['month 11', [[[74, 51], [None, 60], [52, 44], [82, 69], [64, 55], [None, None], [55, 53], [81, 73], [77, 63], [45, 37]]], [66, 28]], ['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]]], [['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]], ['month 15', [[[71, 61], [None, None], [None, 60], [None, 60], [None, None], [73, 67], [61, 41], [86, 74], [None, 60], [None, 60]]], [14, 55]], ['month 16', [[[None, None], [42, 35], [49, 35], [81, 65], [50, 49], [54, 44], [64, 47], [88, 67], [71, 58], [45, 37]]], [113, 21]], ['month 17', [[[59, 59], [84, 70], [83, 63], [64, 56], [77, 66], [44, 42], [84, 62], [49, 40], [36, 36], [59, 35]]], [100, 35]], ['month 18', [[[52, 38], [66, 61], [67, 54], [87, 75], [60, 47], [58, 35], [61, 40], [79, 57], [50, 35], [54, 39]]], [108, 19]], ['month 19', [[[62, 37], [93, 74], [45, 39], [56, 53], [70, 45], [94, 75], [57, 47], [95, 72], [49, 35], [71, 66]]], [91, 62]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]]], [['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 20', [[[77, 75], [58, 55], [63, 40], [76, 57], [94, 70], [60, 45], [72, 66], [None, None], [68, 51], [72, 58]]], [38, 38]], ['month 21', [[[54, 43], [73, 63], [69, 50], [76, 62], [75, 67], [49, 37], [72, 66], [55, 49], [82, 62], [58, 56]]], [64, 24]], ['month 22', [[[65, 61], [None, 60], [75, 71], [92, 75], [76, 69], [81, 75], [81, 70], [85, 65], [58, 55], [68, 59]]], [13, 69]], ['month 23', [[[46, 42], [55, 38], [73, 63], [72, 61], [62, 37], [60, 58], [55, 52], [38, 36], [82, 69], [51, 47]]], [115, 16]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 26', [[[None, 60], [None, 60], [62, 41], [85, 67], [60, 58], [65, 42], [58, 54], [60, 37], [74, 60], [84, 63]]], [55, 22]]], [['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 28', [[[69, 55], [63, 40], [86, 63], [64, 47], [79, 69], [63, 55], [80, 67], [52, 42], [51, 46], [53, 42]]], [82, 28]], ['month 29', [[[70, 54], [68, 60], [54, 39], [None, 60], [None, None], [63, 47], [69, 63], [55, 41], [None, None], [99, 74]]], [102, 23]], ['odd sums', [[[70, 59], [66, 63], [80, 51]]], [0, 1]], ['first day missing', [[[None, None], [70, 50]]], [5, 0]], ['carry forward', [[[90, 71], [None, None], [None, 50]]], [0, 48]], ['base day', [[[65, 65]]], [0, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| month 0 | [51, 43] | [68, 76] | Failed |
| month 1 | [98, 26] | [98, 26] | Passed |
| month 2 | [72, 25] | [72, 25] | Passed |
| month 3 | [51, 34] | [51, 34] | Passed |
| month 4 | [69, 7] | [69, 7] | Passed |
| month 5 | [59, 44] | [72, 44] | Failed |
| month 6 | [19, 73] | [19, 73] | Passed |
| month 7 | [73, 40] | [73, 40] | Passed |
SHA-256 / 846e00f6662e02d393ea4112cead634fc5626bff65b986addd5dd8a1a264e5a6
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(daily):
hdd = 0
cdd = 0
prev = None
for hi, lo in daily:
if hi is None or lo is None:
if prev is None:
continue
mean = prev
else:
mean = (hi + lo) / 2
prev = mean
m = math.floor(mean + 0.5)
if m < 65:
hdd += 65 - m
elif m > 65:
cdd += m - 65
return [hdd, cdd]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 1', [[[83, 66], [71, 50], [49, 42], [46, 43], [92, 70], [55, 54], [55, 46], [70, 55], [64, 64], [38, 36]]], [98, 26]], ['month 2', [[[86, 69], [48, 47], [63, 47], [70, 60], [63, 42], [56, 36], [59, 43], [72, 70], [74, 59], [75, 63]]], [72, 25]], ['month 3', [[[None, None], [None, 60], [65, 60], [74, 72], [93, 69], [76, 73], [58, 43], [54, 35], [74, 52], [55, 49]]], [51, 34]], ['month 4', [[[None, 60], [64, 63], [61, 54], [73, 49], [47, 38], [49, 40], [58, 46], [77, 58], [72, 54], [74, 64]]], [69, 7]], ['month 5', [[[83, 71], [69, 53], [79, 74], [80, 71], [47, 46], [83, 64], [74, 51], [52, 52], [None, None], [48, 37]]], [72, 44]], ['month 6', [[[93, 68], [80, 74], [80, 59], [71, 70], [74, 73], [59, 57], [91, 71], [60, 51], [62, 61], [74, 73]]], [19, 73]], ['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]]], [['month 7', [[[78, 54], [83, 68], [57, 36], [81, 75], [47, 41], [86, 63], [81, 59], [41, 37], [67, 50], [65, 60]]], [73, 40]], ['month 8', [[[71, 60], [75, 67], [77, 54], [84, 71], [62, 45], [None, None], [None, None], [90, 75], [None, 60], [65, 51]]], [40, 57]], ['month 9', [[[None, None], [None, None], [67, 66], [64, 51], [None, None], [None, None], [96, 73], [None, None], [75, 50], [72, 67]]], [23, 47]], ['month 10', [[[68, 47], [71, 53], [93, 68], [78, 65], [52, 47], [53, 43], [77, 72], [84, 72], [80, 71], [67, 58]]], [44, 57]], ['month 11', [[[74, 51], [None, 60], [52, 44], [82, 69], [64, 55], [None, None], [55, 53], [81, 73], [77, 63], [45, 37]]], [66, 28]], ['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]]], [['month 13', [[[77, 62], [51, 47], [None, 60], [None, 60], [83, 65], [54, 43], [67, 67], [72, 47], [71, 49], [48, 47]]], [91, 16]], ['month 14', [[[47, 42], [None, 60], [60, 48], [64, 63], [50, 46], [None, None], [68, 50], [52, 48], [71, 55], [67, 48]]], [116, 0]], ['month 15', [[[71, 61], [None, None], [None, 60], [None, 60], [None, None], [73, 67], [61, 41], [86, 74], [None, 60], [None, 60]]], [14, 55]], ['month 16', [[[None, None], [42, 35], [49, 35], [81, 65], [50, 49], [54, 44], [64, 47], [88, 67], [71, 58], [45, 37]]], [113, 21]], ['month 17', [[[59, 59], [84, 70], [83, 63], [64, 56], [77, 66], [44, 42], [84, 62], [49, 40], [36, 36], [59, 35]]], [100, 35]], ['month 18', [[[52, 38], [66, 61], [67, 54], [87, 75], [60, 47], [58, 35], [61, 40], [79, 57], [50, 35], [54, 39]]], [108, 19]], ['month 19', [[[62, 37], [93, 74], [45, 39], [56, 53], [70, 45], [94, 75], [57, 47], [95, 72], [49, 35], [71, 66]]], [91, 62]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]]], [['month 0', [[[57, 57], [81, 68], [50, 45], [None, 60], [63, 43], [60, 41], [91, 67], [None, None], [92, 75], [None, 60]]], [68, 76]], ['month 20', [[[77, 75], [58, 55], [63, 40], [76, 57], [94, 70], [60, 45], [72, 66], [None, None], [68, 51], [72, 58]]], [38, 38]], ['month 21', [[[54, 43], [73, 63], [69, 50], [76, 62], [75, 67], [49, 37], [72, 66], [55, 49], [82, 62], [58, 56]]], [64, 24]], ['month 22', [[[65, 61], [None, 60], [75, 71], [92, 75], [76, 69], [81, 75], [81, 70], [85, 65], [58, 55], [68, 59]]], [13, 69]], ['month 23', [[[46, 42], [55, 38], [73, 63], [72, 61], [62, 37], [60, 58], [55, 52], [38, 36], [82, 69], [51, 47]]], [115, 16]], ['month 24', [[[67, 65], [58, 56], [None, None], [61, 57], [84, 60], [78, 71], [56, 42], [70, 64], [None, 60], [67, 66]]], [38, 24]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 26', [[[None, 60], [None, 60], [62, 41], [85, 67], [60, 58], [65, 42], [58, 54], [60, 37], [74, 60], [84, 63]]], [55, 22]]], [['month 12', [[[60, 59], [62, 55], [66, 63], [60, 56], [None, 60], [68, 45], [63, 38], [61, 55], [None, 60], [50, 50]]], [76, 0]], ['month 25', [[[61, 43], [None, None], [57, 50], [76, 73], [38, 36], [60, 43], [78, 63], [55, 35], [64, 47], [70, 59]]], [107, 16]], ['month 28', [[[69, 55], [63, 40], [86, 63], [64, 47], [79, 69], [63, 55], [80, 67], [52, 42], [51, 46], [53, 42]]], [82, 28]], ['month 29', [[[70, 54], [68, 60], [54, 39], [None, 60], [None, None], [63, 47], [69, 63], [55, 41], [None, None], [99, 74]]], [102, 23]], ['odd sums', [[[70, 59], [66, 63], [80, 51]]], [0, 1]], ['first day missing', [[[None, None], [70, 50]]], [5, 0]], ['carry forward', [[[90, 71], [None, None], [None, 50]]], [0, 48]], ['base day', [[[65, 65]]], [0, 0]]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| month 0 | [68, 76] | [68, 76] | Passed |
| month 1 | [98, 26] | [98, 26] | Passed |
| month 2 | [72, 25] | [72, 25] | Passed |
| month 3 | [51, 34] | [51, 34] | Passed |
| month 4 | [69, 7] | [69, 7] | Passed |
| month 5 | [72, 44] | [72, 44] | Passed |
| month 6 | [19, 73] | [19, 73] | Passed |
| month 7 | [73, 40] | [73, 40] | Passed |
SHA-256 / 0625748ed55fb86aee6f71ecc4250976712da516ce38e00a34a4272e76c1a087
Verification & scope
Stipulated deterministic teaching model of an operational weather index; coefficients and thresholds are fixed by the contract and no claim of standards conformance is made. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:26.053864+00:00.
Case digest / 5cfb5a3ef7ec3705893bb3a54da71d2a244f37c98721f93ef96499e01866895b