FA-69171 / Tide and marine navigation tables / Open access
Slack water from current samples: Slack is interpolated with the wrong velocity ratio · case 01
Slack times are mirrored inside the sample interval.
ROOT CAUSE
The fraction uses the later velocity in the numerator.
VERIFIED REPAIR
Use vs[prev]/(vs[prev]-vs[k]).
Unsuccessful approach: Dividing by the sum of velocities is only right for symmetric samples.
Case contract
Input [ts, vs]: sample times (minutes) and signed current (flood positive). Zero samples are skipped; a slack occurs between consecutive nonzero samples of opposite sign. With no zero samples in between, slack time is linearly interpolated; across a run of zero samples it is the midpoint of the zero run. Times round half up to minutes; the label says which stream begins. Return [[minute, "flood-begins"|"ebb-begins"], ...].
Why this case matters
Tide tables and passage plans turn published predictions into go/no-go decisions about depth, clearance and timing.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
ts,vs=x
out=[]
prev=None
for k in range(len(vs)):
if vs[k]==0: continue
if prev is not None and (vs[prev]>0)!=(vs[k]>0):
if k-prev>1:
tc=(ts[prev+1]+ts[k-1])/2
else:
tc=ts[prev]+(ts[k]-ts[prev])*vs[k]/(vs[k]-vs[prev])
out.append([math.floor(tc+0.5),'flood-begins' if vs[k]>0 else 'ebb-begins'])
prev=k
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']])], [('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], [])], [('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], [])]]
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 |
|---|---|---|---|
| slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]] | [[77, 'ebb-begins']] | [[73, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]] | [[75, 'flood-begins']] | [[75, 'flood-begins']] | Passed |
| slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]] | [] | [] | Passed |
| slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]] | [] | [] | Passed |
| slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]] | [[84, 'flood-begins'], [180, 'ebb-begins']] | [[96, 'flood-begins'], [180, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]] | [[40, 'ebb-begins']] | [[35, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]] | [[90, 'ebb-begins']] | [[90, 'ebb-begins']] | Passed |
SHA-256 / 22a905905fccb26a6ba920013fc966838553f50adf13505e9c83aec60e17e173
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
ts,vs=x
out=[]
prev=None
for k in range(len(vs)):
if vs[k]==0: continue
if prev is not None and (vs[prev]>0)!=(vs[k]>0):
if k-prev>1:
tc=(ts[prev+1]+ts[k-1])/2
else:
tc=ts[prev]+(ts[k]-ts[prev])*abs(vs[prev]/(vs[prev]+vs[k]))
out.append([math.floor(tc+0.5),'flood-begins' if vs[k]>0 else 'ebb-begins'])
prev=k
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']])], [('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], [])], [('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], [])]]
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 |
|---|---|---|---|
| slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]] | [[150, 'ebb-begins']] | [[73, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]] | [[75, 'flood-begins']] | [[75, 'flood-begins']] | Passed |
| slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]] | [] | [] | Passed |
| slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]] | [] | [] | Passed |
| slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]] | [[240, 'flood-begins'], [180, 'ebb-begins']] | [[96, 'flood-begins'], [180, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]] | [[45, 'ebb-begins']] | [[35, 'ebb-begins']] | Failed |
| slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]] | [[90, 'ebb-begins']] | [[90, 'ebb-begins']] | Passed |
SHA-256 / c9da5fcc546bc56923cd3dd19d5f725ed2b391c973d5850d8baeb664613120cd
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
ts,vs=x
out=[]
prev=None
for k in range(len(vs)):
if vs[k]==0: continue
if prev is not None and (vs[prev]>0)!=(vs[k]>0):
if k-prev>1:
tc=(ts[prev+1]+ts[k-1])/2
else:
tc=ts[prev]+(ts[k]-ts[prev])*vs[prev]/(vs[prev]-vs[k])
out.append([math.floor(tc+0.5),'flood-begins' if vs[k]>0 else 'ebb-begins'])
prev=k
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']])], [('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], [])], [('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], []), ('slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]]', [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]], []), ('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']])], [('slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]]', [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]], [[96, 'flood-begins'], [180, 'ebb-begins']]), ('slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]]', [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]], [[35, 'ebb-begins']]), ('slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]]', [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]], [[90, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]]', [[0, 30, 60, 90, 120, 150, 180], [0.9, 0.4, 0.0, -0.3, -0.2, 0.0, 0.6]], [[60, 'ebb-begins'], [150, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]]', [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]], [[73, 'ebb-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]]', [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]], [[75, 'flood-begins']]), ('slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]]', [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]], [])]]
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 |
|---|---|---|---|
| slack water from current samples [[0, 30, 60, 90, 120, 150], [1.2, 0.8, 0.3, -0.4, -1.1, -1.5]] | [[73, 'ebb-begins']] | [[73, 'ebb-begins']] | Passed |
| slack water from current samples [[0, 30, 60, 90, 120, 150], [-1.0, -0.5, 0.0, 0.0, 0.6, 1.0]] | [[75, 'flood-begins']] | [[75, 'flood-begins']] | Passed |
| slack water from current samples [[0, 30, 60, 90, 120], [1.0, 0.0, 0.7, 1.2, 0.4]] | [] | [] | Passed |
| slack water from current samples [[0, 30, 60, 90], [0.0, 0.0, 1.0, 2.0]] | [] | [] | Passed |
| slack water from current samples [[0, 60, 120, 180, 240], [-0.9, -0.3, 0.2, 0.0, -0.4]] | [[96, 'flood-begins'], [180, 'ebb-begins']] | [[96, 'flood-begins'], [180, 'ebb-begins']] | Passed |
| slack water from current samples [[0, 15, 30, 45, 60], [0.5, 0.3, 0.1, -0.2, -0.3]] | [[35, 'ebb-begins']] | [[35, 'ebb-begins']] | Passed |
| slack water from current samples [[0, 60, 120, 180], [1.0, 0.0, 0.0, -1.0]] | [[90, 'ebb-begins']] | [[90, 'ebb-begins']] | Passed |
SHA-256 / c96f8dc7bd891951f29a3d2e21bb9ed9ff5f0501ec836832fe69eefeff897f48
Verification & scope
A deterministic toy model with stipulated rules and constants; not certified hydrographic software or a substitute for official tide tables. 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:08.952231+00:00.
Case digest / 493526a034f4ebcef0b75d0893e977f62cc0800b67b1497b8005398d1c41b726