diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index c3e5c53f..23a1356f 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -48,6 +48,14 @@ (l1 l2 l3 result) (fresh (l12) (appendo l1 l2 l12) (appendo l12 l3 result)))) +(define + partitiono + (fn + (pred l yes no) + (conde + ((nullo l) (nullo yes) (nullo no)) + ((fresh (a d y-rest n-rest) (conso a d l) (conde ((pred a) (conso a y-rest yes) (== no n-rest) (partitiono pred d y-rest n-rest)) ((nafc (pred a)) (== yes y-rest) (conso a n-rest no) (partitiono pred d y-rest n-rest)))))))) + (define membero (fn @@ -80,6 +88,7 @@ ((nullo l) (nullo r)) ((fresh (a d res-rev) (conso a d l) (reverseo d res-rev) (appendo res-rev (list a) r)))))) + (define rev-acco (fn @@ -88,7 +97,6 @@ ((nullo l) (== result acc)) ((fresh (a d acc-prime) (conso a d l) (conso a acc acc-prime) (rev-acco d acc-prime result)))))) - (define rev-2o (fn (l result) (rev-acco l (list) result))) (define palindromeo (fn (l) (fresh (rev) (reverseo l rev) (== l rev)))) diff --git a/lib/minikanren/tests/partitiono.sx b/lib/minikanren/tests/partitiono.sx new file mode 100644 index 00000000..282d1bda --- /dev/null +++ b/lib/minikanren/tests/partitiono.sx @@ -0,0 +1,75 @@ +;; lib/minikanren/tests/partitiono.sx — partition list by predicate. + +(mk-test + "partitiono-empty" + (run* + q + (fresh + (yes no) + (partitiono (fn (x) (== x 1)) (list) yes no) + (== q (list yes no)))) + (list (list (list) (list)))) + +(mk-test + "partitiono-by-equality" + (run* + q + (fresh + (yes no) + (partitiono + (fn (x) (== x 2)) + (list 1 2 3 2 4) + yes + no) + (== q (list yes no)))) + (list + (list + (list 2 2) + (list 1 3 4)))) + +(mk-test + "partitiono-by-numeric-pred" + (run* + q + (fresh + (yes no) + (partitiono + (fn (x) (lto-i x 5)) + (list 1 7 2 8 3) + yes + no) + (== q (list yes no)))) + (list + (list + (list 1 2 3) + (list 7 8)))) + +(mk-test + "partitiono-all-yes" + (run* + q + (fresh + (yes no) + (partitiono + (fn (x) (lto-i x 100)) + (list 1 2 3) + yes + no) + (== q (list yes no)))) + (list (list (list 1 2 3) (list)))) + +(mk-test + "partitiono-all-no" + (run* + q + (fresh + (yes no) + (partitiono + (fn (x) (lto-i 100 x)) + (list 1 2 3) + yes + no) + (== q (list yes no)))) + (list (list (list) (list 1 2 3)))) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index a3a3e49f..b4a77a5c 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,7 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **partitiono**: relational partition. (partitiono pred l yes no) splits l so yes contains elements where pred succeeds and no contains the rest. Composes with intarith for numeric predicates. 5 new tests, 496/496 cumulative. - **2026-05-08** — **appendo3**: 3-list append via two appendos. (appendo3 a b c r) is (appendo a b mid) ∧ (appendo mid c r). Recovers any of the three lists given the other two and the result. 5 new tests, 491/491 cumulative. - **2026-05-08** — **lengtho-i**: integer-indexed length (intarith). Empty list -> 0; recurse with pluso-i. Drop-in fast replacement for Peano lengtho when the count fits in a host integer. 5 new tests, 486/486 cumulative. - **2026-05-08** — **sumo + producto (intarith)**: fold a list of ground integers to its sum or product. Empty list -> identity (0 / 1). Recurse via pluso-i / *o-i. 9 new tests, 481/481 cumulative.