FA-68861 / Tide and marine navigation tables / Open access
Rule of twelfths: Clock hours are used instead of tide hours · case 01
Predictions are only right when the rise lasts exactly six hours.
ROOT CAUSE
Elapsed clock hours are used as tide-hour positions, ignoring the actual duration between turning points.
VERIFIED REPAIR
Scale elapsed time by 6/(t2-t1).
Unsuccessful approach: Dividing by the duration and multiplying by six in the wrong order still ignores long or short tides.
Case contract
Input [t1,h1,t2,h2,t] in hours/metres for consecutive turning points t1<t2 (rise or fall). The interval is split into six equal tide hours with cumulative twelfths 0,1,3,6,9,11,12 and linear interpolation inside a tide hour. Return height rounded to 4 decimals, or None when t2<=t1 or t lies outside [t1,t2].
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):
t1,h1,t2,h2,t=x
if t2<=t1: return None
if t<t1 or t>t2: return None
u=(t-t1)
k=min(int(u),5)
cum=[0,1,3,6,9,11,12]
c=cum[k]+(cum[k+1]-cum[k])*(u-k)
return round(h1+(h2-h1)*c/12,4)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [0, 0.5, 6, 4.1, 0]', [0, 0.5, 6, 4.1, 0], 0.5), ('rule of twelfths [0, 0.5, 6, 4.1, 1]', [0, 0.5, 6, 4.1, 1], 0.8), ('rule of twelfths [0, 0.5, 6, 4.1, 1.5]', [0, 0.5, 6, 4.1, 1.5], 1.1), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [2, 5.2, 8.5, 0.8, 9]', [2, 5.2, 8.5, 0.8, 9], None), ('rule of twelfths [1, 1.0, 7, 1.0, 3]', [1, 1.0, 7, 1.0, 3], 1.0), ('rule of twelfths [5, 1, 5, 3, 5]', [5, 1, 5, 3, 5], None)]]
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 |
|---|---|---|---|
| rule of twelfths [2, 5.2, 8.5, 0.8, 3.1] | 4.76 | 4.8221 | Failed |
| rule of twelfths [0, 0.5, 6, 4.1, 0] | 0.5 | 0.5 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1] | 0.8 | 0.8 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1.5] | 1.1 | 1.1 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 2] | 1.4 | 1.4 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 3] | 2.3 | 2.3 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 4.5] | 3.5 | 3.5 | Passed |
SHA-256 / 94b787330b1e73289adc4a3e0c2e291c277ec1006b95f5eba2c42db88ba69463
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
t1,h1,t2,h2,t=x
if t2<=t1: return None
if t<t1 or t>t2: return None
u=(t-t1)/6*(t2-t1)
k=min(int(u),5)
cum=[0,1,3,6,9,11,12]
c=cum[k]+(cum[k+1]-cum[k])*(u-k)
return round(h1+(h2-h1)*c/12,4)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [0, 0.5, 6, 4.1, 0]', [0, 0.5, 6, 4.1, 0], 0.5), ('rule of twelfths [0, 0.5, 6, 4.1, 1]', [0, 0.5, 6, 4.1, 1], 0.8), ('rule of twelfths [0, 0.5, 6, 4.1, 1.5]', [0, 0.5, 6, 4.1, 1.5], 1.1), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [2, 5.2, 8.5, 0.8, 9]', [2, 5.2, 8.5, 0.8, 9], None), ('rule of twelfths [1, 1.0, 7, 1.0, 3]', [1, 1.0, 7, 1.0, 3], 1.0), ('rule of twelfths [5, 1, 5, 3, 5]', [5, 1, 5, 3, 5], None)]]
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 |
|---|---|---|---|
| rule of twelfths [2, 5.2, 8.5, 0.8, 3.1] | 4.6928 | 4.8221 | Failed |
| rule of twelfths [0, 0.5, 6, 4.1, 0] | 0.5 | 0.5 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1] | 0.8 | 0.8 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1.5] | 1.1 | 1.1 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 2] | 1.4 | 1.4 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 3] | 2.3 | 2.3 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 4.5] | 3.5 | 3.5 | Passed |
SHA-256 / a00a933806475288762350aedc89bc8ea7c5b9f7062eba353982c7e112d0d7e1
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
t1,h1,t2,h2,t=x
if t2<=t1: return None
if t<t1 or t>t2: return None
u=(t-t1)*6/(t2-t1)
k=min(int(u),5)
cum=[0,1,3,6,9,11,12]
c=cum[k]+(cum[k+1]-cum[k])*(u-k)
return round(h1+(h2-h1)*c/12,4)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [0, 0.5, 6, 4.1, 0]', [0, 0.5, 6, 4.1, 0], 0.5), ('rule of twelfths [0, 0.5, 6, 4.1, 1]', [0, 0.5, 6, 4.1, 1], 0.8), ('rule of twelfths [0, 0.5, 6, 4.1, 1.5]', [0, 0.5, 6, 4.1, 1.5], 1.1), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [0, 0.5, 6, 4.1, 2]', [0, 0.5, 6, 4.1, 2], 1.4), ('rule of twelfths [0, 0.5, 6, 4.1, 3]', [0, 0.5, 6, 4.1, 3], 2.3), ('rule of twelfths [0, 0.5, 6, 4.1, 4.5]', [0, 0.5, 6, 4.1, 4.5], 3.5), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [0, 0.5, 6, 4.1, 5]', [0, 0.5, 6, 4.1, 5], 3.8), ('rule of twelfths [0, 0.5, 6, 4.1, 6]', [0, 0.5, 6, 4.1, 6], 4.1), ('rule of twelfths [0, 0.5, 6, 4.1, 6.5]', [0, 0.5, 6, 4.1, 6.5], None), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [0, 0.5, 6, 4.1, 7.25]', [0, 0.5, 6, 4.1, 7.25], None), ('rule of twelfths [2, 5.2, 8.5, 0.8, 2]', [2, 5.2, 8.5, 0.8, 2], 5.2), ('rule of twelfths [2, 5.2, 8.5, 0.8, 3.1]', [2, 5.2, 8.5, 0.8, 3.1], 4.8221), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8)], [('rule of twelfths [2, 5.2, 8.5, 0.8, 8.5]', [2, 5.2, 8.5, 0.8, 8.5], 0.8), ('rule of twelfths [2, 5.2, 8.5, 0.8, 4]', [2, 5.2, 8.5, 0.8, 4], 4.2128), ('rule of twelfths [2, 5.2, 8.5, 0.8, 5.25]', [2, 5.2, 8.5, 0.8, 5.25], 3.0), ('rule of twelfths [2, 5.2, 8.5, 0.8, 7]', [2, 5.2, 8.5, 0.8, 7], 1.4487), ('rule of twelfths [2, 5.2, 8.5, 0.8, 9]', [2, 5.2, 8.5, 0.8, 9], None), ('rule of twelfths [1, 1.0, 7, 1.0, 3]', [1, 1.0, 7, 1.0, 3], 1.0), ('rule of twelfths [5, 1, 5, 3, 5]', [5, 1, 5, 3, 5], None)]]
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 |
|---|---|---|---|
| rule of twelfths [2, 5.2, 8.5, 0.8, 3.1] | 4.8221 | 4.8221 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 0] | 0.5 | 0.5 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1] | 0.8 | 0.8 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 1.5] | 1.1 | 1.1 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 2] | 1.4 | 1.4 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 3] | 2.3 | 2.3 | Passed |
| rule of twelfths [0, 0.5, 6, 4.1, 4.5] | 3.5 | 3.5 | Passed |
SHA-256 / a9f6cb6c4eeb20496ef8999eff74101e331d24e1279e06b4711c00b02fbf7a4d
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:06.134284+00:00.
Case digest / 82d80f67fa93fd7a359d5d00cb9696b65e1437a48f8963ee59950a0611f87071