From 99f321f532b86fa5a2a8669a52807edff8e4be27 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 10 May 2026 05:21:14 +0000 Subject: [PATCH] ocaml: phase 5.1 mst_kruskal.ml baseline (5-node MST weight 11) Kruskal's minimum spanning tree using path-compressing union-find: edges (w, u, v): (1, 0, 1) (2, 1, 2) (3, 0, 3) (4, 2, 3) (5, 3, 4) (6, 0, 4) After sorting by weight and greedily unioning: pick (1,0,1) -> components: {0,1} {2} {3} {4} pick (2,1,2) -> {0,1,2} {3} {4} pick (3,0,3) -> {0,1,2,3} {4} skip (4,2,3) -- already connected pick (5,3,4) -> {0,1,2,3,4} skip (6,0,4) -- already connected MST weight = 1 + 2 + 3 + 5 = 11 Tests List.sort with 3-tuple destructuring lambda, compare on int, Array.init with closure, in-place array mutation in find, boolean union returning true iff merge happened. 147 baseline programs total. --- lib/ocaml/baseline/expected.json | 1 + lib/ocaml/baseline/mst_kruskal.ml | 32 +++++++++++++++++++++++++++++++ plans/ocaml-on-sx.md | 9 +++++++++ 3 files changed, 42 insertions(+) create mode 100644 lib/ocaml/baseline/mst_kruskal.ml diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index 269c63b2..675c2dd7 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -89,6 +89,7 @@ "levenshtein.ml": 11, "memo_fib.ml": 75025, "mortgage.ml": 1073, + "mst_kruskal.ml": 11, "merge_intervals.ml": 12, "merge_sort.ml": 44, "merge_two.ml": 441, diff --git a/lib/ocaml/baseline/mst_kruskal.ml b/lib/ocaml/baseline/mst_kruskal.ml new file mode 100644 index 00000000..85f8656e --- /dev/null +++ b/lib/ocaml/baseline/mst_kruskal.ml @@ -0,0 +1,32 @@ +let edges = [ + (1, 0, 1); (2, 1, 2); (3, 0, 3); (4, 2, 3); (5, 3, 4); (6, 0, 4) +] + +let make_uf n = Array.init n (fun i -> i) + +let rec find p x = + if p.(x) = x then x + else begin + let r = find p p.(x) in + p.(x) <- r; + r + end + +let union p x y = + let rx = find p x in + let ry = find p y in + if rx <> ry then begin p.(rx) <- ry; true end + else false + +let mst_weight n es = + let sorted = List.sort (fun (w1, _, _) (w2, _, _) -> compare w1 w2) es in + let p = make_uf n in + let total = ref 0 in + List.iter (fun (w, u, v) -> + if union p u v then total := !total + w + ) sorted; + !total + +;; + +mst_weight 5 edges diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 4e42583d..b2a64fea 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,15 @@ _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-10 Phase 5.1 — mst_kruskal.ml baseline (Kruskal MST on + 5-node, 6-edge graph → MST weight 11). Sort edges by weight, + greedily add edges whose endpoints are in different components + using union-find with path compression. Edges (w,u,v) sorted: + (1,0,1) ✓ (2,1,2) ✓ (3,0,3) ✓ (4,2,3) ✗ already connected, + (5,3,4) ✓ (6,0,4) ✗. Picked weight: 1+2+3+5 = 11. Tests + List.sort with 3-tuple destructuring lambda, Array.init, in-place + array mutation (find compression), boolean-returning union. + 147 baseline programs total. - 2026-05-10 Phase 5.1 — trie.ml baseline (prefix tree, 6 of 9 word lookups match). Mutable record `{ terminal; children }` with `children : (char * trie) list`; insert recurses down character