Commit Graph

270 Commits

Author SHA1 Message Date
6780acd0af ocaml: phase 5.1 distinct_subseq.ml baseline ("rabbit" in "rabbbit" = 3)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Classic distinct-subsequences 2D DP:

  dp[i][j] = dp[i-1][j] + (s[i-1] = t[j-1] ? dp[i-1][j-1] : 0)
  dp[i][0] = 1   (empty t is a subseq of any prefix of s)

  count_subseq "rabbbit" "rabbit" = 3

The three witnesses correspond to which 'b' in "rabbbit" is
dropped (positions 2, 3, or 4 zero-indexed of the run of bs).

Complements subseq_check.ml (just tests presence); this one counts
distinct embeddings.

Tests 2D DP with Array.init n (fun _ -> Array.make m 0), base row
initialization, mixed string + array indexing.

175 baseline programs total.
2026-05-11 01:12:33 +00:00
b771ea306c ocaml: phase 5.1 bracket_match.ml baseline (5/9 balanced strings)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Stack-based multi-bracket parenthesis matching for ( [ { ) ] }.
Non-bracket chars are skipped (treated as content).

Tests:
  ()           yes
  [{()}]       yes
  ({[}])       no  (mismatched closer)
  ""           yes
  ((           no  (unclosed)
  ()[](){}     yes
  (a(b)c)      yes  (a/b/c skipped)
  (()          no
  ])           no
                 5 balanced

Body uses begin/end-wrapped match inside while:

  else if c = ')' || c = ']' || c = '}' then begin
    match !stack with
    | [] -> ok := false
    | top :: rest ->
      let pair =
        (c = ')' && top = '(') ||
        (c = ']' && top = '[') ||
        (c = '}' && top = '{')
      in
      if pair then stack := rest else ok := false
  end

Tests side-effecting match arms inside while body, ref-of-list as
stack, multi-char pairing dispatch.

174 baseline programs total.
2026-05-11 01:02:59 +00:00
6c77dec495 ocaml: phase 5.1 wildcard_match.ml baseline (* / ? matcher, 6/18 match)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Recursive wildcard matcher:

  let rec is_match s i p j =
    if j = String.length p then i = String.length s
    else if p.[j] = '*' then
         is_match s i p (j + 1)             (* * matches empty   *)
      || (i < String.length s && is_match s (i + 1) p j)  (* * eats char *)
    else
      i < String.length s
      && (p.[j] = '?' || p.[j] = s.[i])
      && is_match s (i + 1) p (j + 1)

Patterns vs texts:
  a*b      | aaab abc abxyz xy xyz axby   -> 1 match
  ?b*c     | aaab abc abxyz xy xyz axby   -> 1 match
  *x*y*    | aaab abc abxyz xy xyz axby   -> 4 matches
                                  total   = 6

Tests deeply nested short-circuit && / ||, char equality on
pattern bytes, doubly-nested List.iter cross product.

173 baseline programs total.
2026-05-11 00:52:42 +00:00
0a3f02d636 ocaml: phase 5.1 powerset_target.ml baseline (subsets of {1..10} summing to 15 = 20)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Recursive powerset construction by doubling:

  let rec gen xs = match xs with
    | [] -> [[]]
    | h :: rest ->
      let sub = gen rest in
      sub @ List.map (fun s -> h :: s) sub

Enumerates all 2^10 = 1024 subsets, filters by sum:

  count = |{ S ⊆ {1..10} | Σ S = 15 }| = 20

Examples: {1,2,3,4,5}, {2,3,4,6}, {1,4,10}, {7,8}, {6,9}, ...

Tests recursive subset construction via List.map + closures,
pattern matching with h :: rest, List.fold_left (+) 0 sum reduce,
exhaustive O(2^n * n) traversal.

172 baseline programs total.
2026-05-11 00:42:08 +00:00
800dca67ca ocaml: parser accepts top-level tuple patterns in match cases
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Real OCaml accepts `match e1, e2 with | p1, p2 -> …` without
surrounding parens. parse-pattern previously stopped at the cons
layer (`p :: rest`) and treated a trailing `,` as a separator
the outer caller couldn't handle, surfacing as
"expected op -> got op ,".

Fix: `parse-pattern` now collects comma-separated patterns into a
:ptuple after parse-pattern-cons, before the optional `as` alias.
The scrutinee side already built tuples via parse-tuple, so both
sides are now symmetric.

lru_cache.ml (iter 258) reverts its workaround back to the natural
form:

  let rec take n lst = match n, lst with
    | 0, _ -> []
    | _, [] -> []
    | _, h :: r -> h :: take (n - 1) r

607/607 regressions clean.
2026-05-11 00:31:08 +00:00
fd1f94f292 ocaml: phase 5.1 lru_cache.ml baseline (cap=3 LRU, fingerprint 499)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Functional LRU cache via association-list ordered most-recent-first.
Get / put both:
  - find or remove the existing entry
  - cons the fresh (k, v) to the front
  - on put, trim the tail when over capacity

Sequence:
  put 1 100; put 2 200; put 3 300
  a = get 1  -> 100  (moves 1 to front)
  put 4 400          (evicts 2)
  b = get 2  -> -1   (no longer cached)
  c = get 3  -> 300
  d = get 1  -> 100
  a + b + c + d = 499

Tests `match … with (k', v) :: rest when k' = k -> …` tuple-cons
patterns with `when` guards, `function` keyword for arg-less
match, recursive find/remove/take over the same list.

Parser limit found: `match n, lst with` ad-hoc tuple-scrutinee is
not yet supported (got "expected op -> got op ,"); workaround
uses outer `if` plus inner match.

171 baseline programs total.
2026-05-11 00:20:30 +00:00
1d1c35a438 ocaml: phase 5.1 convex_hull.ml baseline (Andrew monotone chain, 5 vertices)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Andrew's monotone chain hull over 8 integer points:

  pts = [(0,0); (1,1); (2,0); (2,2); (0,2); (1,0); (3,3); (5,1)]

Sort lex, build lower hull L->R then upper R->L, popping while
the cross product is non-positive (collinear included on hull).

Hull traverse: (0,0) -> (2,0) -> (5,1) -> (3,3) -> (0,2) = 5
((2,0) lies on the lower edge from (0,0) to (5,1)).

Tests List.sort with 2-tuple comparator using nested pair
destructure, repeated `let (x, y) = arr.(i) in` array tuple
destructure across both passes, while + cont-flag pattern.

170 baseline programs total.
2026-05-11 00:09:06 +00:00
ca34cede88 ocaml: phase 5.1 next_greater.ml baseline (monotonic stack, sum 153)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Right-to-left monotonic stack for next-greater-element:

  for i = n - 1 downto 0 do
    while (match !stack with [] -> false | h :: _ -> h <= arr.(i)) do
      stack := List.tl !stack
    done;
    (match !stack with
     | [] -> res.(i) <- -1
     | h :: _ -> res.(i) <- h);
    stack := arr.(i) :: !stack
  done

For [4; 5; 2; 25; 7; 8; 1; 30; 12]:
  results: [5; 25; 25; 30; 8; 30; 30; -1; -1]
  sum of non-negative = 5+25+25+30+8+30+30 = 153

Tests stack as ref list with match-driven peek, match-as-bool in
while-guard, inline parenthesized match driving <-.

169 baseline programs total.
2026-05-10 23:58:50 +00:00
cb626fc402 ocaml: phase 5.1 fenwick_tree.ml baseline (BIT over 8 elements, fingerprint 228)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Fenwick / Binary Indexed Tree for prefix sums. The classic
`i & -i` low-bit trick needs negative-aware AND, but our `land`
evaluator (iter 127, bitwise via floor/mod arithmetic) only handles
non-negative operands. Workaround: a portable lowbit helper that
finds the largest power of 2 dividing i:

  let lowbit i =
    let r = ref 1 in
    while !r * 2 <= i && i mod (!r * 2) = 0 do
      r := !r * 2
    done;
    !r

After building from [1;3;5;7;9;11;13;15]:
  total       = prefix_sum 8 = 64
  update 1 by +100
  after       = prefix_sum 8 = 164
  total + after = 228

Tests recursive update / prefix_sum chains via helper-extracted
lowbit; documents a non-obvious limit of the bitwise-emulation
layer.

168 baseline programs total.
2026-05-10 23:48:46 +00:00
175a77fba5 ocaml: phase 5.1 segment_tree.ml baseline (range-sum tree, fingerprint 4232)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Power-of-two-indexed segment tree over [1;3;5;7;9;11;13;15]:
  build sums (root holds total = 64)
  query returns range sum in O(log n)
  update propagates a point delta back up the path

Sequence:
  r1 = query [2,5] = 5 + 7 + 9 + 11 = 32
  update idx 3 += 10  (so a[3] becomes 17)
  r2 = query [2,5] = 5 + 17 + 9 + 11 = 42
  encoded fingerprint = r1 + r2*100 = 32 + 4200 = 4232

Tests three mutually independent recursive functions with array
index arithmetic on 2*node / 2*node+1, half-bisection on mid =
(l+r)/2, bottom-up combine pattern.

167 baseline programs total.
2026-05-10 23:38:40 +00:00
3fe3b7b66f ocaml: phase 5.1 magic_square.ml baseline (5x5 Siamese, diag sum = 65)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Siamese construction for odd-order magic squares:

  - place 1 at (0, n/2)
  - for k = 2..n^2, move up-right with (x-1+n) mod n wrap
  - if the target cell is taken, drop down one row instead

  for n=5, magic constant = n*(n^2+1)/2 = 5*26/2 = 65

Returns the main-diagonal sum (65 by construction).

Tests 2D array via Array.init + Array.make, mod arithmetic with
the (x-1+n) mod n idiom for negative-safe wrap, nested begin/end
branches inside for-loop body.

166 baseline programs total.
2026-05-10 23:28:29 +00:00
689438d12e ocaml: phase 5.1 matrix_power.ml baseline (F(30) = 832040 via 2x2 matrix pow)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Fibonacci via repeated-squaring matrix exponentiation:

  [[1, 1], [1, 0]] ^ n = [[F(n+1), F(n)], [F(n), F(n-1)]]

Recursive O(log n) power:

  let rec mpow m n =
    if n = 0 then identity
    else if n mod 2 = 0 then let h = mpow m (n / 2) in mul h h
    else mul m (mpow m (n - 1))

Returns the .b cell after raising to the 30th power -> 832040 = F(30).

Tests record literal construction inside recursive function returns,
record field access (x.a etc), and pure integer arithmetic in the
matrix multiply.

165 baseline programs total.
2026-05-10 23:18:26 +00:00
d1a4616ac4 ocaml: phase 5.1 bipartite.ml baseline (7-node bipartite, 4 in color 0)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
BFS-based 2-coloring of an undirected graph:

  edges (undirected):
    0-1  0-3  1-2  1-4  2-5  3-4  3-6  5-6

  Partition: {0, 2, 4, 6} vs {1, 3, 5} (no odd cycles)

Returns count of color-0 vertices (4) on success, -1 on odd-cycle
detection.

Tests Queue-based BFS with a source-loop wrapper for disconnected
graphs, `1 - color.(u)` toggle, color-equality conflict check
on already-colored neighbors.

164 baseline programs total.
2026-05-10 23:08:16 +00:00
32f6c4ee0c ocaml: phase 5.1 egg_drop.ml baseline (2 eggs, 36 floors -> 8 trials)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Classic egg-drop puzzle DP:

  dp[e][f] = 1 + min over k in [1, f] of
              max(dp[e-1][k-1], dp[e][f-k])

For 2 eggs over 36 floors, the optimal worst-case is 8 trials
(closed form: triangular number bound).

Tests 2D DP with triple-nested for-loops, max-of-two via inline
if, large sentinel constant (100000000), mixed shifted indexing
(e-1) and (f-k) where both shift independently.

163 baseline programs total.
2026-05-10 22:58:13 +00:00
62712accdd ocaml: phase 5.1 polygon_area.ml baseline (pentagon 2x area = 32)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Shoelace formula on a pentagon with integer vertices:

  pts = [(0,0); (4,0); (4,3); (2,5); (0,3)]

  2 * area = | Σ (x_i * y_{i+1} - x_{i+1} * y_i) |
           = | 0*0 - 4*0 + 4*3 - 4*0 + 4*5 - 2*3 + 2*3 - 0*5
                + 0*0 - 0*3 |
           = 32

Returns the doubled form (32) to stay integral.

Tests:
  - let (x1, y1) = arr.(i) in   -- tuple destructure from array
  - arr.((i + 1) mod n)         -- modular wrap-around index
  - if a < 0 then - a else a    -- prefix - negation

162 baseline programs total.
2026-05-10 22:47:22 +00:00
c69a7694c8 ocaml: phase 5.1 min_cost_path.ml baseline (4x4 grid DP, optimal cost 12)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Standard 2D DP for min-cost path with right/down moves only:

  dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + cost[i][j]

  cost:                  dp:
    1 3 1 2                1  4  5  7
    1 5 1 3                2  7  6  9
    4 2 1 4                6  8  7 11
    1 6 2 3                7 13  9 12

Optimal cost from (0,0) to (3,3) = 12.

Tests nested 2D arrays via Array.init + Array.make, double-nested
for-loops with branched edges (first row, first column, general),
mixed .(i-1).(j) read + .(i).(j)<- write on the same DP array.

161 baseline programs total.
2026-05-10 22:37:44 +00:00
5384ff6c42 ocaml: phase 5.1 topo_dfs.ml baseline (DFS topo sort, fingerprint 24135)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
DFS topological sort — recurse on out-edges first, prepend after:

  let rec dfs v =
    if not visited.(v) then begin
      visited.(v) <- true;
      List.iter dfs adj.(v);
      order := v :: !order
    end

Same 6-node DAG as iter 230's Kahn's-algorithm baseline:
  0 -> {1, 2}
  1 -> {3}
  2 -> {3, 4}
  3 -> {5}
  4 -> {5}
  5

DFS order: [0; 2; 4; 1; 3; 5]
Horner fold: 0->0->2->24->241->2413->24135.

Complementary to topo_sort.ml (Kahn's BFS); tests recursive DFS
with no explicit stack + List.fold_left as a horner reduction.

160 baseline programs total.
2026-05-10 22:27:18 +00:00
bcb7db2ea4 ocaml: phase 5.1 radix_sort.ml baseline (LSD radix sort, sentinel 802002)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
LSD radix sort over base 10 digits. Per pass:
  - 10 bucket-refs created via Array.init 10 (fun _ -> ref []) (each
    closure call yields a distinct list cell)
  - scan array, append each value to its digit's bucket
  - flatten buckets back to the array in order

Input  [170;45;75;90;802;24;2;66]
Output [2;24;45;66;75;90;170;802]

Sentinel: a.(0) + a.(7)*1000 = 2 + 802*1000 = 802002.

Tests array-of-refs with !buckets.(d) deref, list-mode bucket
sort within in-place array sort, unused for-loop var (`for _ =
1 to maxd`).

159 baseline programs total.
2026-05-10 22:17:40 +00:00
5eed0dd5f5 ocaml: phase 5.1 coin_min.ml baseline (67 cents in US coins = 6)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Minimum-coin DP with -1 sentinel for unreachable values:

  let coin_min coins amount =
    let dp = Array.make (amount + 1) (-1) in
    dp.(0) <- 0;
    for i = 1 to amount do
      List.iter (fun c ->
        if c <= i && dp.(i - c) >= 0 then begin
          let cand = dp.(i - c) + 1 in
          if dp.(i) < 0 || cand < dp.(i) then dp.(i) <- cand
        end
      ) coins
    done;
    dp.(amount)

  coin_min [1; 5; 10; 25] 67 = 6   (* 25+25+10+5+1+1 *)

Tests `if c <= i && dp.(i-c) >= 0 then` short-circuit guard;
relies on iter-242 fix so dp.(i-c) is not evaluated when c > i.

158 baseline programs total.
2026-05-10 22:07:17 +00:00
3ea8967571 ocaml: phase 5.1 flood_fill.ml baseline (largest grid component = 7)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Recursive 4-way flood fill from every unvisited 1-cell:

  let rec flood visited r c =
    if r < 0 || r >= h || c < 0 || c >= w then 0
    else if visited.(r).(c) || grid.(r).(c) = 0 then 0
    else begin
      visited.(r).(c) <- true;
      1 + flood visited (r - 1) c
        + flood visited (r + 1) c
        + flood visited r (c - 1)
        + flood visited r (c + 1)
    end

Grid (1s shown as #, 0s as .):
  # # . # #
  # . . . #
  . . # . .
  # # # # .
  . . . # #

Largest component: {(2,2),(3,0),(3,1),(3,2),(3,3),(4,3),(4,4)} = 7.

Bounds check r >= 0 must short-circuit before visited/grid reads;
relies on the && / || fix from iter 242.

157 baseline programs total.
2026-05-10 21:57:42 +00:00
e057d9f18f ocaml: phase 5.1 next_permutation.ml baseline (5! - 1 = 119 successors)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Standard in-place next-permutation (Narayana's algorithm):

  let next_perm a =
    let n = Array.length a in
    let i = ref (n - 2) in
    while !i >= 0 && a.(!i) >= a.(!i + 1) do i := !i - 1 done;
    if !i < 0 then false
    else begin
      let j = ref (n - 1) in
      while a.(!j) <= a.(!i) do j := !j - 1 done;
      swap a.(!i) a.(!j);
      reverse a (!i + 1) (n - 1);
      true
    end

Starting from [1;2;3;4;5], next_perm returns true 119 times then
false (when reverse-sorted). 5! - 1 = 119.

Tests guarded `while … && a.(!i) … do` loops that rely on the
iter-242 short-circuit fix.

156 baseline programs total.
2026-05-10 21:47:52 +00:00
4761d41a0d ocaml: && / || short-circuit fix + bfs_grid.ml baseline (5x5 grid, dist 8)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Before: `:op` handler always evaluated both operands before dispatching
to ocaml-eval-op. For pure binops that's fine, but `&&` / `||` MUST
short-circuit:

  if nr >= 0 && grid.(nr).(nc) = 0 then ...

When nr = -1, real OCaml never evaluates `grid.(-1)`. Our evaluator
did, and crashed with "nth: list/string and number".

Fix: special-case `&&` and `||` in :op dispatch, mirroring the same
pattern already used for `:=` and `<-`. Evaluate lhs, branch on it,
and only evaluate rhs when needed.

Latent since baseline 1 — earlier programs never triggered it because
the rhs was unconditionally safe.

bfs_grid.ml: shortest path through a 5x5 grid with walls. Standard
BFS using Queue.{push,pop,is_empty} + Array.init for the 2D distance
matrix. Path 0,0 -> ... -> 4,4 has length 8. 155 baseline programs
total.
2026-05-10 21:37:41 +00:00
bed374c9e1 ocaml: phase 5.1 tarjan_scc.ml baseline (8-node digraph, 4 SCCs)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Tarjan's strongly-connected components in a single DFS using
index/lowlink:

  graph (8 nodes, directed):
    0 -> 1 -> 2 -> 0   (3-cycle)
    2 -> 3
    3 -> 4
    4 -> 5 -> 6 -> 4   (3-cycle)
    4 -> 7

  SCCs: {0,1,2}, {3}, {4,5,6}, {7}  =  4 components

Module-level ref + array state (index_arr, lowlink, on_stack,
stack, scc_count). When lowlink(v) = index(v), pop from stack
until v is removed; that's a complete SCC.

Tests: recursive function with module-level mutable state,
nested begin/end branches inside List.iter closure, inner
`let rec pop ()` traversing a ref-of-list, pattern match on
[] / h :: rest cons-list shape.

154 baseline programs total.
2026-05-10 07:06:29 +00:00
b4571f0f9f ocaml: phase 5.1 lev_iter.ml baseline (sum of 5 edit distances = 16)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Iterative Levenshtein DP with rolling 1D arrays for O(min(m,n))
space. Distances:

  kitten    -> sitting    : 3
  saturday  -> sunday     : 3
  abc       -> abc        : 0
  ""        -> abcde      : 5
  intention -> execution  : 5
  ----------------------------
  total                   : 16

Complementary to the existing levenshtein.ml which uses the
exponential recursive form (only sums tiny strings); this one is
the practical iterative variant used for real ED.

Tests the recently-fixed <- with bare `if` rhs:

  curr.(j) <- (if m1 < c then m1 else c) + 1

153 baseline programs total.
2026-05-10 06:53:38 +00:00
0ef26b20f3 ocaml: phase 5.1 binary_heap.ml baseline (min-heap sort 9 vals -> 123456789)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Array-backed binary min-heap with explicit size tracking via ref:

  let push a size x =
    a.(!size) <- x; size := !size + 1; sift_up a (!size - 1)

  let pop a size =
    let m = a.(0) in
    size := !size - 1;
    a.(0) <- a.(!size);
    sift_down a !size 0;
    m

Push [9;4;7;1;8;3;5;2;6], pop nine times -> 1,2,3,4,5,6,7,8,9.
Fold-as-decimal: ((((((((1*10+2)*10+3)*10+4)*10+5)*10+6)*10+7)*10+8)*10+9 = 123456789.

Tests recursive sift_up + sift_down, in-place array swap,
parent/lchild/rchild index arithmetic, combined push/pop session
with refs.

152 baseline programs total.
2026-05-10 06:43:46 +00:00
19d0ef0f38 ocaml: phase 5.1 rolling_hash.ml baseline (Rabin-Karp, 6 "abc" matches)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Polynomial rolling hash mod 1000003 with base 257:
  - precompute base^(m-1)
  - slide window updating hash in O(1) per step
  - verify hash match with O(m) memcmp to skip false positives

  rolling_match "abcabcabcabcabcabc" "abc" = 6

Six non-overlapping copies of "abc" at positions 0,3,6,9,12,15.

Tests `for _ = 0 to m - 2 do … done` unused loop variable
(uses underscore wildcard pattern), Char.code arithmetic, mod
arithmetic with intermediate negative subtractions, complex nested
if/begin branching with inner break-via-flag.

151 baseline programs total.
2026-05-10 06:34:13 +00:00
1dd350d592 ocaml: phase 5.1 huffman.ml baseline (Huffman tree WPL = 224)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Classic CLRS Huffman code example. ADT:

  type tree = Leaf of int * char | Node of int * tree * tree

Build by repeatedly merging two lightest trees (sorted-list pq):

  let rec build_tree lst = match lst with
    | [t] -> t
    | a :: b :: rest ->
      let merged = Node (weight a + weight b, a, b) in
      build_tree (insert merged rest)

  weighted path length (= total Huffman bits):
    leaves {(5,a) (9,b) (12,c) (13,d) (16,e) (45,f)} -> 224

Tests sum-typed ADT with mixed arities, `function` keyword
pattern matching, recursive sorted insert, depth-counting recursion.

150 baseline programs total.
2026-05-10 06:21:06 +00:00
4fdf6980da ocaml: parser accepts if/match/let/fun as rhs of <- and :=
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Previously `a.(i) <- if c then x else y` failed with
"unexpected token keyword if" because parse-binop-rhs called
parse-prefix for the rhs, which doesn't accept if/match/let/fun.

Real OCaml allows full expressions on the rhs of <-/:=. Fix:
special-case prec-1 ops in parse-binop-rhs to call parse-expr-no-seq
instead of parse-prefix. The recursive parse-binop-rhs with
min-prec restored after picks up any further chained <- (since both
ops are right-associative with no higher-prec binops above them).

Manacher baseline updated to use bare `if` on rhs of <-,
removing the parens workaround from iter 235. 607/607 regressions
remain clean.
2026-05-10 06:11:57 +00:00
cccef832d9 ocaml: phase 5.1 manacher.ml baseline (longest palindrome "babadaba" = 7)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Manacher's algorithm: insert # separators (length 2n+1) to unify
odd/even cases, then maintain palindrome radii p[] alongside a
running (center, right) pair to skip work via mirror reflection.
Linear time.

  manacher "babadaba" = 7   (* witness: "abadaba", positions 1..7 *)

Note: requires parenthesizing the if-expression on the rhs of <-:

  p.(i) <- (if pm < v then pm else v)

Real OCaml parses bare `if` at <-rhs since the rhs is at expr
level; our parser places <-rhs at binop level which doesn't include
`if` / `match` / `let`. Workaround until we relax the binop
RHS grammar.

149 baseline programs total.
2026-05-10 05:58:05 +00:00
526ffbb5f0 ocaml: phase 5.1 floyd_warshall.ml baseline (4-node APSP, dist(0,3)=9)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
Floyd-Warshall all-pairs shortest path with triple-nested for-loop:

  for k = 0 to n - 1 do
    for i = 0 to n - 1 do
      for j = 0 to n - 1 do
        if d.(i).(k) + d.(k).(j) < d.(i).(j) then
          d.(i).(j) <- d.(i).(k) + d.(k).(j)
      done
    done
  done

Graph (4 nodes, directed):
  0->1 weight 5, 0->3 weight 10, 1->2 weight 3, 2->3 weight 1

Direct edge 0->3 = 10, but path 0->1->2->3 = 5+3+1 = 9.

Tests 2D array via Array.init with closure, nested .(i).(j) read
+ write, triple-nested for, in-place mutation under aliasing.

148 baseline programs total.
2026-05-10 05:41:02 +00:00
99f321f532 ocaml: phase 5.1 mst_kruskal.ml baseline (5-node MST weight 11)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
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.
2026-05-10 05:21:14 +00:00
dfd89d998e ocaml: phase 5.1 trie.ml baseline (prefix tree, 6/9 word lookups match)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Mutable-record trie with linked-list children:

  type trie = {
    mutable terminal : bool;
    mutable children : (char * trie) list
  }

Insert {cat, car, card, cart, dog, doge}; lookup 9 words. Hits are
exactly the inserted set: cat, car, card, cart, dog, doge = 6.
Misses: ca (prefix not terminal), dogs (extends 'dog' but no 'dogs'
node), x (no path).

Tests:
  - recursive type definition with self-referential field
  - mutable record fields with .field <- v
  - Option pattern matching (Some / None)
  - tuple-cons pattern (k, v) :: rest

146 baseline programs total.
2026-05-10 05:11:12 +00:00
74d8ade089 ocaml: phase 5.1 count_inversions.ml baseline (12 inversions via merge sort)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Modified merge sort that counts inversions during the merge step:
when an element from the right half is selected, the remaining
elements of the left half (mid - i + 1) all form inversions with
that right element.

  count_inv [|8; 4; 2; 1; 3; 5; 7; 6|] = 12

Inversions of [8;4;2;1;3;5;7;6]:
  with 8: (8,4)(8,2)(8,1)(8,3)(8,5)(8,7)(8,6) = 7
  with 4: (4,2)(4,1)(4,3) = 3
  with 2: (2,1) = 1
  with 7: (7,6) = 1
                                        total = 12

Tests: let rec ... and ... mutual recursion, while + ref + array
mutation, in-place sort with auxiliary scratch array.

145 baseline programs total.
2026-05-10 05:01:08 +00:00
872302ede1 ocaml: phase 5.1 topo_sort.ml baseline (6-node DAG, all 6 ordered)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
Kahn's algorithm BFS topological sort:

  let topo_sort n adj =
    let in_deg = Array.make n 0 in
    for i = 0 to n - 1 do
      List.iter (fun j -> in_deg.(j) <- in_deg.(j) + 1) adj.(i)
    done;
    let q = Queue.create () in
    for i = 0 to n - 1 do
      if in_deg.(i) = 0 then Queue.push i q
    done;
    let count = ref 0 in
    while not (Queue.is_empty q) do
      let u = Queue.pop q in
      count := !count + 1;
      List.iter (fun v ->
        in_deg.(v) <- in_deg.(v) - 1;
        if in_deg.(v) = 0 then Queue.push v q
      ) adj.(u)
    done;
    !count

Graph: 0->{1,2}; 1->{3}; 2->{3,4}; 3->{5}; 4->{5}; 5.
Acyclic, so all 6 nodes can be ordered.

Tests Queue.{create,push,pop,is_empty}, mutable array via closure.

144 baseline programs total.
2026-05-10 04:51:15 +00:00
57a63826e3 ocaml: phase 5.1 knapsack.ml baseline (0/1 knapsack, cap=8 -> 36)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 15s
Standard 1D 0/1 knapsack DP with reverse inner loop:

  let knapsack values weights cap =
    let n = Array.length values in
    let dp = Array.make (cap + 1) 0 in
    for i = 0 to n - 1 do
      let v = values.(i) and w = weights.(i) in
      for c = cap downto w do
        let take = dp.(c - w) + v in
        if take > dp.(c) then dp.(c) <- take
      done
    done;
    dp.(cap)

  values: [|6; 10; 12; 15; 20|]
  weights: [|1; 2;  3;  4;  5|]
  knapsack v w 8 = 36   (* take items with weights 1, 2, 5 *)

Tests for-downto + array literal access in the same hot loop.

143 baseline programs total.
2026-05-10 04:38:59 +00:00
7a67637826 ocaml: phase 5.1 lcs.ml baseline (LCS of "ABCBDAB" and "BDCAB" = 4)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Classic 2D DP for longest common subsequence, optimized to use
two rolling 1D arrays (prev / curr) for O(min(m,n)) space:

  for i = 1 to m do
    for j = 1 to n do
      if s1.[i-1] = s2.[j-1] then curr.(j) <- prev.(j-1) + 1
      else if prev.(j) >= curr.(j-1) then curr.(j) <- prev.(j)
      else curr.(j) <- curr.(j-1)
    done;
    for j = 0 to n do prev.(j) <- curr.(j) done
  done;
  prev.(n)

  lcs "ABCBDAB" "BDCAB" = 4

Two valid LCS witnesses: BCAB and BDAB.

Avoids Array.make_matrix (not in our runtime) by manual rolling.

142 baseline programs total.
2026-05-10 04:29:58 +00:00
42a506faff ocaml: phase 5.1 dijkstra.ml baseline (5-node SSSP, dist(0,4) = 7)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Array-based O(n^2) Dijkstra on a small directed weighted graph:

  edges = [|
    [(1, 4); (2, 1)];   (* 0 -> 1 (w=4), 2 (w=1) *)
    [(3, 1)];           (* 1 -> 3 (w=1)         *)
    [(1, 2); (3, 5)];   (* 2 -> 1 (w=2), 3 (w=5) *)
    [(4, 3)];           (* 3 -> 4 (w=3)         *)
    []                  (* 4 sink              *)
  |]

Optimal path 0->2->1->3->4 has weight 1+2+1+3 = 7.

Tests: array-of-list-of-int-pair literal, List.iter with tuple
destructuring closure, in-place dist mutation, nested for + ref.

141 baseline programs total.
2026-05-10 04:20:47 +00:00
713d506bb8 ocaml: phase 5.1 kmp.ml baseline (5 occurrences of "abab" in haystack)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Knuth-Morris-Pratt linear-time string search:
  - kmp_table builds failure function in O(|pattern|)
  - kmp_search scans text once in O(|text|), counting matches
  - After a hit, k := t.(n-1) so overlapping matches still count

  kmp_search "abababcabababcababcc" "abab" = 5

Hits at positions 0, 2, 7, 9, 14 (overlapping at 0/2 and 7/9).

Tests: nested while-inside-for, char inequality (.<>), pat.[i]
string indexing, Array.make 0, combined string + array indexing.

140 baseline programs total.
2026-05-10 04:08:53 +00:00
bcaa41d1ae ocaml: phase 5.1 union_find.ml baseline (10 nodes, 6 unions, 4 components)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Disjoint-set union with path compression:

  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 p.(rx) <- ry

After unioning (0,1), (2,3), (4,5), (6,7), (0,2), (4,6):
  {0,1,2,3} {4,5,6,7} {8} {9}  --> 4 components.

Tests Array.init with closure, recursive find, in-place .(i)<-r.

139 baseline programs total.
2026-05-10 03:59:56 +00:00
edbb03e205 ocaml: phase 5.1 quickselect.ml baseline (median of 9 elements = 5)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 21s
Hoare quickselect with Lomuto partition: recursively narrows the
range to whichever side contains the kth index. Mutates the array
in place via .(i)<-v. The median (k=4) of [7;2;9;1;5;6;3;8;4] is 5.

  let rec quickselect arr lo hi k =
    if lo = hi then arr.(lo)
    else begin
      let pivot = arr.(hi) in
      let i = ref lo in
      for j = lo to hi - 1 do
        if arr.(j) < pivot then begin
          let t = arr.(!i) in
          arr.(!i) <- arr.(j); arr.(j) <- t;
          i := !i + 1
        end
      done;
      ...
    end

Exercises array literal syntax + in-place mutation in the same
program, ensuring [|...|] yields a mutable backing.

138 baseline programs total.
2026-05-10 03:50:59 +00:00
551ed44f7f ocaml: phase 5.1 array literals [|...|] + lis.ml baseline (LIS = 6)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 35s
Added parser support for OCaml array literal syntax:

  [| e1; e2; ...; en |]  -->  Array.of_list [e1; e2; ...; en]
  [||]                   -->  Array.of_list []

Desugaring keeps the array representation unchanged (ref-of-list)
since Array.of_list is a no-op constructor for that backing.

Tokenizer emits [, |, |, ] as separate ops; parser detects [ followed
by | and enters array-literal mode, terminating on |].

Baseline lis.ml exercises the syntax:

  let lis arr =
    let n = Array.length arr in
    let dp = Array.make n 1 in
    for i = 1 to n - 1 do
      for j = 0 to i - 1 do
        if arr.(j) < arr.(i) && dp.(j) + 1 > dp.(i) then
          dp.(i) <- dp.(j) + 1
      done
    done;
    let best = ref 0 in
    for i = 0 to n - 1 do
      if dp.(i) > !best then best := dp.(i)
    done;
    !best

  lis [|10; 22; 9; 33; 21; 50; 41; 60; 80|] = 6

137 baseline programs total.
2026-05-10 03:41:19 +00:00
76de0a20f8 ocaml: phase 5.1 josephus.ml baseline (n=50 k=3, survivor at position 11)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Classic Josephus problem solved with the standard recurrence:

  let rec josephus n k =
    if n = 1 then 0
    else (josephus (n - 1) k + k) mod n

  josephus 50 3 + 1 = 11

50 people stand in a circle, every 3rd is eliminated; the last
survivor is at position 11 (1-indexed). Tests recursion + mod.

136 baseline programs total.
2026-05-10 03:22:29 +00:00
353dcb67d6 ocaml: phase 5.1 partition_count.ml baseline (p(15) = 176)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
Counts integer partitions via classic DP:

  let partition_count n =
    let dp = Array.make (n + 1) 0 in
    dp.(0) <- 1;
    for k = 1 to n do
      for i = k to n do
        dp.(i) <- dp.(i) + dp.(i - k)
      done
    done;
    dp.(n)

  partition_count 15 = 176

Tests Array.make, .(i)<-/.(i) array access, nested for-loops, refs.

135 baseline programs total.
2026-05-10 03:13:36 +00:00
36e02c906a ocaml: phase 5.1 pythagorean.ml baseline (primitive Pythagorean triples with hyp <= 100 = 16)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 29s
Uses Euclid's formula: for coprime m > k of opposite parity, the
triple (m^2 - k^2, 2mk, m^2 + k^2) is a primitive Pythagorean.

  let count_primitive_triples n =
    let c = ref 0 in
    for m = 2 to 50 do
      let kk = ref 1 in
      while !kk < m do
        if (m - !kk) mod 2 = 1 && gcd m !kk = 1 then begin
          let h = m * m + !kk * !kk in
          if h <= n then c := !c + 1
        end;
        kk := !kk + 1
      done
    done;
    !c

  count_primitive_triples 100 = 16

The 16 triples include the classics (3,4,5), (5,12,13), (8,15,17),
(7,24,25), and end with (65,72,97).

134 baseline programs total.
2026-05-10 03:02:17 +00:00
5c1b4349aa ocaml: phase 5.1 harshad.ml baseline (count Niven/Harshad numbers <= 100 = 33)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
A Harshad (or Niven) number is divisible by its digit sum:

  let count_harshad limit =
    let c = ref 0 in
    for n = 1 to limit do
      if n mod (digit_sum n) = 0 then c := !c + 1
    done;
    !c

  count_harshad 100 = 33

All single-digit numbers (1..9) qualify trivially. Plus 10, 12, 18,
20, 21, 24, 27, 30, 36, 40, 42, 45, 48, 50, 54, 60, 63, 70, 72, 80,
81, 84, 90, 100 (24 more) = 33 total under 100.

133 baseline programs total.
2026-05-10 02:46:20 +00:00
e23aa9c273 ocaml: phase 5.1 reverse_int.ml baseline (digit-reverse sum = 54329)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Walks digits via mod 10 / div 10, accumulating the reversed value:

  let reverse_int n =
    let m = ref n in
    let r = ref 0 in
    while !m > 0 do
      r := !r * 10 + !m mod 10;
      m := !m / 10
    done;
    !r

  reverse 12345 + reverse 100 + reverse 7
  = 54321 + 1 + 7
  = 54329

Trailing zeros collapse (reverse 100 = 1, not 001).

132 baseline programs total.
2026-05-10 02:36:37 +00:00
da54c3ea53 ocaml: phase 5.1 bowling.ml baseline (10-pin bowling score, sample game = 167)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s
Walks the pin-knockdown list applying strike/spare bonuses through
a 10-frame counter:

  strike (10):           score 10 + next 2 throws,  advance i+1
  spare  (a + b = 10):   score 10 + next 1 throw,   advance i+2
  open  (a + b < 10):    score a + b,                advance i+2

Frame ten special-cases are handled implicitly: the input includes
bonus throws naturally and the while-loop terminates after frame 10.

  bowling_score [10; 7; 3; 9; 0; 10; 0; 8; 8; 2; 0; 6;
                 10; 10; 10; 8; 1]
  = 20+19+9+18+8+10+6+30+28+19
  = 167

131 baseline programs total.
2026-05-10 02:26:10 +00:00
63901931c4 ocaml: phase 5.1 tail_factorial.ml baseline (12! via tail-recursion = 479001600)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 43s
Single-helper tail-recursive loop threading an accumulator:

  let factorial n =
    let rec go n acc =
      if n <= 1 then acc
      else go (n - 1) (n * acc)
    in
    go n 1

  factorial 12 = 479_001_600

Companion to factorial.ml (10! = 3628800 via doubly-recursive
style); same answer-shape, different evaluator stress: this version
has constant stack depth.

130 baseline programs total — milestone.
2026-05-10 02:05:09 +00:00
e77a2d3a81 ocaml: phase 5.1 zerosafe.ml baseline (Option-chained safe division, sum = 28)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
safe_div returns None on division by zero; safe_chain stitches two
divisions, propagating None on either failure:

  let safe_div a b =
    if b = 0 then None else Some (a / b)

  let safe_chain a b c =
    match safe_div a b with
    | None -> None
    | Some q -> safe_div q c

Test:
  safe_chain 100 2 5    = Some 10
  safe_chain 100 0 5    = None  -> -1
  safe_chain 50 5 0     = None  -> -1
  safe_chain 1000 10 5  = Some 20
  10 - 1 - 1 + 20 = 28

Tests Option chaining + match-on-result with sentinel default.
Demonstrates the canonical 'fail-early on None' pattern.

129 baseline programs total.
2026-05-10 01:49:23 +00:00
836e01dbb4 ocaml: phase 5.1 number_words.ml baseline (letter count of 1..19 spelled out = 106)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s
19-arm match returning the English word for each number 1..19, then
sum String.length:

  let number_to_words n =
    match n with
    | 1 -> 'one' | 2 -> 'two' | ... | 19 -> 'nineteen'
    | _ -> ''

  total_letters 19 = 36 + 70 = 106
                    (1-9)  (10-19)

Real PE17 covers 1..1000 (answer 21124) but needs more elaborate
number-to-words logic (compounds, 'and', 'thousand'). 1..19 keeps
the program small while exercising literal-pattern match dispatch
on many arms.

128 baseline programs total.
2026-05-10 01:39:25 +00:00