diff --git a/lib/ocaml/baseline/balance.ml b/lib/ocaml/baseline/balance.ml new file mode 100644 index 00000000..5afcafa7 --- /dev/null +++ b/lib/ocaml/baseline/balance.ml @@ -0,0 +1,25 @@ +let is_balanced s = + let stack = Stack.create () in + let n = String.length s in + let ok = ref true in + let i = ref 0 in + while !i < n && !ok do + let c = s.[!i] in + (if c = '(' || c = '[' || c = '{' then Stack.push c stack + else if c = ')' then + (if Stack.is_empty stack || Stack.pop stack <> '(' then ok := false) + else if c = ']' then + (if Stack.is_empty stack || Stack.pop stack <> '[' then ok := false) + else if c = '}' then + (if Stack.is_empty stack || Stack.pop stack <> '{' then ok := false)); + i := !i + 1 + done; + !ok && Stack.is_empty stack + +;; + +(if is_balanced "({[abc]d}e)" then 1 else 0) + +(if is_balanced "(a]" then 1 else 0) + +(if is_balanced "{[}]" then 1 else 0) + +(if is_balanced "(())" then 1 else 0) + +(if is_balanced "" then 1 else 0) diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index 7a081af7..47733ffd 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -1,6 +1,7 @@ { "anagrams.ml": 3, "bag.ml": 3, + "balance.ml": 3, "bfs.ml": 6, "btree.ml": 39, "brainfuck.ml": 75, diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 3b0ad6db..262543f8 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,13 @@ _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-09 Phase 5.1 — balance.ml baseline (paren/bracket/brace + balance using Stack). is_balanced walks a string; on opener push, + on closer check stack non-empty + top matches expected opener (else + fail). Returns ok && is_empty stack at end. 5 test cases: + "({[abc]d}e)" ✓, "(a]" ✗, "{[}]" ✗ (mismatched closers), "(())" ✓, + "" ✓ → 3 balanced. Exercises Stack.create / push / pop / is_empty / + s.[!i] / while + bool ref short-circuit. 31 baseline programs total. - 2026-05-09 Phase 5.1 — safe_div.ml baseline + Result.equal / compare / iter_error (+3 tests, 592 total). safe_div divides only if divisor non-zero, returns `Error "..."` otherwise. sum_safe folds