broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0])], [('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(cross)>bs: return None
    a=math.asin(-cross/bs)
    sog=bs+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None)], [('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None)], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [45, 5, 135, 6]', [45, 5, 135, 6], None), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88])], [('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0])], [('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74])]]
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)

prompt:
Fair and foul streams give the same ETA.

Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if drift>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0])], [('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77])], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81])]]
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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    track,bs,setd,drift=x
    rel=math.radians(setd-track)
    cross=drift*math.sin(rel)
    if abs(drift*math.cos(rel))>bs: return None
    a=math.asin(-cross/bs)
    sog=bs*math.cos(a)+drift*math.cos(rel)
    if sog<=0: return None
    return [round(math.degrees(math.radians(track)+a)%360,1),round(sog,2)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81]), ('course to steer across a stream [10, 5, 100, 2]', [10, 5, 100, 2], [346.4, 4.58]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [350, 5, 80, 2]', [350, 5, 80, 2], [326.4, 4.58]), ('course to steer across a stream [200, 4, 200, 3]', [200, 4, 200, 3], [200.0, 7.0]), ('course to steer across a stream [200, 4, 20, 3]', [200, 4, 20, 3], [200.0, 1.0]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0])], [('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35]), ('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [120, 5, 300, 5.5]', [120, 5, 300, 5.5], None), ('course to steer across a stream [0, 5, 90, 0]', [0, 5, 90, 0], [0.0, 5.0]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77])], [('course to steer across a stream [45, 5, 60, 7]', [45, 5, 60, 7], [23.8, 11.42]), ('course to steer across a stream [270, 8, 315, 2.5]', [270, 8, 315, 2.5], [257.2, 9.57]), ('course to steer across a stream [5, 6, 275, 1.2]', [5, 6, 275, 1.2], [16.5, 5.88]), ('course to steer across a stream [180, 3, 90, 2.9]', [180, 3, 90, 2.9], [255.2, 0.77]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68])], [('course to steer across a stream [0, 5, 10, 7]', [0, 5, 10, 7], [345.9, 11.74]), ('course to steer across a stream [300, 7, 120, 2]', [300, 7, 120, 2], [300.0, 5.0]), ('course to steer across a stream [5, 6, 90, 1.5]', [5, 6, 90, 1.5], [350.6, 5.94]), ('course to steer across a stream [355, 6, 260, 1.5]', [355, 6, 260, 1.5], [9.4, 5.68]), ('course to steer across a stream [90, 4, 100, 4.5]', [90, 4, 100, 4.5], [78.7, 8.35]), ('course to steer across a stream [90, 6, 180, 1.5]', [90, 6, 180, 1.5], [75.5, 5.81]), ('course to steer across a stream [90, 6, 0, 1.5]', [90, 6, 0, 1.5], [104.5, 5.81])]]
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)

prompt:
A strong but fair stream is declared impossible to counter.

Input [track, boat_speed, set, drift] with degrees true (set is the direction the stream flows toward) and knots. Cross-track stream c=drift*sin(set-track); heading = track+asin(-c/boat); SOG=boat*cos(asin(-c/boat))+drift*cos(set-track). Return None when |c|>boat or SOG<=0, else [heading mod 360 rounded to 0.1, SOG rounded to 0.01].

split: open-access


prompt:
Flat high waters are reported at the start of the stand.

Input [h, dt, minr]: equally spaced heights every dt minutes. Interior extrema (plateaus collapse to their midpoint time) are candidates; series endpoints never are. A candidate of the same type as the last accepted event replaces it only if more extreme; otherwise a candidate whose height differs from the last accepted event by less than minr is ignored. Return [[type, minutes, height], ...].

split: open-access


prompt:
A spurious turning point appears at the start of the prediction window.

Input [h, dt, minr]: equally spaced heights every dt minutes. Interior extrema (plateaus collapse to their midpoint time) are candidates; series endpoints never are. A candidate of the same type as the last accepted event replaces it only if more extreme; otherwise a candidate whose height differs from the last accepted event by less than minr is ignored. Return [[type, minutes, height], ...].

split: open-access


prompt:
A genuine event whose height difference equals minr disappears.

Input [h, dt, minr]: equally spaced heights every dt minutes. Interior extrema (plateaus collapse to their midpoint time) are candidates; series endpoints never are. A candidate of the same type as the last accepted event replaces it only if more extreme; otherwise a candidate whose height differs from the last accepted event by less than minr is ignored. Return [[type, minutes, height], ...].

split: open-access


prompt:
The lower of two high waters is reported.

Input [h, dt, minr]: equally spaced heights every dt minutes. Interior extrema (plateaus collapse to their midpoint time) are candidates; series endpoints never are. A candidate of the same type as the last accepted event replaces it only if more extreme; otherwise a candidate whose height differs from the last accepted event by less than minr is ignored. Return [[type, minutes, height], ...].

split: open-access


prompt:
Even-length stands are timed half an interval early.

Input [h, dt, minr]: equally spaced heights every dt minutes. Interior extrema (plateaus collapse to their midpoint time) are candidates; series endpoints never are. A candidate of the same type as the last accepted event replaces it only if more extreme; otherwise a candidate whose height differs from the last accepted event by less than minr is ignored. Return [[type, minutes, height], ...].

split: open-access


prompt:
Windows open and close at mirrored times within the sample interval.

Input [ts, hs, req]: sample times (minutes) and heights. Return the list of [start, end] intervals where height>=req, with crossing times linearly interpolated and rounded conservatively inward (start up, end down, 1e-9 tolerance); windows that vanish after rounding are dropped. A window open at the first sample starts at ts[0]; one still open at the end closes at ts[-1].

split: open-access


prompt:
Windows open late by up to one sample interval.

Input [ts, hs, req]: sample times (minutes) and heights. Return the list of [start, end] intervals where height>=req, with crossing times linearly interpolated and rounded conservatively inward (start up, end down, 1e-9 tolerance); windows that vanish after rounding are dropped. A window open at the first sample starts at ts[0]; one still open at the end closes at ts[-1].

split: open-access


prompt:
The last opportunity of the day is missing from the plan.

Input [ts, hs, req]: sample times (minutes) and heights. Return the list of [start, end] intervals where height>=req, with crossing times linearly interpolated and rounded conservatively inward (start up, end down, 1e-9 tolerance); windows that vanish after rounding are dropped. A window open at the first sample starts at ts[0]; one still open at the end closes at ts[-1].

split: open-access


prompt:
When the tide is already high enough at the start, the first window is omitted or truncated.

Input [ts, hs, req]: sample times (minutes) and heights. Return the list of [start, end] intervals where height>=req, with crossing times linearly interpolated and rounded conservatively inward (start up, end down, 1e-9 tolerance); windows that vanish after rounding are dropped. A window open at the first sample starts at ts[0]; one still open at the end closes at ts[-1].

split: open-access


prompt:
Published windows can open before the water is deep enough.

Input [ts, hs, req]: sample times (minutes) and heights. Return the list of [start, end] intervals where height>=req, with crossing times linearly interpolated and rounded conservatively inward (start up, end down, 1e-9 tolerance); windows that vanish after rounding are dropped. A window open at the first sample starts at ts[0]; one still open at the end closes at ts[-1].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=off[frm]-off[to]
    if kind=='depth': res=val+shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7)], [('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1)], [('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1)]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=off[frm]-off[to]
    if kind=='depth': res=-(val+shift)
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7)], [('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1)], [('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1)]]
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)

prompt:
Soundings referred to a higher datum get deeper instead of shallower.

Input [kind, value, frm, to, table]: table lists [datum, offset above chart datum]; CD itself has offset 0 even if absent. Heights and drying heights are measured upward from their datum; depths downward. Converting frm->to: height=value+off[frm]-off[to], depth=value-off[frm]+off[to]. Unknown datum names return None. Result rounded to 3 decimals.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=off[to]-off[frm]
    if kind=='depth': res=val-shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3)], [('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=abs(off[frm]-off[to])
    if kind=='depth': res=val-shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3)], [('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)]]
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)

prompt:
Every conversion moves values the wrong way by the offset difference.

Input [kind, value, frm, to, table]: table lists [datum, offset above chart datum]; CD itself has offset 0 even if absent. Heights and drying heights are measured upward from their datum; depths downward. Converting frm->to: height=value+off[frm]-off[to], depth=value-off[frm]+off[to]. Unknown datum names return None. Result rounded to 3 decimals.

split: open-access


source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('LAT',0.0)
    if frm not in off or to not in off: return None
    shift=off[frm]-off[to]
    if kind=='depth': res=val-shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1)], [('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1)]]
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)

prompt:
Conversions to or from CD return None.

Input [kind, value, frm, to, table]: table lists [datum, offset above chart datum]; CD itself has offset 0 even if absent. Heights and drying heights are measured upward from their datum; depths downward. Converting frm->to: height=value+off[frm]-off[to], depth=value-off[frm]+off[to]. Unknown datum names return None. Result rounded to 3 decimals.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return round(val,3)
    shift=off[frm]-off[to]
    if kind=='depth': res=val-shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7)], [('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7)], [('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1)], [('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)]]
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)

prompt:
A typo in the datum name silently yields an unconverted value.

Input [kind, value, frm, to, table]: table lists [datum, offset above chart datum]; CD itself has offset 0 even if absent. Heights and drying heights are measured upward from their datum; depths downward. Converting frm->to: height=value+off[frm]-off[to], depth=value-off[frm]+off[to]. Unknown datum names return None. Result rounded to 3 decimals.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=off[frm]-off[to]
    if kind!='height': res=val-shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1)], [('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1)]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    kind,val,frm,to,table=x
    off=dict(table)
    off.setdefault('CD',0.0)
    if frm not in off or to not in off: return None
    shift=off[frm]-off[to]
    if kind=='depth': res=val-shift
    elif kind=='drying': res=-val+shift
    else: res=val+shift
    return round(res,3)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8)], [('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["depth", 5.0, "LAT", "MLWS", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 5.0, 'LAT', 'MLWS', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["height", 2.0, "CD", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'CD', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 2.0), ('vertical datum conversion ["height", 2.0, "ODN", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 2.0, 'ODN', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1)], [('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1), ('vertical datum conversion ["depth", 3.0, "CD", "ODN", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 3.0, 'CD', 'ODN', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], None), ('vertical datum conversion ["height", 0.0, "LAT", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 0.0, 'LAT', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -0.3), ('vertical datum conversion ["depth", 9.0, "MHWS", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 9.0, 'MHWS', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 4.1), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4)], [('vertical datum conversion ["drying", 1.4, "CD", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 1.4, 'CD', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 1.7), ('vertical datum conversion ["height", 1.0, "MSL", "LAT", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4]]]', ['height', 1.0, 'MSL', 'LAT', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4]]], 3.7), ('vertical datum conversion ["height", 3.1, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 3.1, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 0.7), ('vertical datum conversion ["depth", 12.0, "CD", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 12.0, 'CD', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 14.4), ('vertical datum conversion ["depth", 7.5, "MSL", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['depth', 7.5, 'MSL', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.1), ('vertical datum conversion ["height", 1.2, "MHWS", "CD", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['height', 1.2, 'MHWS', 'CD', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], 5.8), ('vertical datum conversion ["drying", 0.8, "MLWS", "MSL", [["LAT", -0.3], ["MLWS", 0.5], ["MSL", 2.4], ["MHWS", 4.6]]]', ['drying', 0.8, 'MLWS', 'MSL', [['LAT', -0.3], ['MLWS', 0.5], ['MSL', 2.4], ['MHWS', 4.6]]], -1.1)]]
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)

prompt:
Drying banks appear lower after conversion to a higher datum.

Input [kind, value, frm, to, table]: table lists [datum, offset above chart datum]; CD itself has offset 0 even if absent. Heights and drying heights are measured upward from their datum; depths downward. Converting frm->to: height=value+off[frm]-off[to], depth=value-off[frm]+off[to]. Unknown datum names return None. Result rounded to 3 decimals.

split: open-access


prompt:
UTC times are off by twice the zone description.

Input [local "YYYY-MM-DD HH:MM", zd, dst]: zone description zd in hours (positive west, may be fractional); UTC = zone time + zd, and when the table is on daylight time the clock is one hour ahead so UTC = local + zd - 1. Return UTC as "YYYY-MM-DD HH:MM" (24-hour).

split: open-access


prompt:
Summer tide times are two hours off in UTC.

Input [local "YYYY-MM-DD HH:MM", zd, dst]: zone description zd in hours (positive west, may be fractional); UTC = zone time + zd, and when the table is on daylight time the clock is one hour ahead so UTC = local + zd - 1. Return UTC as "YYYY-MM-DD HH:MM" (24-hour).

split: open-access


prompt:
Late evening and early morning events are filed on the wrong day.

Input [local "YYYY-MM-DD HH:MM", zd, dst]: zone description zd in hours (positive west, may be fractional); UTC = zone time + zd, and when the table is on daylight time the clock is one hour ahead so UTC = local + zd - 1. Return UTC as "YYYY-MM-DD HH:MM" (24-hour).

split: open-access


prompt:
Tables for half-hour zones are thirty minutes off.

Input [local "YYYY-MM-DD HH:MM", zd, dst]: zone description zd in hours (positive west, may be fractional); UTC = zone time + zd, and when the table is on daylight time the clock is one hour ahead so UTC = local + zd - 1. Return UTC as "YYYY-MM-DD HH:MM" (24-hour).

split: open-access


prompt:
Afternoon events are indistinguishable from morning ones.

Input [local "YYYY-MM-DD HH:MM", zd, dst]: zone description zd in hours (positive west, may be fractional); UTC = zone time + zd, and when the table is on daylight time the clock is one hour ahead so UTC = local + zd - 1. Return UTC as "YYYY-MM-DD HH:MM" (24-hour).

split: open-access


prompt:
Coefficients double and nearly every tide is clamped to 120.

Input [hw, lw_before, lw_after, z0, U]: range = hw - mean of the two flanking low waters; coefficient = floor(100*(range/2)/U + 0.5) clamped to [20,120]. Class: exceptional if coef>=110, else spring if coef>=70, neap if coef<=45, else mean. Return [coef, class]. z0 (mean level) is informational only.

split: open-access


prompt:
Grandes marees are never flagged as exceptional.

Input [hw, lw_before, lw_after, z0, U]: range = hw - mean of the two flanking low waters; coefficient = floor(100*(range/2)/U + 0.5) clamped to [20,120]. Class: exceptional if coef>=110, else spring if coef>=70, neap if coef<=45, else mean. Return [coef, class]. z0 (mean level) is informational only.

split: open-access


prompt:
Extreme ranges produce coefficients such as 131 or 12.

Input [hw, lw_before, lw_after, z0, U]: range = hw - mean of the two flanking low waters; coefficient = floor(100*(range/2)/U + 0.5) clamped to [20,120]. Class: exceptional if coef>=110, else spring if coef>=70, neap if coef<=45, else mean. Return [coef, class]. z0 (mean level) is informational only.

split: open-access


prompt:
Borderline spring tides are labelled mean.

Input [hw, lw_before, lw_after, z0, U]: range = hw - mean of the two flanking low waters; coefficient = floor(100*(range/2)/U + 0.5) clamped to [20,120]. Class: exceptional if coef>=110, else spring if coef>=70, neap if coef<=45, else mean. Return [coef, class]. z0 (mean level) is informational only.

split: open-access


prompt:
Asymmetric tides get coefficients from one side of the high water.

Input [hw, lw_before, lw_after, z0, U]: range = hw - mean of the two flanking low waters; coefficient = floor(100*(range/2)/U + 0.5) clamped to [20,120]. Class: exceptional if coef>=110, else spring if coef>=70, neap if coef<=45, else mean. Return [coef, class]. z0 (mean level) is informational only.

split: open-access


prompt:
Recorded slack water is late by half the stand.

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"], ...].

split: open-access


prompt:
Slack times are mirrored inside the sample interval.

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"], ...].

split: open-access


prompt:
A stream that eases to zero and resumes in the same direction produces two false slacks.

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"], ...].

split: open-access


prompt:
Flood-begins and ebb-begins are swapped in the tide table.

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"], ...].

split: open-access


prompt:
After the first reversal later slacks are missed or mistimed.

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"], ...].

split: open-access


prompt:
Ports with a high chart datum always use the spring curve.

Input [hrel, hw, lw, sr, nr, hours, fs, fn]: hours ascending, fs/fn spring and neap curve factors. Outside [hours[0],hours[-1]] return None. Factors are linearly interpolated in time on each curve, then blended with k=clamp((hw-lw-nr)/(sr-nr),0,1) as fn+(fs-fn)*k. Height = lw + f*(hw-lw), rounded to 3 decimals.

split: open-access


prompt:
Heights between table hours are mirrored within each hour.

Input [hrel, hw, lw, sr, nr, hours, fs, fn]: hours ascending, fs/fn spring and neap curve factors. Outside [hours[0],hours[-1]] return None. Factors are linearly interpolated in time on each curve, then blended with k=clamp((hw-lw-nr)/(sr-nr),0,1) as fn+(fs-fn)*k. Height = lw + f*(hw-lw), rounded to 3 decimals.

split: open-access


prompt:
Low water heights are reported at high water and vice versa.

Input [hrel, hw, lw, sr, nr, hours, fs, fn]: hours ascending, fs/fn spring and neap curve factors. Outside [hours[0],hours[-1]] return None. Factors are linearly interpolated in time on each curve, then blended with k=clamp((hw-lw-nr)/(sr-nr),0,1) as fn+(fs-fn)*k. Height = lw + f*(hw-lw), rounded to 3 decimals.

split: open-access


prompt:
Neap-day heights swing as far as spring tides.

Input [hrel, hw, lw, sr, nr, hours, fs, fn]: hours ascending, fs/fn spring and neap curve factors. Outside [hours[0],hours[-1]] return None. Factors are linearly interpolated in time on each curve, then blended with k=clamp((hw-lw-nr)/(sr-nr),0,1) as fn+(fs-fn)*k. Height = lw + f*(hw-lw), rounded to 3 decimals.

split: open-access


prompt:
Neap-weighted heights drift from the neap curve between table hours.

Input [hrel, hw, lw, sr, nr, hours, fs, fn]: hours ascending, fs/fn spring and neap curve factors. Outside [hours[0],hours[-1]] return None. Factors are linearly interpolated in time on each curve, then blended with k=clamp((hw-lw-nr)/(sr-nr),0,1) as fn+(fs-fn)*k. Height = lw + f*(hw-lw), rounded to 3 decimals.

split: open-access