# Exercise 3: read five chart labels and see what each one promises to a small boat. import math import re NM_PER_SQRT_M = 2.084 LABELS = ("Fl W 5s 28m 18M", "Oc W 6s 20m 12M", "Iso W 4s 15m 10M", "Fl(2) W 10s 45m 25M", "LFl W 12s 30m 16M") def parse(label): pattern = r"(?PLFl|Fl|Iso|Oc)(?:\((?P\d+)\))?\s+W\s+(?P\d+)s\s+(?P\d+)m\s+(?P\d+)M$" d = re.match(pattern, label).groupdict() return d["cls"], int(d["n"] or 1), int(d["period"]), int(d["h"]), int(d["rng"]) def geographic_range_nm(light_m, eye_m): return NM_PER_SQRT_M * (math.sqrt(light_m) + math.sqrt(eye_m)) # Part 1: the horizon range for eyes at 2, 5 and 10 m, and whether the horizon or the brightness limits it. for label in LABELS: cls, n, period, h, rng = parse(label) row = [] for eye in (2, 5, 10): geo = geographic_range_nm(h, eye) row.append(str(round(geo, 1)) + (" H" if geo < rng else " B")) print(label, "| 2 m, 5 m, 10 m eyes:", ", ".join(row), "(H = horizon limits, B = brightness limits)") # Part 2: minutes a boat at 6 knots takes to close from first sight (5 m eye) to the light. for label in LABELS: cls, n, period, h, rng = parse(label) first_sight = min(geographic_range_nm(h, 5), rng) print(label, "| first seen at", round(first_sight, 1), "nm | at 6 knots:", round(first_sight / 6 * 60), "minutes to reach it") # Part 3: chart heights are usually measured from high water, so at low water the light stands higher (assumed 4 m lower tide). for label in LABELS: cls, n, period, h, rng = parse(label) high = geographic_range_nm(h, 5) low = geographic_range_nm(h + 4, 5) print(label, "| horizon at high water", round(high, 1), "nm | at low water", round(low, 1), "nm | gain", round(low - high, 2), "nm") # Fl W 5s 28m 18M | 2 m, 5 m, 10 m eyes: 14.0 H, 15.7 H, 17.6 H (H = horizon limits, B = brightness limits) # Oc W 6s 20m 12M | 2 m, 5 m, 10 m eyes: 12.3 B, 14.0 B, 15.9 B (H = horizon limits, B = brightness limits) # Iso W 4s 15m 10M | 2 m, 5 m, 10 m eyes: 11.0 B, 12.7 B, 14.7 B (H = horizon limits, B = brightness limits) # Fl(2) W 10s 45m 25M | 2 m, 5 m, 10 m eyes: 16.9 H, 18.6 H, 20.6 H (H = horizon limits, B = brightness limits) # LFl W 12s 30m 16M | 2 m, 5 m, 10 m eyes: 14.4 H, 16.1 B, 18.0 B (H = horizon limits, B = brightness limits) # Fl W 5s 28m 18M | first seen at 15.7 nm | at 6 knots: 157 minutes to reach it # Oc W 6s 20m 12M | first seen at 12 nm | at 6 knots: 120 minutes to reach it # Iso W 4s 15m 10M | first seen at 10 nm | at 6 knots: 100 minutes to reach it # Fl(2) W 10s 45m 25M | first seen at 18.6 nm | at 6 knots: 186 minutes to reach it # LFl W 12s 30m 16M | first seen at 16 nm | at 6 knots: 160 minutes to reach it # Fl W 5s 28m 18M | horizon at high water 15.7 nm | at low water 16.4 nm | gain 0.76 nm # Oc W 6s 20m 12M | horizon at high water 14.0 nm | at low water 14.9 nm | gain 0.89 nm # Iso W 4s 15m 10M | horizon at high water 12.7 nm | at low water 13.7 nm | gain 1.01 nm # Fl(2) W 10s 45m 25M | horizon at high water 18.6 nm | at low water 19.2 nm | gain 0.61 nm # LFl W 12s 30m 16M | horizon at high water 16.1 nm | at low water 16.8 nm | gain 0.74 nm