From ddd1e40d007c1063508125d3f49eee3ef673b3c2 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 9 May 2026 06:15:03 +0000 Subject: [PATCH] ocaml: phase 5.1 bag.ml baseline + String.equal/compare/cat/empty (+3 tests, 579 total) bag.ml: split a sentence on spaces, count each word in a Hashtbl, return the maximum count via Hashtbl.fold. count_words 'the quick brown fox jumps over the lazy dog the fox' -> Hashtbl with 'the' = 3 as the max -> 3 Exercises String.split_on_char + Hashtbl.find_opt/replace + Hashtbl.fold (k v acc -> ...). Together with frequency.ml from iter 84 we now have two Hashtbl-counting baselines exercising slightly different idioms. 29 baseline programs total. String additions: equal a b = a = b compare a b = -1 / 0 / 1 via host < / > cat a b = a ^ b empty = '' (constant) --- lib/ocaml/baseline/bag.ml | 18 ++++++++++++++++++ lib/ocaml/baseline/expected.json | 1 + lib/ocaml/runtime.sx | 5 +++++ lib/ocaml/test.sh | 13 +++++++++++++ plans/ocaml-on-sx.md | 8 ++++++++ 5 files changed, 45 insertions(+) create mode 100644 lib/ocaml/baseline/bag.ml diff --git a/lib/ocaml/baseline/bag.ml b/lib/ocaml/baseline/bag.ml new file mode 100644 index 00000000..661c3523 --- /dev/null +++ b/lib/ocaml/baseline/bag.ml @@ -0,0 +1,18 @@ +let count_words text = + let words = String.split_on_char ' ' text in + let counts = Hashtbl.create 8 in + List.iter (fun w -> + let n = match Hashtbl.find_opt counts w with + | Some n -> n + 1 + | None -> 1 + in + Hashtbl.replace counts w n + ) words; + counts + +let max_count counts = + Hashtbl.fold (fun _ v acc -> if v > acc then v else acc) counts 0 + +;; + +max_count (count_words "the quick brown fox jumps over the lazy dog the fox") diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index b2697a83..b38d6a77 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -1,5 +1,6 @@ { "anagrams.ml": 3, + "bag.ml": 3, "bfs.ml": 6, "btree.ml": 39, "brainfuck.ml": 75, diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index c5eb84d0..5f21e4f1 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -447,6 +447,11 @@ | h :: t -> aux t (acc ^ h) in aux xs \"\" + let equal a b = a = b + let compare a b = + if a < b then -1 else if a > b then 1 else 0 + let cat a b = a ^ b + let empty = \"\" end ;; module Bytes = struct diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index 58868059..9d5d1e24 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -1440,6 +1440,14 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 5193) (eval "(ocaml-run \"Seq.fold_left (+) 0 (Seq.unfold (fun n -> if n > 4 then None else Some (n, n + 1)) 1)\")") +;; ── String.equal / compare / cat ───────────────────────────── +(epoch 5200) +(eval "(ocaml-run \"String.equal \\\"abc\\\" \\\"abc\\\"\")") +(epoch 5201) +(eval "(ocaml-run \"String.compare \\\"banana\\\" \\\"apple\\\"\")") +(epoch 5202) +(eval "(ocaml-run \"String.cat \\\"hello \\\" \\\"world\\\"\")") + EPOCHS OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -2290,6 +2298,11 @@ check 5191 "Seq filter evens" '5' check 5192 "Seq init 5 i*2" '20' check 5193 "Seq unfold 1..4 sum" '10' +# ── String.equal / compare / cat ──────────────────────────────── +check 5200 "String.equal abc abc" 'true' +check 5201 "String.compare banana apple" '1' +check 5202 "String.cat hello world" '"hello world"' + TOTAL=$((PASS + FAIL)) if [ $FAIL -eq 0 ]; then echo "ok $PASS/$TOTAL OCaml-on-SX tests passed" diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 301ede2f..cd07e8ac 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -407,6 +407,14 @@ _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 — bag.ml baseline + String.equal/compare/cat/ + empty (+3 tests, 579 total). bag.ml: split a sentence on spaces, + count word frequency in a Hashtbl, return the maximum count. + Sentence "the quick brown fox jumps over the lazy dog the fox" has + "the"×3 as the most frequent → 3. Exercises String.split_on_char + + Hashtbl.find_opt/replace + Hashtbl.fold over (k, v) tuples. 29 + baseline programs total. String additions: equal, compare (via host + `<`/`>`), cat (alias of `^`), empty. - 2026-05-09 Phase 5.1 — fraction.ml baseline (rational arithmetic via record + gcd canonicalization). Defines `type frac = { num; den }`, `make` that reduces via gcd and forces den > 0, `add` and