diff --git a/lib/ocaml/baseline/convex_hull.ml b/lib/ocaml/baseline/convex_hull.ml new file mode 100644 index 00000000..575c0387 --- /dev/null +++ b/lib/ocaml/baseline/convex_hull.ml @@ -0,0 +1,43 @@ +let cross ox oy ax ay bx by = + (ax - ox) * (by - oy) - (ay - oy) * (bx - ox) + +let hull_size pts = + let n = List.length pts in + if n < 3 then n + else begin + let sorted = List.sort (fun (a, b) (c, d) -> + if a <> c then compare a c else compare b d) pts in + let arr = Array.of_list sorted in + let h = Array.make (2 * n) (0, 0) in + let k = ref 0 in + for i = 0 to n - 1 do + let (xi, yi) = arr.(i) in + let cont = ref true in + while !cont && !k >= 2 do + let (ox, oy) = h.(!k - 2) in + let (ax, ay) = h.(!k - 1) in + if cross ox oy ax ay xi yi <= 0 then k := !k - 1 + else cont := false + done; + h.(!k) <- (xi, yi); + k := !k + 1 + done; + let lo = !k + 1 in + for i = n - 2 downto 0 do + let (xi, yi) = arr.(i) in + let cont = ref true in + while !cont && !k >= lo do + let (ox, oy) = h.(!k - 2) in + let (ax, ay) = h.(!k - 1) in + if cross ox oy ax ay xi yi <= 0 then k := !k - 1 + else cont := false + done; + h.(!k) <- (xi, yi); + k := !k + 1 + done; + !k - 1 + end + +;; + +hull_size [(0, 0); (1, 1); (2, 0); (2, 2); (0, 2); (1, 0); (3, 3); (5, 1)] diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index d06b991b..8f4df2a9 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -25,6 +25,7 @@ "calc.ml": 13, "catalan.ml": 42, "closures.ml": 315, + "convex_hull.ml": 5, "coin_change.ml": 6, "coin_min.ml": 6, "count_change.ml": 406, diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 798a952a..292124dc 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,17 @@ _Newest first._ binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree * 'a tree`) with insert + in-order traversal. Tests parametric ADT, recursive match, List.append, List.fold_left. +- 2026-05-11 Phase 5.1 — convex_hull.ml baseline (Andrew's monotone + chain over 8 points → 5-vertex convex hull). Sorts points + lexicographically, then builds lower hull left-to-right and upper + hull right-to-left, popping back when the cross product turns the + wrong way. Points: (0,0), (1,1), (2,0), (2,2), (0,2), (1,0), + (3,3), (5,1). Hull = (0,0) → (2,0) → (5,1) → (3,3) → (0,2) = 5 + vertices ((2,0) lies on lower edge, included by the ≤ test). + Tests List.sort with a 2-tuple comparator using nested pair + destructure, repeated `let (x, y) = arr.(i) in` array tuple + destructure across both passes, while + cont-flag pattern instead + of break. 170 baseline programs total. - 2026-05-10 Phase 5.1 — next_greater.ml baseline (monotonic stack for next-greater-element over [4;5;2;25;7;8;1;30;12], sum of successors = 153). Right-to-left scan with a stack that pops