├── .gitignore ├── .travis.yml ├── KotlinDiscreteMathToolkit.iml ├── README.md ├── _config.yml ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── main └── java │ └── com │ └── marcinmoskala │ └── math │ ├── CartesianProductExt.kt │ ├── CombinationsExt.kt │ ├── FactorialFun.kt │ ├── IterableMultiplication.kt │ ├── NumSplitFunc.kt │ ├── NumbersDivisible.kt │ ├── PermutationsExt.kt │ ├── Power.kt │ ├── PowersetExt.kt │ ├── ProductExt.kt │ ├── SetSplitFunc.kt │ └── SublistsBySplittersExt.kt └── test └── java └── com └── marcinmoskala └── math └── tests ├── CartesianProductPropertyTest.kt ├── CartesianProductTest.kt ├── CombinationTest.kt ├── CombinationWithRepetitionTest.kt ├── FactorialTest.kt ├── IterableMultipliationTest.kt ├── JavaTest.java ├── NumberSplitTest.kt ├── NumbersDivisibleTest.kt ├── PermutationTest.kt ├── PowerTest.kt ├── PowersetTest.kt ├── ProductTest.kt ├── SetSplitTest.kt ├── SublistsBySplittersTest.kt └── TestUtils.kt /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.jar 3 | *.war 4 | *.ear 5 | /.idea/ 6 | DiscreteMathToolkit.iml 7 | out/ 8 | gradle.properties 9 | *.log 10 | *.ctxt 11 | .mtj.tmp/ 12 | *.zip 13 | *.tar.gz 14 | *.rar 15 | hs_err_pid* 16 | .gradle/ 17 | build/ 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | install: true 7 | 8 | script: 9 | - ./gradlew check 10 | 11 | after_success: 12 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /KotlinDiscreteMathToolkit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiscreteMathToolkit 2 | Set of extensions for Kotlin that provides Discrete Math functionalities as an Kotlin extension functions. 3 | 4 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.marcinmoskala/DiscreteMathToolkit/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.marcinmoskala/DiscreteMathToolkit) 5 | [![Build Status](https://travis-ci.org/MarcinMoskala/KotlinDiscreteMathToolkit.svg?branch=master)](https://travis-ci.org/MarcinMoskala/KotlinDiscreteMathToolkit) 6 | [![codecov](https://codecov.io/gh/MarcinMoskala/KotlinDiscreteMathToolkit/branch/master/graph/badge.svg)](https://codecov.io/gh/MarcinMoskala/KotlinDiscreteMathToolkit) 7 | [![codebeat badge](https://codebeat.co/badges/70bb9b0e-a47e-477a-933d-adc7220ae926)](https://codebeat.co/projects/github-com-marcinmoskala-kotlindiscretemathtoolkit-master) 8 | [![Analytics](https://ga-beacon.appspot.com/UA-92159206-7/main-page?pixel)](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit) 9 | 10 | To stay current with news about library [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/fold_left.svg?style=social&label=Follow%20%40marcinmoskala)](https://twitter.com/marcinmoskala?ref_src=twsrc%5Etfw) 11 | 12 | # Permutations 13 | 14 | ```kotlin 15 | setOf(1, 2, 3).permutations() // {[1, 2, 3], [2, 1, 3], [3, 2, 1], [1, 3, 2], [2, 3, 1], [3, 1, 2]} 16 | setOf(1, 2, 3).permutationsNumber() // 6 17 | listOf(1, 2, 2).permutations() // {[1, 2, 2], [2, 1, 2], [2, 2, 1]} 18 | listOf(1, 2, 2).permutationsNumber() // 3 19 | ``` 20 | 21 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/PermutationTest.kt) 22 | 23 | # Combinations 24 | 25 | ```kotlin 26 | setOf(1, 2, 3, 4).combinations(3) // { {1, 2, 3}, {1, 2, 4}, {1, 4, 3}, {4, 2, 3} } 27 | setOf(1, 2, 3, 4).combinationNumber(3) // 4 28 | 29 | setOf(1, 2, 3, 4).combinationsWithRepetitions(2) // [{1=2}, {1=1, 2=1}, {1=1, 3=1}, {1=1, 4=1}, {2=2}, {2=1, 3=1}, {2=1, 4=1}, {3=2}, {3=1, 4=1}, {4=2}] 30 | setOf(1, 2, 3, 4).combinationsWithRepetitionsNumber(2) // 10 31 | ``` 32 | 33 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/CombinationTest.kt) and [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/CombinationWithRepetitionTest.kt) 34 | 35 | # Powerset 36 | Powerset of any set S is the set of all subsets of S, including the empty set and S itself. 37 | 38 | ```kotlin 39 | setOf(1, 2, 3).powerset() // { {}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3} } 40 | setOf(1, 2, 3).powersetSize() // 8 41 | ``` 42 | # Product 43 | Product is the result of multiplying. 44 | 45 | ```kotlin 46 | (3..4).product() // 12 47 | listOf(10, 10, 10).product() // 1000 48 | ``` 49 | 50 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/ProductTest.kt). 51 | 52 | # Factorial 53 | Factorian of n (n!) is a product of all positive integers less than or equal to n. 54 | 55 | ```kotlin 56 | 3.factorial() // 6L 57 | 10.factorial() // 3628800L 58 | 20.factorial() // 2432902008176640000L 59 | ``` 60 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/FactorialTest.kt). 61 | 62 | # Numbers divisible and non-divisible by 63 | 64 | ```kotlin 65 | (1..1000).countNonDivisiveBy(2) // 500 66 | (1..1000).countNonDivisiveBy(3) // 777 67 | (1..1000).countNonDivisiveBy(2, 6, 13) // 462 68 | (1..1000).countNonDivisiveBy(3, 7, 11) // 520 69 | 70 | (1..1000).countDivisiveBy(2) // 500 71 | (1..1000).countDivisiveBy(3) // 333 72 | (1..1000).countDivisiveBy(2, 6, 13) // 538 73 | (1..1000).countDivisiveBy(3, 7, 11) // 480 74 | ``` 75 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/NumbersDivisibleTest.kt). 76 | 77 | # Splits of sets and numbers 78 | In Descrete Math there are two functions used to count number of splits: 79 | S(n, k) - Stirling function - number of splits of n different elements to k groups 80 | P(n, k) - number of splits of n identical elements to k groups 81 | 82 | ```kotlin 83 | (1..n).toSet().splitsNumber(1) // 1 84 | (1..n).toSet().splitsNumber(n) // 1 85 | setOf(1, 2, 3).splitsNumber(2) // 3 86 | setOf(1, 2, 3, 4).splitsNumber(2) // 7 87 | setOf(1, 2, 3, 4, 5).splitsNumber(3) // 25 88 | setOf(1, 2, 3, 4, 5, 6, 7).splitsNumber(4) // 350 89 | setOf(1, 2, 3).splits(2) // { { {1, 2}, {3} },{ {1, 3}, {2} },{ {3, 2}, {1} } } 90 | ``` 91 | 92 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/SetSplitTest.kt) 93 | 94 | ```kotlin 95 | n.splitsNumber(1) // 1 96 | n.splitsNumber(n) // 1 97 | 7.splitsNumber(4) // 3 98 | 11.splitsNumber(4) // 11 99 | 9.splitsNumber(5) // 5 100 | 13.splitsNumber(8) // 7 101 | ``` 102 | 103 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/NumberSplitTest.kt) 104 | 105 | # Iterable multiplication 106 | 107 | Multiplication of iterables returns iterable with pairs of each possible connections of elements from first and iterable: 108 | 109 | ```kotlin 110 | listOf(1, 2) * listOf("A", "B") // returns List> 111 | // [(1, "A"), (1, "B"), (2, "A"), (2, "B")] 112 | listOf('a', 'b') * listOf(1, 2) * listOf("A", "B") // returns List> 113 | // [ 114 | // ('a', 1, "A"), ('a', 1, "B"), 115 | // ('a', 2, "A"), ('a', 2, "B"), 116 | // ('b', 1, "A"), ('b', 1, "B"), 117 | // ('b', b, "A"), ('b', 2, "B") 118 | // ] 119 | ``` 120 | 121 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/IterableMultipliationTest.kt). 122 | 123 | # Cartesian product of lists 124 | 125 | Similar to iterable multiplication but produces sequence of lists: 126 | 127 | ```kotlin 128 | listOf('A', 'B', 'C', D).cartesianProduct(listOf('x', 'y')) // returns List> 129 | // [ 130 | // ['A', 'x'], 131 | // ['A', 'y'], 132 | // ['B', 'x'], 133 | // ['B', 'y'], 134 | // ['C', 'x'], 135 | // ['C', 'y'], 136 | // ['D', 'x'], 137 | // ['D', 'y'] 138 | // ] 139 | listOf(0, 1).cartesianProduct(repeat = 2) // returns List> 140 | // [ 141 | // [0, 0], 142 | // [0, 1], 143 | // [1, 0], 144 | // [1, 1] 145 | // ] 146 | listOf(1, 2).cartesianProduct(listOf("ABC")) // returns List> 147 | // [ 148 | // [1, "ABC"], 149 | // [2, "ABC"] 150 | // ] 151 | ``` 152 | 153 | More examples [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/CartesianProductTest.kt). 154 | 155 | # Java support 156 | 157 | Library is fully supporting usage from Java. All functions can be used as static function of DiscreteMath. For example: 158 | 159 | ```java 160 | DiscreteMath.permutationsNumber(set) 161 | DiscreteMath.permutationsNumber(list) 162 | DiscreteMath.factorial(10) // 3628800L 163 | ``` 164 | 165 | Returned list and sets are Java standard lists and sets. More examples of Java usage [here](https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit/blob/master/src/test/java/com/marcinmoskala/math/tests/JavaTest.java). 166 | 167 | # Install 168 | 169 | Gradle: 170 | ```groovy 171 | compile "com.marcinmoskala:DiscreteMathToolkit:1.0.3" 172 | ``` 173 | 174 | Maven: 175 | ``` 176 | 177 | com.marcinmoskala 178 | DiscreteMathToolkit 179 | 1.0.3 180 | 181 | ``` 182 | 183 | Jar to download together with sources and javadoc can be found on [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cmarcinmoskala). 184 | 185 | License 186 | ------- 187 | 188 | Copyright 2017 Marcin Moskała 189 | 190 | Licensed under the Apache License, Version 2.0 (the "License"); 191 | you may not use this file except in compliance with the License. 192 | You may obtain a copy of the License at 193 | 194 | http://www.apache.org/licenses/LICENSE-2.0 195 | 196 | Unless required by applicable law or agreed to in writing, software 197 | distributed under the License is distributed on an "AS IS" BASIS, 198 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 199 | See the License for the specific language governing permissions and 200 | limitations under the License. 201 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'kotlin' 2 | if (project.hasProperty("signing.keyId")) { 3 | apply plugin: 'signing' 4 | } 5 | apply plugin: 'maven-publish' 6 | apply plugin: "jacoco" 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | buildscript { 13 | ext.kotlin_version = '1.3.72' 14 | ext.junit_version = '5.6.1' 15 | ext.kotest_version = '4.0.6' 16 | repositories { 17 | mavenCentral() 18 | } 19 | dependencies { 20 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 21 | } 22 | } 23 | 24 | jacocoTestReport { 25 | reports { 26 | xml.enabled = true 27 | html.enabled = true 28 | } 29 | } 30 | 31 | check.dependsOn jacocoTestReport 32 | 33 | dependencies { 34 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 35 | testImplementation "org.junit.jupiter:junit-jupiter-api:$junit_version" 36 | testImplementation "org.junit.jupiter:junit-jupiter-engine:$junit_version" 37 | testImplementation "io.kotest:kotest-runner-junit5-jvm:$kotest_version" 38 | testImplementation "io.kotest:kotest-property-jvm:$kotest_version" 39 | } 40 | 41 | // Publishing 42 | 43 | test { 44 | // show standard out and standard error of the test JVM(s) on the console 45 | testLogging.showStandardStreams = true 46 | } 47 | 48 | task sourceJar(type: Jar) { 49 | classifier "sources" 50 | from sourceSets.main.allJava 51 | } 52 | 53 | task javadocJar(type: Jar, dependsOn: javadoc) { 54 | classifier "javadoc" 55 | from javadoc.destinationDir 56 | } 57 | 58 | artifacts { 59 | archives sourceJar, javadocJar 60 | } 61 | 62 | signing { 63 | sign configurations.archives 64 | } 65 | 66 | publishing { 67 | publications { 68 | mavenJava(MavenPublication) { 69 | customizePom(pom) 70 | 71 | groupId "com.marcinmoskala" 72 | artifactId "DiscreteMathToolkit" 73 | version '1.0.5' 74 | 75 | from components.java 76 | 77 | // create the sign pom artifact 78 | pom.withXml { 79 | def pomFile = file("${project.buildDir}/generated-pom.xml") 80 | writeTo(pomFile) 81 | def pomAscFile = signing.sign(pomFile).signatureFiles[0] 82 | artifact(pomAscFile) { 83 | classifier = null 84 | extension = 'pom.asc' 85 | } 86 | } 87 | 88 | artifact(sourceJar) { 89 | classifier = 'sources' 90 | } 91 | artifact(javadocJar) { 92 | classifier = 'javadoc' 93 | } 94 | 95 | // create the signed artifacts 96 | project.tasks.signArchives.signatureFiles.each { 97 | artifact(it) { 98 | def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ 99 | if (matcher.find()) { 100 | classifier = matcher.group(1) 101 | } else { 102 | classifier = null 103 | } 104 | extension = 'jar.asc' 105 | } 106 | } 107 | } 108 | } 109 | repositories { 110 | maven { 111 | url "https://oss.sonatype.org/service/local/staging/deploy/maven2" 112 | credentials { 113 | username sonatypeUsername 114 | password sonatypePassword 115 | } 116 | } 117 | } 118 | } 119 | 120 | def customizePom(pom) { 121 | pom.withXml { 122 | def root = asNode() 123 | 124 | root.dependencies.removeAll { dep -> 125 | dep.scope == "test" 126 | } 127 | 128 | root.children().last() + { 129 | resolveStrategy = Closure.DELEGATE_FIRST 130 | 131 | name 'DescreteMathToolkit' 132 | description 'Set of extensions for Kotlin that provides Discrete Math functionalities as an Kotlin extension functions.' 133 | url 'https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit' 134 | 135 | scm { 136 | connection 'scm:https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit' 137 | developerConnection 'scm:https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit' 138 | url 'https://github.com/MarcinMoskala/KotlinDiscreteMathToolkit' 139 | } 140 | 141 | licenses { 142 | license { 143 | name 'The Apache License, Version 2.0' 144 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 145 | } 146 | } 147 | 148 | developers { 149 | developer { 150 | id 'MarcinMoskala' 151 | name 'Marcin Moskala' 152 | email 'marcinmoskala@gmail.com' 153 | } 154 | } 155 | } 156 | } 157 | } 158 | 159 | model { 160 | tasks.generatePomFileForMavenJavaPublication { 161 | destination = file("$buildDir/generated-pom.xml") 162 | } 163 | tasks.publishMavenJavaPublicationToMavenLocal { 164 | dependsOn project.tasks.signArchives 165 | } 166 | tasks.publishMavenJavaPublicationToMavenRepository { 167 | dependsOn project.tasks.signArchives 168 | } 169 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcinMoskala/KotlinDiscreteMathToolkit/17a7329af042c5de232051027ec1155011d57da8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 08 23:32:02 CEST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/CartesianProductExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | 4 | package com.marcinmoskala.math 5 | 6 | /** 7 | * Cartesian product of a list with itself, specify the number of repetitions with the optional repeat keyword argument. 8 | * For example, A.cartesianProduct(repeat=4) means the same as A.cartesianProduct(A, A, A). 9 | * Throws an [IllegalArgumentException]: if [repeat] is less or equals to 0 10 | * Throws an [IllegalArgumentException]: if size of result should exceeds [Int.MAX_VALUE] 11 | */ 12 | fun List.cartesianProduct(repeat: Int = 2): Sequence> { 13 | require(repeat > 0) { "Parameter repeat should be greater than 0" } 14 | return product(*Array(repeat) { this }) 15 | } 16 | 17 | /** 18 | * Cartesian product of lists. 19 | * Throws an [IllegalArgumentException]: if size of result should exceeds [Int.MAX_VALUE] 20 | */ 21 | fun List.cartesianProduct(vararg lists: List): Sequence> = 22 | product(this, *lists) 23 | 24 | private fun product(vararg iterables: List): Sequence> = sequence { 25 | 26 | require(iterables.map { it.size.toLong() }.reduce(Long::times) <= Int.MAX_VALUE) { 27 | "Cartesian product function can produce result whose size does not exceed Int.MAX_VALUE" 28 | } 29 | 30 | val numberOfIterables = iterables.size 31 | val lstLengths = ArrayList() 32 | val lstRemaining = ArrayList(listOf(1)) 33 | 34 | iterables.reversed().forEach { 35 | lstLengths.add(0, it.size) 36 | lstRemaining.add(0, it.size * lstRemaining[0]) 37 | } 38 | 39 | val nProducts = lstRemaining.removeAt(0) 40 | 41 | (0 until nProducts).forEach { product -> 42 | val result = ArrayList() 43 | (0 until numberOfIterables).forEach { iterableIndex -> 44 | val elementIndex = product / lstRemaining[iterableIndex] % lstLengths[iterableIndex] 45 | result.add(iterables[iterableIndex][elementIndex]) 46 | } 47 | yield(result.toList()) 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/CombinationsExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | /** 6 | * In mathematics, a combination is a way of selecting items from a collection, such that (unlike permutations) the 7 | * order of selection does not matter. 8 | * 9 | * For set {1, 2, 3}, 2 elements combinations are {1, 2}, {2, 3}, {1, 3}. 10 | * All possible combinations is called 'powerset' and can be found as an 11 | * extension function for set under this name 12 | */ 13 | fun Set.combinations(combinationSize: Int): Set> = when { 14 | combinationSize < 0 -> throw Error("combinationSize cannot be smaller then 0. It is equal to $combinationSize") 15 | combinationSize == 0 -> setOf(setOf()) 16 | combinationSize >= size -> setOf(toSet()) 17 | else -> powerset() 18 | .filter { it.size == combinationSize } 19 | .toSet() 20 | } 21 | 22 | fun Set.combinationsNumber(combinationSize: Int): Long = when { 23 | combinationSize < 0 -> throw Error("combinationSize cannot be smaller then 0. It is equal to $combinationSize") 24 | combinationSize >= size || combinationSize == 0 -> 1 25 | else -> size.factorial() / (combinationSize.factorial() * (size - combinationSize).factorial()) 26 | } 27 | 28 | fun Set.combinationsWithRepetitions(combinationSize: Int): Set> = when { 29 | combinationSize < 0 -> throw Error("combinationSize cannot be smaller then 0. It is equal to $combinationSize") 30 | combinationSize == 0 -> setOf(mapOf()) 31 | else -> combinationsWithRepetitions(combinationSize - 1) 32 | .flatMap { subset -> this.map { subset + (it to (subset.getOrElse(it) { 0 } + 1)) } } 33 | .toSet() 34 | } 35 | 36 | fun Set.combinationsWithRepetitionsNumber(combinationSize: Int): Long = when { 37 | combinationSize < 0 -> throw Error("combinationSize cannot be smaller then 0. It is equal to $combinationSize") 38 | combinationSize == 0 -> 1 39 | else -> (size + combinationSize - 1).factorial() / (combinationSize.factorial() * (size - 1).factorial()) 40 | } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/FactorialFun.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | fun Int.factorial(): Long = (1..this).product() -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/IterableMultiplication.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | operator fun List.times(l: List): List> = flatMap { e1 -> l.map { e2 -> e1 to e2 } } 6 | 7 | @JvmName("listOfPairTimes") 8 | operator fun List>.times(l: List): List> = flatMap { (e1, e2) -> l.map { e3 -> Triple(e1, e2, e3) } } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/NumSplitFunc.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | // Number of splits of n identical elements to k groups 6 | fun Int.splitsNumber(groupsNum: Int): Int = when { 7 | groupsNum < 0 -> throw Error("groupsNum cannot be smaller then 0. It is now equal to $groupsNum") 8 | groupsNum == 0 -> if (this == 0) 1 else 0 9 | groupsNum == 1 || groupsNum == this -> 1 10 | groupsNum > this -> 0 11 | else -> (1..groupsNum).sumBy { i -> (this - groupsNum).splitsNumber(i) } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/NumbersDivisible.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | fun IntRange.divisiveBy(vararg numbers: Int) 6 | = filter { n -> numbers.any { n % it == 0 } } 7 | 8 | fun IntRange.countDivisiveBy(vararg numbers: Int) 9 | = count { n -> numbers.any { n % it == 0 } } 10 | 11 | fun IntRange.nonDivisiveBy(vararg numbers: Int) 12 | = filter { n -> numbers.all { n % it != 0 } } 13 | 14 | fun IntRange.countNonDivisiveBy(vararg numbers: Int) 15 | = count { n -> numbers.all { n % it != 0 } } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/PermutationsExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | /** 6 | * Permutations are all different ways to arrange elements from some collection (https://en.wikipedia.org/wiki/Permutation). 7 | * For sets it's number is n!, for lists it is n! / (n1! * n2! * ...) where n1, n2... are numbers elements that are the same. 8 | */ 9 | 10 | /* This function returns number of all permutations of elements from set. It is equal to n! where n is size of set. */ 11 | fun Set.permutationsNumber(): Long = size.factorial() 12 | 13 | /* This function returns number of all permutations of elements from list. It is equal to n! / (n1! * n2! * ...) where n1, n2... are numbers elements that are the same. */ 14 | fun List.permutationsNumber(): Long = if (size < 1) 1L else size.factorial() / groupBy { it }.map { it.value.size.factorial() }.product() 15 | 16 | /* This function returns all permutations of elements from set. These are different ways to arrange elements from this list. */ 17 | fun Set.permutations(): Set> = toList().permutations() 18 | 19 | /* This function returns all permutations of elements from list. These are different ways to arrange elements from this list. */ 20 | fun List.permutations(): Set> = when { 21 | isEmpty() -> setOf() 22 | size == 1 -> setOf(listOf(get(0))) 23 | else -> { 24 | val element = get(0) 25 | drop(1).permutations() 26 | .flatMap { sublist -> (0..sublist.size).map { i -> sublist.plusAt(i, element) } } 27 | .toSet() 28 | } 29 | } 30 | 31 | internal fun List.plusAt(index: Int, element: T): List = when { 32 | index !in 0..size -> throw Error("Cannot put at index $index because size is $size") 33 | index == 0 -> listOf(element) + this 34 | index == size -> this + element 35 | else -> dropLast(size - index) + element + drop(index) 36 | } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/Power.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | 4 | package com.marcinmoskala.math 5 | 6 | import java.math.BigDecimal 7 | import java.math.BigInteger 8 | 9 | infix fun Number.pow(power: Number): Double = 10 | Math.pow(this.toDouble(), power.toDouble()) 11 | 12 | infix fun Int.pow(power: Int): Int = 13 | Math.pow(this.toDouble(), power.toDouble()).toInt() -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/PowersetExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | fun Collection.powerset(): Set> = powerset(this, setOf(setOf())) 6 | 7 | private tailrec fun powerset(left: Collection, acc: Set>): Set> = when { 8 | left.isEmpty() -> acc 9 | else ->powerset(left.drop(1), acc + acc.map { it + left.first() }) 10 | } 11 | 12 | val Collection.powersetSize: Int 13 | get() = 2.pow(size) -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/ProductExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | fun Iterable.product(): Long = fold(1L) { a, n -> a * n } 6 | 7 | @JvmName("productLong") 8 | fun Collection.product(): Long = fold(1L) { a, n -> a * n } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/SetSplitFunc.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | // Stirling function - number of splits of n different elements to k groups 6 | fun Set.splitsNumber(groupsNum: Int): Int = when { 7 | groupsNum < 0 -> throw Error("groupsNum cannot be smaller then 0. It is equal to $groupsNum") 8 | groupsNum == 0 -> if (isEmpty()) 1 else 0 9 | groupsNum == 1 || groupsNum == size -> 1 10 | groupsNum > size -> 0 11 | else -> (1..(size - 1)).toSet().splitsNumber(groupsNum - 1) + groupsNum * (1..(size - 1)).toSet().splitsNumber(groupsNum) 12 | } 13 | 14 | // Takes set of elements and returns set of splits and each of them is set of sets 15 | fun Set.splits(groupsNum: Int): Set>> = when { 16 | groupsNum < 0 -> throw Error("groupsNum cannot be smaller then 0. It is equal to $groupsNum") 17 | groupsNum == 0 -> if (isEmpty()) setOf(emptySet()) else emptySet() 18 | groupsNum == 1 -> setOf(setOf(this)) 19 | groupsNum == size -> setOf(this.map { setOf(it) }.toSet()) 20 | groupsNum > size -> emptySet() 21 | else -> setOf>>() 22 | .plus(splitsWhereFirstIsAlone(groupsNum)) 23 | .plus(splitsForFirstIsInAllGroups(groupsNum)) 24 | } 25 | 26 | private fun Set.splitsWhereFirstIsAlone(groupsNum: Int): List>> = this 27 | .minusElement(first()) 28 | .splits(groupsNum - 1) 29 | .map { it.plusElement(setOf(first())) } 30 | 31 | private fun Set.splitsForFirstIsInAllGroups(groupsNum: Int): List>> = this 32 | .minusElement(first()) 33 | .splits(groupsNum) 34 | .flatMap { split -> split.map { group -> split.minusElement(group).plusElement(group + first()) } } -------------------------------------------------------------------------------- /src/main/java/com/marcinmoskala/math/SublistsBySplittersExt.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("DiscreteMath") 2 | @file:JvmMultifileClass 3 | package com.marcinmoskala.math 4 | 5 | fun List.sublistsBySplitters(isSplitter: (T) -> Boolean): List> = when { 6 | isEmpty() -> listOf(listOf()) 7 | isSplitter(last()) -> sublistFromRest(isSplitter) 8 | .flatMap { listOf(it + last(), it) } 9 | else -> sublistFromRest(isSplitter) 10 | .map { it + last() } 11 | } 12 | 13 | private fun List.sublistFromRest(isSplitter: (T) -> Boolean) = dropLast(1).sublistsBySplitters(isSplitter) -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/CartesianProductPropertyTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.cartesianProduct 4 | import io.kotest.core.spec.style.StringSpec 5 | import io.kotest.property.Arb 6 | import io.kotest.property.arbitrary.int 7 | import io.kotest.property.arbitrary.list 8 | import io.kotest.property.forAll 9 | 10 | 11 | internal class CartesianProductPropertyTest : StringSpec({ 12 | 13 | val intListGen = Arb.list( 14 | Arb.int(0..100), 15 | 2..5 16 | ) 17 | 18 | val listOfIntListsGen = Arb.list( 19 | intListGen, 20 | 2..5 21 | ) 22 | 23 | "output product size is product of sizes of inputs" { 24 | forAll(listOfIntListsGen) { list -> 25 | val head = list[0] 26 | val tail = list.drop(1).toTypedArray() 27 | head.cartesianProduct(*tail).toList().size == list.map { it.size }.reduce(Int::times) 28 | } 29 | } 30 | 31 | "cartesian product with repeat of empty list is empty list" { 32 | forAll(Arb.int(2..10)) { repeat -> 33 | emptyList().cartesianProduct(repeat).toList().isEmpty() 34 | } 35 | } 36 | 37 | "cartesian product of empty list and non empty list is empty list" { 38 | forAll(intListGen) { list -> 39 | emptyList().cartesianProduct(list).toList().isEmpty() 40 | } 41 | } 42 | 43 | "cartesian product of non empty list and empty list is empty list" { 44 | forAll(intListGen) { list -> 45 | list.cartesianProduct(emptyList()).toList().isEmpty() 46 | } 47 | } 48 | 49 | "set of elements in product is the same as in input" { 50 | forAll(listOfIntListsGen) { list -> 51 | val head = list[0] 52 | val tail = list.drop(1).toTypedArray() 53 | head.cartesianProduct(*tail).toList().flatten().toSet() == 54 | list.flatten().toSet() 55 | } 56 | } 57 | }) -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/CartesianProductTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.cartesianProduct 4 | import io.kotest.property.Arb 5 | import io.kotest.property.arbitrary.int 6 | import io.kotest.property.arbitrary.next 7 | import org.junit.jupiter.api.Assertions.assertThrows 8 | import org.junit.jupiter.api.Test 9 | import org.junit.jupiter.api.Assertions.assertEquals 10 | 11 | 12 | internal class CartesianProductTest { 13 | 14 | @Test 15 | fun `cartesian product with size more than MAX_INT throws`() { 16 | assertThrows(IllegalArgumentException::class.java) { 17 | listOf(1, 2, 3, 5, 6, 7, 8, 9, 0).cartesianProduct(10).toList() 18 | } 19 | } 20 | 21 | @Test 22 | fun `cartesian product with repeat less than 1 throws`() { 23 | val repeat = Arb.int(-100..0).next() 24 | assertThrows(IllegalArgumentException::class.java) { 25 | listOf(1, 2, 3).cartesianProduct(repeat) 26 | } 27 | } 28 | 29 | @Test 30 | fun `cartesian product with repeat = 1`() { 31 | val actual = listOf(1, 2, 3).cartesianProduct(1).toList() 32 | val expected = listOf( 33 | listOf(1), 34 | listOf(2), 35 | listOf(3) 36 | ) 37 | assertEquals(expected, actual) 38 | } 39 | 40 | @Test 41 | fun `cartesian product with repeat`() { 42 | val actual = listOf(1, 2, 3).cartesianProduct(2).toList() 43 | val expected = listOf( 44 | listOf(1, 1), 45 | listOf(1, 2), 46 | listOf(1, 3), 47 | listOf(2, 1), 48 | listOf(2, 2), 49 | listOf(2, 3), 50 | listOf(3, 1), 51 | listOf(3, 2), 52 | listOf(3, 3) 53 | ) 54 | assertEquals(expected, actual) 55 | } 56 | 57 | @Test 58 | fun `cartesian product of different sizes`() { 59 | val actual = listOf(1, 2, 3).cartesianProduct(listOf(8, 9)).toList() 60 | val expected = listOf( 61 | listOf(1, 8), 62 | listOf(1, 9), 63 | listOf(2, 8), 64 | listOf(2, 9), 65 | listOf(3, 8), 66 | listOf(3, 9) 67 | ) 68 | assertEquals(expected, actual) 69 | } 70 | 71 | @Test 72 | fun `cartesian product of same sizes`() { 73 | val actual = listOf(1, 2).cartesianProduct(listOf(8, 9)).toList() 74 | val expected = listOf( 75 | listOf(1, 8), 76 | listOf(1, 9), 77 | listOf(2, 8), 78 | listOf(2, 9) 79 | ) 80 | assertEquals(expected, actual) 81 | } 82 | 83 | @Test 84 | fun `cartesian product of 3 lists`() { 85 | val actual = listOf(1, 2).cartesianProduct( 86 | listOf(3, 4), 87 | listOf(5, 6) 88 | ).toList() 89 | val expected = listOf( 90 | listOf(1, 3, 5), 91 | listOf(1, 3, 6), 92 | listOf(1, 4, 5), 93 | listOf(1, 4, 6), 94 | listOf(2, 3, 5), 95 | listOf(2, 3, 6), 96 | listOf(2, 4, 5), 97 | listOf(2, 4, 6) 98 | ) 99 | assertEquals(expected, actual) 100 | } 101 | 102 | @Test 103 | fun `cartesian product of 3 lists with different size`() { 104 | val actual = listOf(0, 1, 2).cartesianProduct( 105 | listOf(3, 4), 106 | listOf(5, 6) 107 | ).toList() 108 | val expected = listOf( 109 | listOf(0, 3, 5), 110 | listOf(0, 3, 6), 111 | listOf(0, 4, 5), 112 | listOf(0, 4, 6), 113 | listOf(1, 3, 5), 114 | listOf(1, 3, 6), 115 | listOf(1, 4, 5), 116 | listOf(1, 4, 6), 117 | listOf(2, 3, 5), 118 | listOf(2, 3, 6), 119 | listOf(2, 4, 5), 120 | listOf(2, 4, 6) 121 | ) 122 | assertEquals(expected, actual) 123 | } 124 | 125 | @Test 126 | fun `cartesian product of 2 lists with different types`() { 127 | val expected = listOf( 128 | listOf("A", 1), 129 | listOf("A", 2), 130 | listOf("A", 3), 131 | listOf("B", 1), 132 | listOf("B", 2), 133 | listOf("B", 3) 134 | ) 135 | val actual = listOf("A", "B").cartesianProduct(listOf(1, 2, 3)).toList() 136 | assertEquals(expected, actual) 137 | } 138 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/CombinationTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.combinations 4 | import com.marcinmoskala.math.combinationsNumber 5 | import org.junit.jupiter.api.Assertions.assertEquals 6 | import org.junit.jupiter.api.Test 7 | 8 | internal class CombinationTest { 9 | 10 | @Test 11 | fun `combinations function is throwing error when asked for subsets of size smaller then 0`() { 12 | val set = setOf(1, 2, 3, 4) 13 | for (subsetSize in -10..-1) { 14 | assertIsThrowingError { set.combinations(subsetSize) } 15 | } 16 | } 17 | 18 | @Test fun `combinationsNumber function is throwing error when asked for subsets of size smaller then 0`() { 19 | val set = setOf(1, 2, 3, 4) 20 | for (subsetSize in -10..-1) { 21 | assertIsThrowingError { set.combinationsNumber(subsetSize) } 22 | } 23 | } 24 | 25 | @Test fun `Test combinationsNumber for Sets with different sizes`() { 26 | val set = setOf(1, 2, 3, 4) 27 | val subsetSizeToCombinationNumber = mapOf( 28 | 0 to 1L, 29 | 1 to 4L, 30 | 2 to 6L, 31 | 3 to 4L, 32 | 4 to 1L, 33 | 5 to 1L 34 | ) 35 | for ((subsetSize, expectedCombinationNumber) in subsetSizeToCombinationNumber) { 36 | assertEquals(expectedCombinationNumber, set.combinationsNumber(subsetSize)) 37 | } 38 | } 39 | 40 | @Test fun `Test combinations for Sets with different sizes`() { 41 | val set = setOf(1, 2, 3, 4) 42 | val sizeToCombinations = mapOf( 43 | 0 to setOf(setOf()), 44 | 1 to setOf(setOf(1), setOf(2), setOf(3), setOf(4)), 45 | 2 to setOf(setOf(1, 2), setOf(2, 3), setOf(3, 4), setOf(1, 3), setOf(2, 4), setOf(1, 4)), 46 | 3 to setOf(setOf(1, 2, 3), setOf(1, 2, 4), setOf(1, 3, 4), setOf(2, 3, 4)), 47 | 4 to setOf(setOf(1, 2, 3, 4)), 48 | 5 to setOf(setOf(1, 2, 3, 4)) 49 | ) 50 | for ((subsetSize, expectedCombinations) in sizeToCombinations) { 51 | assertEquals(expectedCombinations, set.combinations(subsetSize)) 52 | } 53 | } 54 | 55 | @Test fun `Test combinations size and combinationsNumber correctness`() { 56 | val set = (1..6).toSet() 57 | (1..7).forEach { i -> assertEquals(set.combinationsNumber(i), set.combinations(i).size.toLong()) } 58 | } 59 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/CombinationWithRepetitionTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.combinationsWithRepetitions 4 | import com.marcinmoskala.math.combinationsWithRepetitionsNumber 5 | import org.junit.jupiter.api.Assertions.assertEquals 6 | import org.junit.jupiter.api.Test 7 | 8 | internal class CombinationWithRepetitionTest { 9 | 10 | @Test fun `combinationsWithRepetitions function is throwing error when asked for subsets of size smaller then 0`() { 11 | val set = setOf(1, 2, 3, 4) 12 | for (subsetSize in -10..-1) { 13 | assertIsThrowingError { set.combinationsWithRepetitions(subsetSize) } 14 | } 15 | } 16 | 17 | @Test fun `combinationsWithRepetitionsNumber function is throwing error when asked for subsets of size smaller then 0`() { 18 | val set = setOf(1, 2, 3, 4) 19 | for (subsetSize in -10..-1) { 20 | assertIsThrowingError { set.combinationsWithRepetitionsNumber(subsetSize) } 21 | } 22 | } 23 | 24 | @Test fun `Test combinationsWithRepetitionsNumber for Sets with different sizes`() { 25 | val set = setOf(1, 2, 3) 26 | val subsetSizeToCombinationNumber = mapOf( 27 | 0 to 1L, 28 | 1 to 3L, 29 | 2 to 6L, 30 | 3 to 10L, 31 | 4 to 15L, 32 | 5 to 21L 33 | ) 34 | for ((subsetSize, expectedCombinationNumber) in subsetSizeToCombinationNumber) { 35 | assertEquals(expectedCombinationNumber, set.combinationsWithRepetitionsNumber(subsetSize)) 36 | } 37 | } 38 | 39 | @Test fun `Simple combinationsWithRepetitions test`() { 40 | val set = setOf(1, 2, 3) 41 | val sizeToCombinations = mapOf>>( 42 | 0 to setOf(mapOf()), 43 | 1 to setOf(mapOf(1 to 1), mapOf(2 to 1), mapOf(3 to 1)), 44 | 2 to setOf(mapOf(1 to 1, 2 to 1), mapOf(2 to 1, 3 to 1), mapOf(1 to 1, 3 to 1), mapOf(1 to 2), mapOf(2 to 2), mapOf(3 to 2)) 45 | ) 46 | for ((subsetSize, expectedCombinations) in sizeToCombinations) { 47 | assertEquals(expectedCombinations, set.combinationsWithRepetitions(subsetSize)) 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/FactorialTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.factorial 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | internal class FactorialTest { 8 | 9 | @Test fun `Test factorial results`() { 10 | val numberWithFactorial = mapOf( 11 | 0 to 1L, 12 | 1 to 1L, 13 | 2 to 2L, 14 | 3 to 6L, 15 | 4 to 24L, 16 | 10 to 3628800L, 17 | 15 to 1307674368000L, 18 | 20 to 2432902008176640000L 19 | ) 20 | for ((i, factorialResult) in numberWithFactorial) { 21 | assertEquals(factorialResult, i.factorial()) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/IterableMultipliationTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.times 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | internal class IterableMultipliationTest { 8 | 9 | @Test fun `When one list empty then multiplication is also returning empty`() { 10 | assertEquals(listOf(), listOf() * listOf()) 11 | assertEquals(listOf(), listOf(1) * listOf()) 12 | assertEquals(listOf(), listOf() * listOf(1)) 13 | assertEquals(listOf(), listOf(1, 2) * listOf()) 14 | } 15 | 16 | @Test fun `When size of one list is 1 then multiplication of it with other list returns list with size of second with element of it paired with element from other list`() { 17 | assertEquals(listOf("A" to 1, "A" to 2), listOf("A") * listOf(1, 2)) 18 | assertEquals(listOf("A" to 1, "A" to 2, "A" to 3), listOf("A") * listOf(1, 2, 3)) 19 | assertEquals(listOf("A" to 1, "A" to 2, "A" to 2), listOf("A") * listOf(1, 2, 2)) 20 | } 21 | 22 | @Test fun `Simple list multiplication returns each combination of pairs from lists`() { 23 | assertEquals(listOf("A" to 1, "A" to 2, "B" to 1, "B" to 2), listOf("A", "B") * listOf(1, 2)) 24 | } 25 | 26 | @Test fun `Multiplication of tree lists is returning triple with each combination of each lists`() { 27 | assertEquals(listOf( 28 | Triple("A", 1, 'a'), 29 | Triple("A", 1, 'b'), 30 | Triple("A", 2, 'a'), 31 | Triple("A", 2, 'b'), 32 | Triple("B", 1, 'a'), 33 | Triple("B", 1, 'b'), 34 | Triple("B", 2, 'a'), 35 | Triple("B", 2, 'b') 36 | ), listOf("A", "B") * listOf(1, 2) * listOf('a', 'b')) 37 | } 38 | 39 | @Test fun `Size of result of list multipication is equeal to multiplication of list sizes`() { 40 | val list1 = (1..5).toList() 41 | val list2 = (1..10).toList() 42 | val list3 = (1..25).toList() 43 | assertEquals(list1.size * list2.size, (list1 * list2).size) 44 | assertEquals(list1.size * list3.size, (list1 * list3).size) 45 | assertEquals(list2.size * list3.size, (list2 * list3).size) 46 | assertEquals(list1.size * list1.size, (list1 * list1).size) 47 | assertEquals(list2.size * list2.size, (list2 * list2).size) 48 | assertEquals(list3.size * list3.size, (list3 * list3).size) 49 | assertEquals(list1.size * list2.size * list3.size, (list1 * list2 * list3).size) 50 | assertEquals(list1.size * list1.size * list1.size, (list1 * list1 * list1).size) 51 | assertEquals(list2.size * list2.size * list2.size, (list2 * list2 * list2).size) 52 | assertEquals(list3.size * list3.size * list3.size, (list3 * list3 * list3).size) 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/JavaTest.java: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests; 2 | 3 | import com.marcinmoskala.math.DiscreteMath; 4 | import org.junit.jupiter.api.Assertions; 5 | import org.junit.jupiter.api.BeforeAll; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Set; 12 | 13 | public class JavaTest { 14 | 15 | private static Set smallSet = new HashSet<>(); 16 | private static List smallList = new ArrayList<>(); 17 | 18 | @BeforeAll 19 | static public void setUp() { 20 | smallSet.add(0); 21 | smallSet.add(1); 22 | smallSet.add(2); 23 | smallList.add(0); 24 | smallList.add(1); 25 | smallList.add(1); 26 | } 27 | 28 | @Test 29 | public void permutationsTest() { 30 | Assertions.assertEquals(6, DiscreteMath.permutationsNumber(smallSet)); 31 | Assertions.assertEquals(3, DiscreteMath.permutationsNumber(smallList)); 32 | } 33 | 34 | @Test 35 | public void combinationsTest() { 36 | Assertions.assertEquals(3, DiscreteMath.combinationsNumber(smallSet, 2)); 37 | Assertions.assertEquals(6, DiscreteMath.combinationsWithRepetitionsNumber(smallSet, 2)); 38 | } 39 | 40 | @Test 41 | public void powersetTest() { 42 | Assertions.assertEquals(8, DiscreteMath.getPowersetSize(smallSet)); 43 | } 44 | 45 | @Test 46 | public void productTest() { 47 | Assertions.assertEquals(0, DiscreteMath.product(smallList)); 48 | } 49 | 50 | @Test 51 | public void factorialTest() { 52 | Assertions.assertEquals(3628800L, DiscreteMath.factorial(10)); 53 | } 54 | 55 | @Test 56 | public void splitsOfSetTest() { 57 | Assertions.assertEquals(3, DiscreteMath.splitsNumber(smallSet, 2)); 58 | } 59 | 60 | @Test 61 | public void splitsOfNumberTest() { 62 | Assertions.assertEquals(3, DiscreteMath.splitsNumber(7, 4)); 63 | } 64 | 65 | @Test 66 | public void iterableMultiplicationTest() { 67 | Assertions.assertEquals(smallList.size() * smallList.size(), DiscreteMath.times(smallList, smallList).size()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/NumberSplitTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.splitsNumber 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | internal class NumberSplitTest { 8 | 9 | @Test fun `splitsNumber function for number is throwing error when asked for groupsNum of size smaller then 0`() { 10 | for (groupsNum in -10..-1) { 11 | for (num in 0..10) { 12 | assertIsThrowingError { num.splitsNumber(groupsNum) } 13 | } 14 | } 15 | } 16 | 17 | @Test 18 | fun `n number can be only one way splitted to one or n components`() { 19 | for (n in 1..100) { 20 | assertEquals(1, n.splitsNumber(1)) 21 | assertEquals(1, n.splitsNumber(n)) 22 | } 23 | } 24 | 25 | @Test 26 | fun `For 0 splits, number splits function is returning 1 for 0 and 0 otherwise`() { 27 | assertEquals(1, 0.splitsNumber(0)) 28 | for (n in 1..100) { 29 | assertEquals(0, n.splitsNumber(0)) 30 | } 31 | } 32 | 33 | @Test 34 | fun `Number splits function is correct according to recurrence definition`() { 35 | for (n in 1..10) { 36 | for (k in 1..(n - 1)) { 37 | assertEquals(n.splitsNumber(k), (1..k).sumBy { i -> (n - k).splitsNumber(i) }) 38 | } 39 | } 40 | } 41 | 42 | @Test 43 | fun `Simple number splits examples are calculated correctly`() { 44 | assertEquals(3, 7.splitsNumber(4)) 45 | assertEquals(11, 11.splitsNumber(4)) 46 | assertEquals(5, 9.splitsNumber(5)) 47 | assertEquals(7, 13.splitsNumber(8)) 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/NumbersDivisibleTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.countDivisiveBy 4 | import com.marcinmoskala.math.countNonDivisiveBy 5 | import com.marcinmoskala.math.divisiveBy 6 | import com.marcinmoskala.math.nonDivisiveBy 7 | import org.junit.jupiter.api.Assertions.assertEquals 8 | import org.junit.jupiter.api.Test 9 | 10 | internal class NumbersDivisibleTest { 11 | 12 | @Test fun `Simple count divisible test`() { 13 | assertEquals(462, (1..1000).countNonDivisiveBy(2, 6, 13)) 14 | assertEquals(520, (1..1000).countNonDivisiveBy(3, 7, 11)) 15 | assertEquals(768, (1..1000).countNonDivisiveBy(6, 9, 33)) 16 | } 17 | 18 | @Test fun `Simple count nondivisible test`() { 19 | assertEquals(1000 - 462, (1..1000).countDivisiveBy(2, 6, 13)) 20 | assertEquals(1000 - 520, (1..1000).countDivisiveBy(3, 7, 11)) 21 | assertEquals(1000 - 768, (1..1000).countDivisiveBy(6, 9, 33)) 22 | } 23 | 24 | @Test fun `Simple divisible test`() { 25 | assertEquals(listOf(1, 5, 7), (1..10).nonDivisiveBy(2, 3)) 26 | } 27 | 28 | @Test fun `Simple nondivisible test`() { 29 | assertEquals(listOf(2, 3, 4, 6, 8, 9, 10), (1..10).divisiveBy(2, 3)) 30 | } 31 | 32 | @Test fun `Divisible (and non divisible) size and count matches`() { 33 | val r = (1..100) 34 | for(i in 1..10) { 35 | for(j in 1..10) { 36 | assertEquals(r.countDivisiveBy(i, j), r.divisiveBy(i, j).size) 37 | assertEquals(r.countNonDivisiveBy(i, j), r.nonDivisiveBy(i, j).size) 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/PermutationTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.permutations 4 | import com.marcinmoskala.math.permutationsNumber 5 | import com.marcinmoskala.math.plusAt 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.api.Test 8 | 9 | internal class PermutationTest { 10 | 11 | @Test fun `Test permutation numbers for Sets with different sizes`() { 12 | val setSizeToPermutations = mapOf( 13 | 0 to 1L, 14 | 1 to 1L, 15 | 2 to 2L, 16 | 3 to 6L, 17 | 4 to 24L 18 | ) 19 | for ((setSize, expectedNumber) in setSizeToPermutations) { 20 | val set = (1..setSize).toSet() 21 | assertEquals(expectedNumber, set.permutationsNumber()) 22 | } 23 | } 24 | 25 | @Test fun `Test permutation numbers for Lists with different sizes and different elements`() { 26 | val listSizeToPermutations = mapOf( 27 | 0 to 1L, 28 | 1 to 1L, 29 | 2 to 2L, 30 | 3 to 6L, 31 | 4 to 24L 32 | ) 33 | for ((listSize, expectedNumber) in listSizeToPermutations) { 34 | val set = (1..listSize).toList() 35 | assertEquals(expectedNumber, set.permutationsNumber()) 36 | } 37 | } 38 | 39 | @Test fun `Test permutation numbers for Lists with different sizes and same elements`() { 40 | val listToPermutations = mapOf( 41 | listOf(1, 1, 1, 1) to 1L, 42 | listOf(1, 1, 2, 2) to 6L, 43 | listOf(1, 1, 1, 2) to 4L 44 | ) 45 | for ((list, expectedNumber) in listToPermutations) { 46 | assertEquals(expectedNumber, list.permutationsNumber()) 47 | } 48 | } 49 | 50 | @Test fun `Get all permutations for different elements`() { 51 | val setToPermutations = mapOf( 52 | setOf() to setOf>(), 53 | setOf(1, 2) to setOf(listOf(1, 2), listOf(2, 1)), 54 | setOf(1, 2, 3) to setOf(listOf(1, 2, 3), listOf(2, 1, 3), listOf(1, 3, 2), listOf(2, 3, 1), listOf(3, 1, 2), listOf(3, 2, 1)) 55 | ) 56 | for ((set, allExpectedPermutations) in setToPermutations) { 57 | assertEquals(allExpectedPermutations, set.permutations()) 58 | } 59 | } 60 | 61 | @Test fun `Check permutations number in allPermutations for bigger numbers`() { 62 | val set = (1..5).toSet() 63 | assertEquals(set.permutationsNumber(), set.permutations().size.toLong()) 64 | } 65 | 66 | @Test fun `Simple plusAt tests`() { 67 | val list = listOf(1,2,3) 68 | assertIsThrowingError { list.plusAt(-1, 100) } 69 | assertIsThrowingError { list.plusAt(-100, 100) } 70 | assertIsThrowingError { list.plusAt(1000, 100) } 71 | assertEquals(listOf(100, 1, 2, 3), list.plusAt(0, 100)) 72 | assertEquals(listOf(1, 100, 2, 3), list.plusAt(1, 100)) 73 | assertEquals(listOf(1, 2, 3, 100), list.plusAt(3, 100)) 74 | } 75 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/PowerTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.pow 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Assertions.assertTrue 6 | import org.junit.jupiter.api.Test 7 | 8 | @Suppress("USELESS_IS_CHECK") 9 | internal class PowerTest { 10 | 11 | @Test 12 | fun `Power for Number tests`() { 13 | assertEquals(4.0, (2 as Number).pow(2)) 14 | assertEquals(81.0, (3 as Number).pow(4)) 15 | assertEquals(100000.0, (10 as Number).pow(5)) 16 | assertTrue((10 as Number).pow(5) is Double) 17 | } 18 | 19 | @Test 20 | fun `Power for Int tests`() { 21 | assertEquals(4, 2.pow(2)) 22 | assertEquals(81, 3.pow(4)) 23 | assertEquals(100000, 10.pow(5)) 24 | assertTrue(10.pow(5) is Int) 25 | } 26 | 27 | @Test 28 | fun `Power for Double tests`() { 29 | assertEquals(4.0, 2.0.pow(2)) 30 | assertEquals(81.0, 3.0.pow(4)) 31 | assertEquals(100000.0, 10.0.pow(5)) 32 | assertTrue(2.0.pow(5) is Double) 33 | } 34 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/PowersetTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.pow 4 | import com.marcinmoskala.math.powerset 5 | import com.marcinmoskala.math.powersetSize 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.api.Test 8 | 9 | internal class PowersetTest { 10 | 11 | @Test fun `Sublists from empty list is only empty list`() { 12 | val emptyList = setOf() 13 | assertEquals(setOf(emptyList), emptyList.powerset()) 14 | } 15 | 16 | @Test 17 | fun `Powerset simple example test`() { 18 | val set = setOf( 19 | setOf(1, 2, 3), 20 | setOf(1, 2), 21 | setOf(1, 3), 22 | setOf(2, 3), 23 | setOf(1), 24 | setOf(2), 25 | setOf(3), 26 | setOf()) 27 | assertEquals(set, setOf(1, 2, 3).powerset()) 28 | } 29 | 30 | @Test 31 | fun `Size of n element set powerset is 2^n`() { 32 | for(n in 1..6) { 33 | val set = (1..n).toSet() 34 | val size = 2.pow(n) 35 | assertEquals(size, set.powerset().size) 36 | assertEquals(size, set.powersetSize) 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/ProductTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.product 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | internal class ProductTest { 8 | 9 | @Test 10 | fun `Product of empty IntRange is 1`() { 11 | assertEquals(1, (0..-1).product()) 12 | } 13 | 14 | @Test 15 | fun `Test products of different IntRanges`() { 16 | val rangeToProduct = mapOf( 17 | 2..4 to 24L, 18 | 1..4 to 24L, 19 | 3..4 to 12L, 20 | 100..100 to 100L 21 | ) 22 | for ((range, product) in rangeToProduct) 23 | assertEquals(product, range.product()) 24 | } 25 | 26 | @Test 27 | fun `Test products of different Int Collections`() { 28 | val collectionToProduct = mapOf( 29 | listOf(1,2,3) to 6L, 30 | listOf(2,3) to 6L, 31 | listOf(3) to 3L, 32 | listOf(10, 10, 10) to 1000L 33 | ) 34 | for ((collection, product) in collectionToProduct) 35 | assertEquals(product, collection.product()) 36 | } 37 | 38 | @Test 39 | fun `Test products of different Long Collections`() { 40 | val collectionToProduct = mapOf( 41 | listOf(1L,2L,3L) to 6L, 42 | listOf(2L,3L) to 6L, 43 | listOf(3L) to 3L, 44 | listOf(10L, 10L, 10L) to 1000L 45 | ) 46 | for ((collection, product) in collectionToProduct) 47 | assertEquals(product, collection.product()) 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/SetSplitTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.splits 4 | import com.marcinmoskala.math.splitsNumber 5 | import org.junit.jupiter.api.Assertions.assertEquals 6 | import org.junit.jupiter.api.Test 7 | 8 | internal class SetSplitTest { 9 | 10 | fun set(size: Int) = (1..size).toSet() 11 | 12 | @Test fun `splitsNumber function for set is throwing error when asked for groupsNum of size smaller then 0`() { 13 | for (groupsNum in -10..-1) { 14 | for (num in 0..10) { 15 | assertIsThrowingError { set(num).splitsNumber(groupsNum) } 16 | } 17 | } 18 | } 19 | 20 | @Test fun `splits function for set is throwing error when asked for groupsNum of size smaller then 0`() { 21 | for (groupsNum in -10..-1) { 22 | for (num in 0..10) { 23 | assertIsThrowingError { set(num).splits(groupsNum) } 24 | } 25 | } 26 | } 27 | 28 | @Test 29 | fun `n elements can be only one way splitted to one or n groups`() { 30 | for (n in 1..100) { 31 | assertEquals(1, set(n).splitsNumber(1)) 32 | assertEquals(1, set(n).splitsNumber(n)) 33 | } 34 | } 35 | 36 | @Test 37 | fun `For 0 splits, Stirling function is returning 1 for 0 and 0 otherwise`() { 38 | assertEquals(1, set(0).splitsNumber(0)) 39 | for (n in 1..100) { 40 | assertEquals(0, set(n).splitsNumber(0)) 41 | } 42 | } 43 | 44 | @Test 45 | fun `Stirling function is correct according to recurrence definition`() { 46 | for (n in 1..10) { 47 | for (k in 1..(n - 1)) { 48 | assertEquals( 49 | set(n).splitsNumber(k), 50 | set(n - 1).splitsNumber(k - 1) + k * set(n - 1).splitsNumber(k) 51 | ) 52 | } 53 | } 54 | } 55 | 56 | @Test 57 | fun `Simple set splits number for examples are calculated correctly`() { 58 | assertEquals(1, set(3).splitsNumber(1)) 59 | assertEquals(3, set(3).splitsNumber(2)) 60 | assertEquals(7, set(4).splitsNumber(2)) 61 | assertEquals(25, set(5).splitsNumber(3)) 62 | assertEquals(140, set(7).splitsNumber(5)) 63 | assertEquals(350, set(7).splitsNumber(4)) 64 | } 65 | 66 | @Test 67 | fun `There is no splits to 0, except empty set`() { 68 | assertEquals(setOf(emptySet()), set(0).splits(0)) 69 | for (n in 1..100) assertEquals(emptySet>(), set(n).splits(0)) 70 | } 71 | 72 | @Test 73 | fun `Split to 1 is returning only base set`() { 74 | (1..10).map { set(it) }.forEach { s -> assertEquals(setOf(setOf(s)), s.splits(1)) } 75 | } 76 | 77 | @Test 78 | fun `Split to set size is returning set with each element separated`() { 79 | (1..10).map { set(it) }.forEach { s -> assertEquals(setOf(s.map { setOf(it) }.toSet()), s.splits(s.size)) } 80 | } 81 | 82 | @Test 83 | fun `Simple set split is correct`() { 84 | assertEquals(setOf(setOf(setOf(1, 2), setOf(3)), setOf(setOf(1, 3), setOf(2)), setOf(setOf(3, 2), setOf(1))), setOf(1, 2, 3).splits(2)) 85 | } 86 | 87 | @Test 88 | fun `Splits size and splitsNumber matches`() { 89 | for (i in 1..5) for (j in 1..5) { 90 | val s = set(i) 91 | assertEquals(s.splitsNumber(j), s.splits(j).size) 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/SublistsBySplittersTest.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | import com.marcinmoskala.math.sublistsBySplitters 4 | import org.junit.jupiter.api.Assertions.assertEquals 5 | import org.junit.jupiter.api.Test 6 | 7 | internal class SublistsBySplittersTest { 8 | 9 | @Test fun `Sublists from empty list is only empty list`() { 10 | val emptyList = listOf() 11 | assertEquals(listOf(emptyList), emptyList.sublistsBySplitters { true }) 12 | assertEquals(listOf(emptyList), emptyList.sublistsBySplitters { false }) 13 | } 14 | 15 | @Test 16 | fun `Sublists order is from biggest list to empty with elements in natural order`() { 17 | assertEquals(listOf(listOf(1, 2), listOf(1), listOf(2), listOf()), listOf(1, 2).sublistsBySplitters { true }) 18 | assertEquals(listOf(listOf(1, 2), listOf(1)), listOf(1, 2).sublistsBySplitters { it % 2 == 0 }) 19 | } 20 | 21 | @Test 22 | fun `Sublist creation for mixed splitters and simple`() { 23 | assertEquals(setOf(listOf(1, 2, 3), listOf(1, 3)), listOf(1, 2, 3).sublistsBySplitters { it % 2 == 0 }.toSet()) 24 | assertEquals(setOf(listOf(1, 2, 3, 4), listOf(1, 2, 3), listOf(1, 3, 4), listOf(1, 3)), listOf(1, 2, 3, 4).sublistsBySplitters { it % 2 == 0 }.toSet()) 25 | } 26 | 27 | @Test 28 | fun `Big sublists results sizes are correct`() { 29 | // 10 splitters, so 2^10 = 1024 lists 30 | assert((1..20).toList().sublistsBySplitters { it % 2 == 0 }.size == 1024) 31 | assert((1..40).toList().sublistsBySplitters { it % 4 == 0 }.size == 1024) 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/java/com/marcinmoskala/math/tests/TestUtils.kt: -------------------------------------------------------------------------------- 1 | package com.marcinmoskala.math.tests 2 | 3 | internal fun assertIsThrowingError(f: () -> T) { 4 | try { 5 | f() 6 | } catch (r: Error) { 7 | return 8 | } 9 | assert(false) 10 | } --------------------------------------------------------------------------------