From 3f00e6257754c2307a8320679b3ea892e6cb4ed6 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 11 May 2026 03:54:52 +0000 Subject: [PATCH] ocaml: phase 5.1 count_paths_dag.ml baseline (source-to-sink paths = 3) Count source-to-sink paths in a DAG via Kahn's topological sort plus accumulation: paths[source] = 1 for u in topological order: for v in adj[u]: paths[v] += paths[u] Same 6-node DAG as topo_sort.ml: 0 -> {1, 2} 1 -> {3} 2 -> {3, 4} 3 -> {5} 4 -> {5} The three witnesses 0 -> 5: 0 -> 1 -> 3 -> 5 0 -> 2 -> 3 -> 5 0 -> 2 -> 4 -> 5 Tests Queue-driven Kahn order + List.rev to recover topological order, module-level mutable arrays (in_deg, paths), accumulation in topological traversal. 191 baseline programs total. --- lib/ocaml/baseline/count_paths_dag.ml | 42 +++++++++++++++++++++++++++ lib/ocaml/baseline/expected.json | 1 + plans/ocaml-on-sx.md | 11 +++++++ 3 files changed, 54 insertions(+) create mode 100644 lib/ocaml/baseline/count_paths_dag.ml diff --git a/lib/ocaml/baseline/count_paths_dag.ml b/lib/ocaml/baseline/count_paths_dag.ml new file mode 100644 index 00000000..a7357dd1 --- /dev/null +++ b/lib/ocaml/baseline/count_paths_dag.ml @@ -0,0 +1,42 @@ +let n = 6 +let adj = [| + [1; 2]; + [3]; + [3; 4]; + [5]; + [5]; + [] +|] + +let in_deg = Array.make n 0 +let paths = Array.make n 0 + +let count_paths () = + for u = 0 to n - 1 do + List.iter (fun v -> in_deg.(v) <- in_deg.(v) + 1) adj.(u) + done; + let order = ref [] in + let q = Queue.create () in + for v = 0 to n - 1 do + if in_deg.(v) = 0 then Queue.push v q + done; + while not (Queue.is_empty q) do + let u = Queue.pop q in + order := u :: !order; + List.iter (fun v -> + in_deg.(v) <- in_deg.(v) - 1; + if in_deg.(v) = 0 then Queue.push v q + ) adj.(u) + done; + paths.(0) <- 1; + let topo = List.rev !order in + List.iter (fun u -> + List.iter (fun v -> + paths.(v) <- paths.(v) + paths.(u) + ) adj.(u) + ) topo; + paths.(n - 1) + +;; + +count_paths () diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index 36865605..3df8f632 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -31,6 +31,7 @@ "coin_change.ml": 6, "coin_min.ml": 6, "count_change.ml": 406, + "count_paths_dag.ml": 3, "count_inversions.ml": 12, "count_palindromes.ml": 9, "count_subarrays_k.ml": 7, diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 8a8699e8..bb6f2b7c 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 — count_paths_dag.ml baseline (count + source-to-sink paths in the same 6-node DAG as topo_sort.ml, + paths 0→5 = 3). Topological sort via Kahn's (BFS), then relax + edges in topological order: paths[v] += paths[u] for each edge + u→v. paths[source] = 1. The three witnesses: + 0 → 1 → 3 → 5 + 0 → 2 → 3 → 5 + 0 → 2 → 4 → 5 + Tests Queue-driven Kahn order + List.rev to topological order, + module-level mutable arrays (in_deg / paths), accumulation in + topological traversal. 191 baseline programs total. - 2026-05-11 Phase 5.1 — stock_two.ml baseline (max stock profit with at most 2 transactions on [3;3;5;0;0;3;1;4] = 6). Two-pass DP: left[i] = max single-transaction profit in prices[0..i]