diff --git a/sci b/sci index a6e4ad72..8efab358 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit a6e4ad727780ed0c4516d5252c1eb9d6f119dc2a +Subproject commit 8efab358867ea3bee390e8ff8815dae402210ada diff --git a/script/lib_tests/combinatorics_test b/script/lib_tests/combinatorics_test new file mode 100755 index 00000000..d71a9c3d --- /dev/null +++ b/script/lib_tests/combinatorics_test @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -eo pipefail + +export BABASHKA_CLASSPATH=$(clojure -Sdeps '{:deps {org.clojure/math.combinatorics {:mvn/version "0.1.6"}}}' -Spath) + +if [ "$BABASHKA_TEST_ENV" = "native" ]; then + BB_CMD="./bb" +else + BB_CMD="lein bb" +fi + +$BB_CMD -cp "test-resources/lib_tests:$BABASHKA_CLASSPATH" -e " +(require '[clojure.math.test-combinatorics]) +(require '[clojure.test :as t]) +(let [{:keys [:test :pass :fail :error]} (t/run-tests 'clojure.math.test-combinatorics)] + (when-not (pos? test) + (System/exit 1)) + (System/exit (+ fail error))) +" diff --git a/script/run_lib_tests b/script/run_lib_tests index b50b845d..229e9d73 100755 --- a/script/run_lib_tests +++ b/script/run_lib_tests @@ -14,3 +14,4 @@ script/lib_tests/comb_test script/lib_tests/arrangement_test script/lib_tests/clj_yaml_test script/lib_tests/clojure_data_csv_test +script/lib_tests/combinatorics_test diff --git a/test-resources/lib_tests/clojure/math/test_combinatorics.cljc b/test-resources/lib_tests/clojure/math/test_combinatorics.cljc new file mode 100644 index 00000000..bbb941cf --- /dev/null +++ b/test-resources/lib_tests/clojure/math/test_combinatorics.cljc @@ -0,0 +1,204 @@ +(ns clojure.math.test-combinatorics + (:require [clojure.math.combinatorics :refer + [subsets combinations selections permutations cartesian-product + partitions nth-permutation permutation-index drop-permutations + permuted-combinations + count-permutations count-combinations count-subsets + nth-subset nth-combination]] + [clojure.test :refer [deftest is are testing run-tests]])) + +(deftest test-permuted-combinations + (are [x y] (= x y) + (permuted-combinations [1 2 3] 2) '([1 2] [2 1] [1 3] [3 1] [2 3] [3 2]) + (permuted-combinations [1 2 2] 2) '([1 2] [2 1] [2 2]))) + +(deftest test-combinations + (are [x y] (= x y) + (combinations [1 2 3] 2) '((1 2) (1 3) (2 3)))) + +(defn old-subsets [l] + (map (partial map deref) (subsets (map atom l)))) + +(deftest test-subsets + (are [x y] (= x y) + (subsets []) '(()) + (subsets [1 2 3]) '(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3)) + (subsets [3 2 1]) '(() (3) (2) (1) (3 2) (3 1) (2 1) (3 2 1)) + (subsets [1 2 3 4]) '(() (1) (2) (3) (4) (1 2) (1 3) (1 4) (2 3) (2 4) (3 4) (1 2 3) (1 2 4) (1 3 4) (2 3 4) (1 2 3 4)) + (subsets [1 1 2]) (subsets [1 2 1]) + (subsets [1 3 2 3]) (subsets [1 3 3 2])) + (are [x] (and (= (subsets x) (distinct (old-subsets x))) + (= (count (subsets x)) (count-subsets x))) + [] + [1 2 3 4] + [1 1 2 2 2 3] + [1 1 1 2 2 3] + [1 1 1 1 1] + [1 2 2 3 3 3] + [1 1 2 2 3 3] + [1 1 1 2 2 2] + [1 2 2 2 3 3] + [1 1 1 1 2 2] + [1 2 3 3 4 4] + [1 1 2 3 3 4])) + +(deftest test-nth-combination + (are [x] + (every? + (fn [t] + (and (= (count-combinations x t) (count (combinations x t))) + (let [c (count-combinations x t)] + (= (for [i (range c)] (nth-combination x t i)) + (combinations x t))))) + (range (inc (count x)))) + [1 2 3 4] + [] + [1 2 2 3 3 3] + [1 1 1 2 2 3] + [1 2 2 2 3 3] + [1 1 1 2 3 3] + [1 1 2 3 3 3] + [1 2 3 1 2 1] + [\a \b \c] + [\a \b \c \a \b \c] + )) + +(deftest test-nth-subset + (are [x] + (let [c (count-subsets x)] + (= (for [i (range c)] (nth-subset x i)) + (subsets x))) + [1 2 3 4] + [] + [1 2 2 3 3 3] + [1 1 1 2 2 3] + [1 2 2 2 3 3] + [1 1 1 2 3 3] + [1 1 2 3 3 3] + [1 2 3 1 2 1] + [\a \b \c] + [\a \b \c \a \b \c])) + +(deftest test-cartesian-product + (are [x y] (= x y) + (cartesian-product [1 2] [3 4]) '((1 3) (1 4) (2 3) (2 4)))) + +(deftest test-selections + (are [x y] (= x y) + (selections [1 2] 3) '((1 1 1) (1 1 2) (1 2 1) (1 2 2) (2 1 1) (2 1 2) (2 2 1) (2 2 2)))) + +(def lex-permutations @#'clojure.math.combinatorics/lex-permutations) + +(deftest test-permutations + (are [x y] (= x y) + (permutations [1 2 3]) '((1 2 3) (1 3 2) (2 1 3) (2 3 1) (3 1 2) (3 2 1)) + (permutations [2 3 1]) '((2 3 1) (2 1 3) (3 2 1) (3 1 2) (1 2 3) (1 3 2)) + (permutations [1 1 2]) (lex-permutations [1 1 2]) + (permutations [:a :b]) [[:a :b] [:b :a]] + (permutations [2 1 1]) [[2 1 1] [1 2 1] [1 1 2]])) + +(deftest test-lex-permutations + (are [x y] (= x y) + (lex-permutations [1 1 2]) '([1 1 2] [1 2 1] [2 1 1]))) + +(def sorted-numbers? @#'clojure.math.combinatorics/sorted-numbers?) + +(deftest test-sorted-numbers? + (are [x y] (= x y) + (sorted-numbers? [1 2 3]) true + (sorted-numbers? [1 1 2]) true + (sorted-numbers? []) true + (sorted-numbers? [1 4 2]) false + (sorted-numbers? [1 :a 2]) false)) + +(def factorial-numbers @#'clojure.math.combinatorics/factorial-numbers) + +(deftest test-factorial-numbers + (are [x y] (= (factorial-numbers x) y) + 463 [3 4 1 0 1 0] + 0 [] + 1 [1 0] + 2 [1 0 0])) + +(def nth-permutation-distinct @#'clojure.math.combinatorics/nth-permutation-distinct) + +(deftest test-nth-permutation-distinct + (let [perms (permutations (range 4))] + (doseq [i (range 24)] + (is (= (nth perms i) (nth-permutation-distinct (range 4) i)))))) + +(def nth-permutation-duplicates @#'clojure.math.combinatorics/nth-permutation-duplicates) + +(deftest test-nth-permutation-duplicates + (let [perms (permutations [1 1 2 2 2 3])] + (doseq [i (range 60)] + (is (= (nth perms i) (nth-permutation-duplicates [1 1 2 2 2 3] i)))))) + +(deftest test-count-permutations + (are [x] (= (count-permutations x) (count (permutations x))) + (range 4) + [1 1 2] + [1 1 2 2] + [1 1 1 2 2 3])) + +(deftest test-nth-permutation + (let [sortedDistinctNumbers (range 4) + sortedDuplicateNumbers [1 1 1 2 3 3] + distinctChars [\a \b \c \d] + duplicates [\a \a \b \c \c] + duplicates2 [1 3 1 2 1 2]] + (doseq [collection [sortedDistinctNumbers + sortedDuplicateNumbers + distinctChars + duplicates + duplicates2], + :let [perms (permutations collection) + c (count perms)] + n (range c)] + (is (= (nth perms n) (nth-permutation collection n))) + (is (= c (count-permutations collection)))))) + +(deftest test-drop-permutations + (doseq [x [[1 2 3] + [1 1 2] + [\a \b \c] + [\a \a \b \c \c] + [1 3 1 2 1 2]] + :let [c (count-permutations x)] + i (range c)] + (is (= (drop-permutations x i) (drop i (permutations x)))))) + +(deftest test-permutation-index + (let [sortedDistinctNumbers (range 4) + sortedDuplicateNumbers [1 1 1 2 3 3] + distinctChars [\a \b \c \d] + duplicates [\a \a \b \c \c] + duplicates2 [1 3 1 2 1 2]] + (doseq [collection [sortedDistinctNumbers + sortedDuplicateNumbers + distinctChars + duplicates + duplicates2], + perm (permutations collection)] + (is (= (nth-permutation (sort collection) (permutation-index perm)) + perm))))) + +(deftest test-partitions + (do (are [x y] (= x y) + (partitions [1 2 3]) '(([1 2 3]) ([1 2] [3]) ([1 3] [2]) ([1] [2 3]) ([1] [2] [3])) + (partitions [1 2]) '(([1 2]) ([1] [2])) + (partitions [1]) '(([1])) + (partitions []) '(()) + (partitions nil) '(()) + (partitions [1 1 1]) '(([1 1 1]) ([1 1] [1]) ([1] [1] [1])) + (partitions [1 1 2]) '(([1 1 2]) ([1 1] [2]) ([1 2] [1]) ([1] [1] [2]))) + (doseq [num-items (range 0 4) + lo (range -1 (+ 2 num-items)) + hi (range -1 (+ 2 num-items))] + (is (= (partitions (range num-items) :min lo :max hi) + (filter #(<= lo (count %) hi) (partitions (range num-items)))))) ; tests partitions-H + (doseq [num-items (range 2 4) + lo (range -1 (+ 2 num-items)) + hi (range -1 (+ 2 num-items))] + (is (= (partitions (cons 0 (range (dec num-items))) :min lo :max hi) + (filter #(<= lo (count %) hi) (partitions (cons 0 (range (dec num-items)))))))))) ; tests partitions-M