FAILURE MAP
← Case archive

FA-69306 / Tide and marine navigation tables / Open access

Deviation card interpolation: Unsorted cards are interpolated in entry order · case 01

Cards written clockwise from another heading give wrong deviations.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The card is used as given instead of sorted by heading.

VERIFIED REPAIR

Sort card entries by heading.

Unsuccessful approach: Sorting by deviation value scrambles the heading order.

Case contract

Input [heading, card]: card lists [compass heading, deviation] pairs (east positive) in any order. Headings wrap modulo 360; deviation is linearly interpolated between neighbouring card headings, including across the 360/0 seam. Return deviation rounded to 2 decimals.

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):
    hdg,card=x
    pts=list(card)
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pts.append([first+360,pts[0][1]])
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67)], [('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0)], [('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83)], [('deviation card interpolation [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 1.33), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94)], [('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61)]]
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 fixtureActualExpectedOutcome
deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]1.692.67Failed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.02.0Passed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.672.67Passed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.01.0Passed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]0.440.44Passed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.671.67Passed

SHA-256 / be8c7cb8626907e777c5eb910d513f35abe1b31909dd7dae2b597448486337ea

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    hdg,card=x
    pts=sorted(card,key=lambda p:p[1])
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pts.append([first+360,pts[0][1]])
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67)], [('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0)], [('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83)], [('deviation card interpolation [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 1.33), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94)], [('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61)]]
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 fixtureActualExpectedOutcome
deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]-1.422.67Failed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-0.642.0Failed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-0.92.67Failed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-1.821.0Failed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-1.950.44Failed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-0.241.67Failed

SHA-256 / 2e2514d32b497f247d052ccda6a6134811d1fe33618cb6993dca1eba92e7c958

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    hdg,card=x
    pts=sorted(card)
    first=pts[0][0]
    t=hdg%360
    if t<first: t+=360
    pts.append([first+360,pts[0][1]])
    for k in range(len(pts)-1):
        h0,d0=pts[k]; h1,d1=pts[k+1]
        if h0<=t<h1:
            return round(d0+(d1-d0)*(t-h0)/(h1-h0),2)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67)], [('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61), ('deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.67), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], -2.56), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0)], [('deviation card interpolation [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [30, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 0.33), ('deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.0), ('deviation card interpolation [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [359, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.99), ('deviation card interpolation [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [360, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.0), ('deviation card interpolation [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [-30, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83)], [('deviation card interpolation [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]]', [200, [[90, 1.0], [0, 0.0], [270, -1.0], [180, 2.0]]], 1.33), ('deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 0.44), ('deviation card interpolation [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [725, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 2.17), ('deviation card interpolation [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [5, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.83), ('deviation card interpolation [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [15, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.0), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94)], [('deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], 2.67), ('deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]', [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]], 1.67), ('deviation card interpolation [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [50, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 1.88), ('deviation card interpolation [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [150, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.94), ('deviation card interpolation [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [300, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], -0.25), ('deviation card interpolation [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]]', [350, [[15, 1.0], [75, 2.5], [120, 0.0], [200, -2.5], [285, -0.5]]], 0.58), ('deviation card interpolation [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]', [250, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]], -0.61)]]
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 fixtureActualExpectedOutcome
deviation card interpolation [60, [[315, 1.5], [270, 0.5], [225, -2.0], [180, -3.0], [135, -1.5], [90, 1.0], [45, 3.5], [0, 2.0]]]2.672.67Passed
deviation card interpolation [0, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.02.0Passed
deviation card interpolation [20, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]2.672.67Passed
deviation card interpolation [90, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.01.0Passed
deviation card interpolation [100, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]0.440.44Passed
deviation card interpolation [200, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]-2.56-2.56Passed
deviation card interpolation [330, [[0, 2.0], [45, 3.5], [90, 1.0], [135, -1.5], [180, -3.0], [225, -2.0], [270, 0.5], [315, 1.5]]]1.671.67Passed

SHA-256 / 9e6a157e595fc743e2aece319442e9d7960cc43c54d0b8397a26337e77ae5b98

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:10.185928+00:00.

Case digest / 8c3f473f929fdb481b1ef2e05500c79c2cb95d7f0f413bb3e961bab5d021ac6f