├── settings.gradle.kts ├── src ├── test │ ├── resources │ │ └── mockito-extensions │ │ │ └── org.mockito.plugins.MockMaker │ └── kotlin │ │ └── dev │ │ └── shtanko │ │ └── algorithms │ │ ├── utils │ │ ├── MeasureTimeTest.kt │ │ ├── ByteFormatterTest.kt │ │ ├── CharArrayExtTest.kt │ │ └── HumanReadableDurationTest.kt │ │ ├── search │ │ ├── Strategies.kt │ │ ├── StringSearchTest.kt │ │ └── IntSearchTest.kt │ │ ├── ConstantsTest.kt │ │ ├── extensions │ │ ├── DoubleXTest.kt │ │ ├── IntArrayXTest.kt │ │ └── CharXTest.kt │ │ ├── sorts │ │ ├── IsSorted.kt │ │ ├── Strategies.kt │ │ ├── TestObject.kt │ │ ├── QuickSortRecursiveTest.kt │ │ └── MemoryTest.kt │ │ ├── graph │ │ └── GraphTest.kt │ │ ├── math │ │ ├── NewtonMethodTest.kt │ │ ├── NarcissisticNumberTest.kt │ │ ├── GCDTest.kt │ │ ├── BinomialTest.kt │ │ └── MatrixTranspositionTest.kt │ │ ├── leetcode │ │ ├── AppealSumTest.kt │ │ ├── MinDistanceTest.kt │ │ ├── dp │ │ │ └── linear │ │ │ │ └── ClimbingStairsTest.kt │ │ └── TwoSumTest.kt │ │ └── bitwise │ │ └── BinaryRepresentationTest.kt └── main │ └── kotlin │ └── dev │ └── shtanko │ └── algorithms │ ├── extensions │ ├── DoubleX.kt │ ├── IntPredicate.kt │ ├── IntArrayX.kt │ ├── CharArrayX.kt │ ├── CharX.kt │ ├── LongX.kt │ ├── IntX.kt │ └── ArrayX.kt │ ├── sorts │ ├── Sortable.kt │ ├── JvmSort.kt │ ├── PancakeSort.kt │ ├── GnomeSort.kt │ ├── QuickSortRecursive.kt │ ├── ShellSort.kt │ ├── InsertionSorts.kt │ ├── HeapSort.kt │ ├── README.md │ ├── SelectionSorts.kt │ ├── BubbleSorts.kt │ └── BottomUpMergeSort.kt │ ├── graph │ ├── GraphTraverseStrategy.kt │ ├── Graph.kt │ └── BreadthFirstSearch.kt │ ├── math │ ├── MatrixTransposition.kt │ ├── Binomial.kt │ ├── Gcd.kt │ ├── ComputeFactorial.kt │ ├── Sqrt.kt │ ├── NarcissisticNumber.kt │ └── Fibonacci.kt │ ├── search │ ├── Searchable.kt │ ├── LinearSearch.kt │ ├── BinarySearch.kt │ └── BinaryRecursiveSearch.kt │ ├── utils │ ├── ToHumanReadableDuration.kt │ ├── ByteFormatter.kt │ ├── ToHumanReadableByteCountSI.kt │ ├── ToHumanReadableByteCountBin.kt │ └── MeasureTime.kt │ ├── leetcode │ ├── dp │ │ └── linear │ │ │ └── ClimbingStairs.kt │ └── AppealSum.kt │ ├── Constants.kt │ └── bitwise │ └── BinaryRepresentation.kt ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── qodana.yaml ├── .idea ├── .gitignore ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── PMDPlugin.xml ├── compiler.xml ├── kotlinc.xml ├── sonarlint.xml ├── markdown.xml ├── the-algorithms.iml ├── misc.xml └── jarRepositories.xml ├── renovate.json ├── config ├── detekt │ └── detekt-baseline.xml └── main.md ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── codecov.yml ├── local.properties ├── scripts └── git-hooks │ └── pre-commit.sh ├── LICENSE ├── spotless └── copyright.kt ├── Makefile ├── gradle.properties ├── doc └── ROADMAP.md └── gradlew.bat /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "DSA-Kotlin" 2 | -------------------------------------------------------------------------------- /src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashtanko/DSA-Kotlin/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /qodana.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | linter: jetbrains/qodana-jvm-community:2023.2-eap 3 | profile: 4 | name: qodana.recommended 5 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # GitHub Copilot persisted chat sessions 5 | /copilot/chatSessions 6 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /config/detekt/detekt-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "03:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.idea/PMDPlugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: main 3 | disable_default_path_fixes: true 4 | notify: 5 | require_ci_to_pass: yes 6 | 7 | coverage: 8 | status: 9 | project: 10 | default: 11 | target: 80% 12 | threshold: 5% 13 | fixes: 14 | - "main/::" 15 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.idea/sonarlint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /.idea/markdown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/the-algorithms.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Fri Apr 14 17:36:18 CEST 2023 8 | sdk.dir=/Users/shtanko/Library/Android/sdk 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 11 | 12 | 14 | 15 | 17 | 18 | -------------------------------------------------------------------------------- /scripts/git-hooks/pre-commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Running static analysis..." 3 | 4 | JAVA_HOME=$(/usr/libexec/java_home -v 11) 5 | export JAVA_HOME 6 | 7 | OUTPUT="/tmp/analysis-result" 8 | ./gradlew spotlessApply spotlessCheck spotlessKotlin detekt ktlintCheck --profile > ${OUTPUT} 9 | EXIT_CODE=$? 10 | if [ ${EXIT_CODE} -ne 0 ]; then 11 | cat ${OUTPUT} 12 | rm ${OUTPUT} 13 | echo "*********************************************" 14 | echo " Static Analysis Failed " 15 | echo "Please fix the above issues before committing" 16 | echo "*********************************************" 17 | exit ${EXIT_CODE} 18 | else 19 | rm ${OUTPUT} 20 | echo "*********************************************" 21 | echo " Static analysis no problems found " 22 | echo "*********************************************" 23 | fi 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Oleksii Shtanko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /spotless/copyright.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Phony targets to avoid conflicts with files of the same name 2 | .PHONY: default check test report treport lines md all kover diktat c m a t re r l d h 3 | 4 | # Run code quality checks and apply formatting 5 | check c: 6 | ./gradlew spotlessApply spotlessCheck spotlessKotlin detekt ktlintCheck diktatCheck buildHealth --profile --daemon 7 | 8 | # Default target: run checks and update README.md 9 | default: 10 | make check && make md 11 | 12 | # Update README.md with main and detekt report content 13 | md m: 14 | truncate -s0 README.md && cat config/main.md >> README.md && cat build/reports/detekt/detekt.md >> README.md 15 | 16 | # Run checks, build the project, and update README.md 17 | all a: 18 | make check && ./gradlew build && md 19 | 20 | # Run tests 21 | test t: 22 | ./gradlew test 23 | 24 | # Generate JaCoCo test coverage report 25 | report re: 26 | ./gradlew jacocoTestReport 27 | 28 | # Run tests and generate JaCoCo test coverage report 29 | treport r: 30 | make test & make report 31 | 32 | # Count lines of Kotlin code 33 | lines l: 34 | find . -name '*.kt' | xargs wc -l 35 | 36 | # Generate Kover HTML report 37 | kover: 38 | ./gradlew koverHtmlReport 39 | 40 | # Run Diktat code style checks 41 | diktat d: 42 | ./gradlew diktatCheck 43 | 44 | # Run build health checks 45 | health h: 46 | ./gradlew buildHealth 47 | 48 | detekt: 49 | ./gradlew detekt 50 | 51 | # Set the default target 52 | .DEFAULT_GOAL := default 53 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Kotlin-specific configuration (adjust as needed) 2 | kotlin.code.style=official 3 | kotlin.coroutines=enable 4 | # Set the JVM heap size for the Gradle Daemon (adjust as needed) 5 | org.gradle.jvmargs=-Xmx4g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC 6 | # Gradle Daemon: Enable or disable the Gradle Daemon (improves build speed) 7 | org.gradle.daemon=true 8 | # Parallel execution: Enable parallel task execution for multi-core processors 9 | org.gradle.parallel=true 10 | # Build caching: Enable or disable build caching (improves build speed) 11 | org.gradle.caching=true 12 | # Enable configuration on demand (only configure projects that are needed) 13 | org.gradle.configureondemand=true 14 | # Configure the maximum number of concurrent build cache connections (adjust as needed) 15 | org.gradle.caching.http.max-concurrent-connections=50 16 | # Optimize dependency resolution by caching resolved dependencies 17 | org.gradle.dependency-resolution-caching=true 18 | # Optimize dependency resolution by avoiding network access when possible 19 | org.gradle.unresolved-dependencies=use-cache 20 | # Optimize task input and output caching to minimize unnecessary task re-execution 21 | org.gradle.caching.debug=false 22 | org.jetbrains.dokka.experimental.gradle.pluginMode=V2EnabledWithHelpers 23 | # suppress dokka (Thank you for enabling Dokka Gradle plugin V2!) console message 24 | org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true 25 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/DoubleX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | /** 28 | * Checks if a Double value is even. 29 | * 30 | * @return `true` if the Double value is even, `false` otherwise. 31 | */ 32 | fun Double.isEven(): Boolean = (this % 2).toInt() == 0 33 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/Sortable.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | /** 28 | * Interface representing an abstract sorting strategy. 29 | */ 30 | sealed interface Sortable { 31 | /** 32 | * Invokes the sorting strategy on the given array. 33 | * 34 | * @param arr The array to be sorted. 35 | */ 36 | operator fun > invoke(arr: Array) 37 | } 38 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/graph/GraphTraverseStrategy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.graph 26 | 27 | /** 28 | * A strategy to traverse a graph. 29 | * @see Graph 30 | */ 31 | sealed interface GraphTraverseStrategy { 32 | /** 33 | * Traverses the graph. 34 | * 35 | * @param graph The graph to traverse. 36 | * @param start The starting vertex. 37 | * @return The list of visited vertices. 38 | */ 39 | operator fun invoke(graph: Graph, start: Int): List 40 | } 41 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/IntPredicate.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | /** 28 | * Functional interface representing a predicate that accepts an Int and returns a Boolean. 29 | */ 30 | fun interface IntPredicate { 31 | /** 32 | * Evaluates the predicate for the given Int value. 33 | * 34 | * @param i The Int value to evaluate. 35 | * @return `true` if the predicate accepts the value, `false` otherwise. 36 | */ 37 | operator fun invoke(i: Int): Boolean 38 | } 39 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/utils/MeasureTimeTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.Test 29 | import kotlin.time.DurationUnit 30 | import kotlin.time.ExperimentalTime 31 | 32 | class MeasureTimeTest { 33 | @ExperimentalTime 34 | @Test 35 | fun `simple test`() { 36 | val time = measureTime(DurationUnit.MILLISECONDS) { 37 | repeat(10_000_000) {} 38 | } 39 | assertThat(time).isLessThan(333) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/JvmSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | /** 28 | * Implementation of the sorting strategy using the built-in array sort function. 29 | */ 30 | data object JvmSort : Sortable { 31 | /** 32 | * Performs the sorting operation on the given array using the built-in array sort function. 33 | * 34 | * @param arr The array to sort. 35 | * @param T The type of elements in the array, must be comparable. 36 | */ 37 | override fun > invoke(arr: Array) = arr.sort() 38 | } 39 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/IntArrayX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | /** 28 | * Reverses a portion of the IntArray between the specified start and end indices (inclusive). 29 | * 30 | * @param start The starting index of the portion to be reversed. 31 | * @param end The ending index of the portion to be reversed. 32 | */ 33 | fun IntArray.reverse( 34 | start: Int, 35 | end: Int, 36 | ) { 37 | for (i in 0 until (end - start) / 2) { 38 | val temp = this[i + start] 39 | this[i + start] = this[end - i - 1] 40 | this[end - i - 1] = temp 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/search/Strategies.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | class LinearSearchTest : IntSearchTest>(LinearSearch()) 28 | class LinearSearchStringTest : StringSearchTest>(LinearSearch()) 29 | 30 | class BinarySearchTest : IntSearchTest>(BinarySearch()) 31 | class BinarySearchStringTest : StringSearchTest>(BinarySearch()) 32 | 33 | class BinaryRecursiveSearchTest : IntSearchTest>(BinaryRecursiveSearch()) 34 | class BinaryRecursiveStringSearchTest : 35 | StringSearchTest>(BinaryRecursiveSearch()) 36 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/MatrixTransposition.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | /** 28 | * Transposes the matrix by swapping rows and columns. 29 | * 30 | * @return The transposed matrix. 31 | */ 32 | fun Array.transpose(): Array { 33 | if (isEmpty()) { 34 | return emptyArray() 35 | } 36 | val matrix = this 37 | val rows = matrix.size 38 | val cols = matrix[0].size 39 | 40 | val transposedMatrix = Array(cols) { IntArray(rows) } 41 | 42 | for (i in 0 until rows) { 43 | for (j in 0 until cols) { 44 | transposedMatrix[j][i] = matrix[i][j] 45 | } 46 | } 47 | 48 | return transposedMatrix 49 | } 50 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/search/Searchable.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | /** 28 | * Functional interface representing an abstract search strategy. 29 | * 30 | * @param T The type of elements in the array. 31 | */ 32 | fun interface Searchable { 33 | /** 34 | * Performs the search operation on the given array to find the index of the specified element. 35 | * 36 | * @param arr The array to search. 37 | * @param element The element to search for. 38 | * @return The index of the element in the array, or -1 if the element is not found. 39 | */ 40 | operator fun invoke( 41 | arr: Array, 42 | element: T, 43 | ): Int 44 | } 45 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/ConstantsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.Test 29 | 30 | class ConstantsTest { 31 | @Test 32 | fun `constants test`() { 33 | assertEquals(10, DECIMAL) 34 | assertEquals(8, OCTAL) 35 | assertEquals(16, HEXADECIMAL) 36 | assertEquals(65535, SHUFFLE) 37 | assertEquals(1_000_000_007, MOD) 38 | assertEquals(1_000_000_000.0, BILLION) 39 | assertEquals(0.00001, EPSILON) 40 | assertEquals(1024, BYTE) 41 | assertEquals(1000L, MILLISECOND) 42 | assertEquals("%.1f %cB", BIN_FORMAT) 43 | assertEquals("%.1f %ciB", SI_FORMAT) 44 | assertEquals(26, ALPHABET_LETTERS_COUNT) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/utils/ToHumanReadableDuration.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import dev.shtanko.algorithms.MILLISECOND 28 | import java.util.concurrent.TimeUnit 29 | 30 | /** 31 | * Converts the given duration in nanoseconds to a human-readable format. 32 | * 33 | * @return a string representing the duration in a human-readable format. 34 | */ 35 | fun Long.toHumanReadableDuration(): String { 36 | val millis = TimeUnit.MILLISECONDS.convert(this, TimeUnit.NANOSECONDS) 37 | val sec = TimeUnit.SECONDS.convert(this, TimeUnit.NANOSECONDS) 38 | val sb = 39 | if (sec != 0L) { 40 | val diff = millis - MILLISECOND * sec 41 | val sbDiff = "$diff ms" 42 | "$sec,$sbDiff" 43 | } else { 44 | "$millis ms" 45 | } 46 | return "Runtime: $sb" 47 | } 48 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/graph/Graph.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.graph 26 | 27 | /** 28 | * A graph is a collection of nodes (vertices) along with identified pairs of 29 | * nodes (called edges, links, etc.). 30 | * The graph is one of the most common data structures in computer science. 31 | */ 32 | typealias Graph = Map> 33 | 34 | /** 35 | * An empty graph. 36 | */ 37 | data object EmptyGraph : Graph by graphOf() 38 | 39 | /** 40 | * Creates a graph from the specified pairs. 41 | * The first value in the pair is the node, and the second value is the list 42 | * of neighbors. 43 | * The neighbors are the nodes that are connected to the current node. 44 | * 45 | * @param pairs The pairs of nodes and their neighbors. 46 | * @return The created graph. 47 | */ 48 | fun graphOf(vararg pairs: Pair>): Graph = pairs.toMap() 49 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/leetcode/dp/linear/ClimbingStairs.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode.dp.linear 26 | 27 | val climbingStairsBottomUpDp = ClimbingStairs { num -> 28 | if (num == 1) { 29 | return@ClimbingStairs 1 30 | } 31 | var oneBefore = 1 32 | var twoBefore = 1 33 | var total = 0 34 | repeat(num - 1) { 35 | total = oneBefore + twoBefore 36 | twoBefore = oneBefore 37 | oneBefore = total 38 | } 39 | return@ClimbingStairs total 40 | } 41 | 42 | /** 43 | * 70. Climbing Stairs 44 | * @see Source 45 | */ 46 | fun interface ClimbingStairs { 47 | /** 48 | * Calculates the number of ways to climb the given number of stairs. 49 | * 50 | * @param num The number of stairs to climb. 51 | * @return The number of ways to climb the given number of stairs. 52 | */ 53 | operator fun invoke(num: Int): Int 54 | } 55 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/extensions/DoubleXTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.ValueSource 31 | 32 | class DoubleXTest { 33 | @DisplayName("Test only even numbers") 34 | @ParameterizedTest(name = "For example, value {0} is even.") 35 | @ValueSource(doubles = [2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 100.0]) 36 | fun `is even test`(value: Double) { 37 | assertThat(value.isEven()).isTrue 38 | } 39 | 40 | @DisplayName("Test only odd numbers") 41 | @ParameterizedTest(name = "For example, value {0} is not even.") 42 | @ValueSource(doubles = [1.0, 11.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 91.0, 3.0, 13.0]) 43 | fun `is odd test`(value: Double) { 44 | assertThat(value.isEven()).isFalse 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/Binomial.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | /** 28 | * Calculates the binomial coefficient (n choose k). 29 | * A binomial coefficient C(n, k) can be defined as the coefficient of X^k in the expansion of (1 + X)^n. 30 | * A binomial coefficient C(n, k) also gives the number of ways, disregarding order, 31 | * that k objects can be chosen from among n objects; more formally, the number of k-element subsets 32 | * (or k-combinations) of an n-element set. 33 | * 34 | * @param totalItems The total number of items. 35 | * @param itemsToSelect The number of items to choose. 36 | * @return The binomial coefficient. 37 | */ 38 | fun binomial( 39 | totalItems: Int, 40 | itemsToSelect: Int, 41 | ): Long { 42 | var numerator = totalItems - itemsToSelect + 1 43 | var result = 1L 44 | for (denominator in 1..itemsToSelect) { 45 | result = result * numerator / denominator 46 | numerator++ 47 | } 48 | return result 49 | } 50 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/Gcd.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | /** 28 | * Calculates the greatest common divisor (GCD) of the two integers in the Pair. 29 | * 30 | * @receiver The Pair of integers. 31 | * @return The greatest common divisor of the two integers. 32 | */ 33 | fun Pair.gcd(): Int { 34 | var largerNumber = first 35 | var smallerNumber = second 36 | while (smallerNumber != 0) { 37 | val remainder = largerNumber % smallerNumber 38 | largerNumber = smallerNumber 39 | smallerNumber = remainder 40 | } 41 | return largerNumber 42 | } 43 | 44 | /** 45 | * Calculates the greatest common divisor (GCD) of two integers. 46 | * 47 | * @param number1 The first integer. 48 | * @param number2 The second integer. 49 | * @return The greatest common divisor of the two integers. 50 | */ 51 | fun gcd( 52 | number1: Int, 53 | number2: Int 54 | ): Int = if (number2 == 0) number1 else gcd(number2, number1 % number2) 55 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/sorts/IsSorted.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | /** 28 | * Checks if the integer array is sorted in non-decreasing order. 29 | * 30 | * This function uses a sequence to compare each element with the next one 31 | * and ensures that all elements are in non-decreasing order. 32 | * 33 | * @return `true` if the array is sorted in non-decreasing order, `false` 34 | * otherwise. 35 | */ 36 | fun IntArray.isSorted(): Boolean = 37 | asSequence().zipWithNext { a, b -> a <= b }.all { it } 38 | 39 | /** 40 | * Checks if the array of integers is sorted in non-decreasing order. 41 | * 42 | * This function uses a sequence to compare each element with the next one 43 | * and ensures that all elements are in non-decreasing order. 44 | * 45 | * @return `true` if the array is sorted in non-decreasing order, `false` 46 | * otherwise. 47 | */ 48 | @Suppress("ArrayPrimitive") 49 | fun Array.isSorted(): Boolean = 50 | asSequence().zipWithNext { a, b -> a <= b }.all { it } 51 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/CharArrayX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | /** 28 | * Reverses a portion of the CharArray between the specified indices. 29 | * 30 | * @param leftIdx The starting index (inclusive) of the portion to be reversed. 31 | * @param rightIdx The ending index (inclusive) of the portion to be reversed. 32 | */ 33 | fun CharArray.reverse( 34 | leftIdx: Int, 35 | rightIdx: Int, 36 | ) { 37 | var left = leftIdx 38 | var right = rightIdx 39 | while (left < right) { 40 | val tmp = this[left] 41 | this[left++] = this[right] 42 | this[right--] = tmp 43 | } 44 | } 45 | 46 | /** 47 | * Swaps the characters at the given indices in this CharArray. 48 | * 49 | * @param i the index of the first character to swap. 50 | * @param j the index of the second character to swap. 51 | */ 52 | fun CharArray.swap( 53 | i: Int, 54 | j: Int, 55 | ) { 56 | val temp = this[i] 57 | this[i] = this[j] 58 | this[j] = temp 59 | } 60 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/CharX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import kotlin.random.Random 28 | 29 | /** 30 | * Generates a random string of the specified length consisting of characters within the closed range. 31 | * 32 | * @param length the length of the generated random string. 33 | * @return a random string of the specified length. 34 | */ 35 | fun ClosedRange.randomString(length: Int) = 36 | (1..length) 37 | .map { 38 | val randomLimit = endInclusive.code - start.code 39 | val randomCode = Random.nextInt(until = randomLimit) + start.code 40 | randomCode.toChar() 41 | } 42 | .joinToString("") 43 | 44 | /** 45 | * Checks if the character is a vowel (a, e, i, o, u). 46 | * 47 | * @return true if the character is a vowel, false otherwise. 48 | */ 49 | fun Char.isVowel(): Boolean { 50 | val ae = this == 'a' || this == 'e' 51 | val io = this == 'i' || this == 'o' 52 | val iou = io || this == 'u' 53 | return ae || iou 54 | } 55 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/ComputeFactorial.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | /** 28 | * Computes the factorial of the given input using tail recursion. 29 | * Factorial, in mathematics, the product of all positive integers less than or equal to a given positive integer 30 | * and denoted by that integer and an exclamation point. Thus, factorial seven is written 7!, 31 | * meaning 1 × 2 × 3 × 4 × 5 × 6 × 7. Factorial zero is defined as equal to 1. 32 | * 33 | * @param input The input number to compute the factorial of. 34 | * @param temp The temporary variable to store the intermediate result (default: 1). 35 | * @return The factorial of the input number. 36 | * @throws IllegalArgumentException if the input is a negative number. 37 | */ 38 | tailrec fun computeFactorial( 39 | input: Int, 40 | temp: Long = 1L, 41 | ): Long = 42 | when { 43 | input < 0 -> error("Factorial is not defined for negative numbers") 44 | input == 0 -> temp 45 | else -> computeFactorial(input - 1, temp * input) 46 | } 47 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/sorts/Strategies.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | class SelectionSortTest : SortTest(SelectionSort) 28 | 29 | class StableSelectionSortTest : SortTest(StableSelectionSort) 30 | 31 | class ShellSortTest : SortTest(ShellSort) 32 | 33 | class QuickSortTest : SortTest(QuickSort) 34 | 35 | class MergeSortTest : SortTest(MergeSort) 36 | 37 | class BottomUpMergeSortTest : SortTest(BottomUpMergeSort) 38 | 39 | class InsertionSortTest : SortTest(InsertionSort) 40 | 41 | class InsertionSort2Test : SortTest(InsertionSort2) 42 | 43 | class HeapSortTest : SortTest(HeapSort) 44 | 45 | class BubbleSortTest : SortTest(BubbleSort) 46 | 47 | class SimpleBubbleSortTest : SortTest(SimpleBubbleSort) 48 | 49 | class JvmSortTest : SortTest(JvmSort) 50 | 51 | class PancakeSortTest : SortTest(PancakeSort) 52 | 53 | class GnomeSortTest : SortTest(GnomeSort) 54 | 55 | class QuickSortRecursiveTest2 : SortTest(QuickSortRecursive) 56 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/sorts/TestObject.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | fun interface ToStringStrategy { 28 | fun invoke(obj: TestObject): String 29 | } 30 | 31 | data object FullToStringStrategy : ToStringStrategy { 32 | override fun invoke(obj: TestObject): String = "TestObject(id=${obj.id}, name=${obj.name})" 33 | } 34 | 35 | data object NameToStringStrategy : ToStringStrategy { 36 | override fun invoke(obj: TestObject): String = obj.name 37 | } 38 | 39 | /** 40 | * @property id 41 | * @property name 42 | */ 43 | data class TestObject( 44 | val id: Int, 45 | val name: String, 46 | val strategy: ToStringStrategy = NameToStringStrategy, 47 | ) : Comparable { 48 | override fun compareTo(other: TestObject): Int { 49 | val n = this.name.compareTo(other.name) 50 | return if (n == 0) this.id.compareTo(other.id) else n 51 | } 52 | 53 | companion object { 54 | fun empty( 55 | strategy: ToStringStrategy = NameToStringStrategy, 56 | ): TestObject = TestObject(0, "", strategy) 57 | } 58 | 59 | override fun toString(): String = strategy.invoke(this) 60 | } 61 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/graph/GraphTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.graph 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.Assertions.assertTrue 29 | import org.junit.jupiter.api.Test 30 | 31 | class GraphTest { 32 | @Test 33 | fun `emptyGraph should be empty`() { 34 | assertTrue(EmptyGraph.isEmpty()) 35 | } 36 | 37 | @Test 38 | fun `graphOf should create a graph with the specified pairs`() { 39 | val graph = graphOf( 40 | 1 to listOf(2, 3), 41 | 2 to listOf(1, 4), 42 | 3 to listOf(1), 43 | 4 to listOf(2), 44 | ) 45 | 46 | assertEquals(listOf(2, 3), graph[1]) 47 | assertEquals(listOf(1, 4), graph[2]) 48 | assertEquals(listOf(1), graph[3]) 49 | assertEquals(listOf(2), graph[4]) 50 | } 51 | 52 | @Test 53 | fun `graphOf should handle empty lists of neighbors`() { 54 | val graph = graphOf( 55 | 1 to emptyList(), 56 | 2 to listOf(1), 57 | ) 58 | assertTrue(graph[1]?.isEmpty() == true) 59 | assertEquals(listOf(1), graph[2]) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/search/LinearSearch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | /** 28 | * Implementation of the linear search algorithm. 29 | * 30 | * Linear search is an algorithm which finds the position of a target value within an array (Usually unsorted) 31 | * 32 | * Worst-case performance O(n) 33 | * Best-case performance O(1) 34 | * Average performance O(n) 35 | * Worst-case space complexity O(1) 36 | * 37 | * @param T The type of elements in the array. 38 | */ 39 | class LinearSearch : Searchable { 40 | /** 41 | * Performs the linear search operation on the given array to find the index of the specified element. 42 | * 43 | * @param array The array to search. 44 | * @param element The element to search for. 45 | * @return The index of the element in the array, or -1 if the element is not found. 46 | */ 47 | override operator fun invoke( 48 | arr: Array, 49 | element: T, 50 | ): Int { 51 | for ((index, item) in arr.withIndex()) { 52 | if (item == element) { 53 | return index 54 | } 55 | } 56 | return -1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/utils/ByteFormatter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import dev.shtanko.algorithms.BIN_FORMAT 28 | import dev.shtanko.algorithms.SI_FORMAT 29 | import java.util.Locale 30 | 31 | /** 32 | * Implementation of ByteFormatter for formatting byte values in binary format. 33 | */ 34 | val binByteFormatter = ByteFormatter { bytes, current -> 35 | String.format(Locale.getDefault(), BIN_FORMAT, bytes, current) 36 | } 37 | 38 | /** 39 | * Implementation of ByteFormatter for formatting byte values in SI format. 40 | */ 41 | val siByteFormatter = ByteFormatter { bytes, current -> 42 | String.format(Locale.getDefault(), SI_FORMAT, bytes, current) 43 | } 44 | 45 | /** 46 | * Functional interface for formatting byte values. 47 | */ 48 | fun interface ByteFormatter { 49 | /** 50 | * Formats the given bytes using the specified current unit. 51 | * 52 | * @param bytes the number of bytes to be formatted. 53 | * @param current the unit of the current byte value (e.g., 'B' for bytes, 'iB' for binary bytes). 54 | * @return a formatted string representing the byte value. 55 | */ 56 | operator fun invoke(bytes: Double, current: Char): String 57 | } 58 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/utils/ToHumanReadableByteCountSI.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import java.text.CharacterIterator 28 | import java.text.StringCharacterIterator 29 | 30 | private const val LIMIT = 1000 31 | private const val BOUNDARY = 999_950 32 | private const val UNITS = "kMGTPE" 33 | 34 | /** 35 | * Converts a long value to a human-readable byte count representation using 36 | * SI prefixes. 37 | * 38 | * @param formatter The formatter to use for converting the byte count to a 39 | * string representation. 40 | * Defaults to `binByteFormatter`. 41 | * @return The human-readable byte count representation. 42 | */ 43 | fun Long.toHumanReadableByteCountSi(formatter: ByteFormatter = binByteFormatter): String { 44 | var bytes = this 45 | 46 | if (-LIMIT < bytes && bytes < LIMIT) { 47 | return "$bytes B" 48 | } 49 | 50 | val ci: CharacterIterator = StringCharacterIterator(UNITS) 51 | while (bytes <= -BOUNDARY || bytes >= BOUNDARY) { 52 | bytes /= LIMIT 53 | ci.next() 54 | } 55 | val kiloBytes = bytes / LIMIT.toDouble() 56 | val current = ci.current() 57 | 58 | return formatter.invoke(kiloBytes, current) 59 | } 60 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/Constants.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms 26 | 27 | /** 28 | * Base for decimal numbers. 29 | */ 30 | const val DECIMAL = 10 31 | 32 | /** 33 | * Base for octal numbers. 34 | */ 35 | const val OCTAL = 8 36 | 37 | /** 38 | * Base for hexadecimal numbers. 39 | */ 40 | const val HEXADECIMAL = 16 41 | 42 | /** 43 | * Constant used for shuffling. 44 | */ 45 | const val SHUFFLE = 0xFFFF 46 | 47 | /** 48 | * Modulus constant. 49 | */ 50 | const val MOD = 1_000_000_007 51 | 52 | /** 53 | * Constant representing one billion. 54 | */ 55 | const val BILLION = 1e9 56 | 57 | /** 58 | * Constant representing a byte (1024 bits). 59 | */ 60 | const val BYTE = 1024 61 | 62 | /** 63 | * Constant representing a millisecond. 64 | */ 65 | const val MILLISECOND = 1000L 66 | 67 | /** 68 | * Small constant used for floating point comparisons. 69 | */ 70 | const val EPSILON = 1e-5 71 | 72 | /** 73 | * Format for binary size representation. 74 | */ 75 | const val BIN_FORMAT = "%.1f %cB" 76 | 77 | /** 78 | * Format for SI size representation. 79 | */ 80 | const val SI_FORMAT = "%.1f %ciB" 81 | 82 | /** 83 | * Number of letters in the English alphabet. 84 | */ 85 | const val ALPHABET_LETTERS_COUNT = 26 86 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/Sqrt.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import dev.shtanko.algorithms.EPSILON 28 | import kotlin.math.abs 29 | 30 | /** 31 | * Calculates the square root of the given integer. 32 | * 33 | * @param number The integer to calculate the square root of. 34 | * @param tolerance The tolerance value for convergence (default: EPSILON). 35 | * @return The square root of the given integer. 36 | */ 37 | fun sqrt( 38 | number: Int, 39 | tolerance: Double = EPSILON, 40 | ): Double = sqrt(number.toDouble(), tolerance) 41 | 42 | /** 43 | * Calculates the square root of the given double. 44 | * 45 | * @param number The double to calculate the square root of. 46 | * @param tolerance The tolerance value for convergence (default: EPSILON). 47 | * @return The square root of the given double. 48 | */ 49 | fun sqrt( 50 | number: Double, 51 | tolerance: Double = EPSILON, 52 | ): Double { 53 | if (number < 0) { 54 | return Double.NaN 55 | } 56 | var approximation = number 57 | while (abs(approximation - number / approximation) > tolerance * approximation) { 58 | approximation = (number / approximation + approximation) / 2 59 | } 60 | return approximation 61 | } 62 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/PancakeSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.flip 28 | 29 | /** 30 | * Pancake sort is a sorting algorithm that sorts a sequence by repeatedly flipping the elements. 31 | * In each iteration, it finds the maximum element and flips the subsequence from the first element 32 | * up to the maximum element. 33 | * This process is repeated until the sequence is sorted. 34 | * 35 | * Worst-case performance: O(n^2) 36 | * Best-case performance: O(n) 37 | * Average performance: O(n^2) 38 | * Worst-case space complexity: O(1) 39 | */ 40 | data object PancakeSort : Sortable { 41 | /** 42 | * Performs the pancake sort operation on the given array. 43 | * 44 | * @param arr The array to sort. 45 | * @param T The type of elements in the array, must be comparable. 46 | */ 47 | override fun > invoke(arr: Array) { 48 | for (i in arr.indices) { 49 | var max = arr[0] 50 | var index = 0 51 | 52 | for (j in 0 until arr.size - i) { 53 | if (max < arr[j]) { 54 | max = arr[j] 55 | index = j 56 | } 57 | } 58 | arr.flip(index, arr.size - 1 - i) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/bitwise/BinaryRepresentation.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.bitwise 26 | 27 | private const val BITS_COUNT = 32 28 | 29 | /** 30 | * Converts a 32-bit unsigned integer to its binary representation. 31 | * 32 | * The method takes a 32-bit unsigned integer and returns its binary 33 | * representation as a string. 34 | * It starts from the most significant bit (bit 31) and iterates through each 35 | * bit, appending "1" if the bit is ON (1), or "0" if the bit is OFF (0). 36 | * The resulting binary representation is returned as a string. 37 | * 38 | * Time Complexity: O(1) 39 | * Auxiliary Space: O(1) 40 | * 41 | * @return The binary representation of the unsigned integer as a string. 42 | */ 43 | fun Long.bin(): String { 44 | val sb = StringBuilder() 45 | sb.append("0") 46 | 47 | val mostSignificantBit = BITS_COUNT - 2 48 | // Create the initial bitmask with a 1 at the most significant bit position 49 | val initialBitMask = 1L shl mostSignificantBit 50 | 51 | var currentBitMask: Long = initialBitMask 52 | while (currentBitMask > 0) { 53 | // Check if the current bit is set (1) or not (0) 54 | if (this and currentBitMask != 0L) { 55 | sb.append("1") 56 | } else { 57 | sb.append("0") 58 | } 59 | // Shift the bitmask to the right to check the next bit 60 | currentBitMask /= 2 61 | } 62 | return sb.toString() 63 | } 64 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/utils/ByteFormatterTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.Test 29 | 30 | class ByteFormatterTest { 31 | 32 | @Test 33 | fun testBinByteFormatter() { 34 | assertEquals("0.0 BB", binByteFormatter(0.0, 'B')) 35 | assertEquals("-1023.0 BB", binByteFormatter(-1023.0, 'B')) 36 | assertEquals("1023.0 BB", binByteFormatter(1023.0, 'B')) 37 | assertEquals("1024.0 iB", binByteFormatter(1024.0, 'i')) 38 | assertEquals("1572864.0 iB", binByteFormatter(1.5 * 1024 * 1024, 'i')) 39 | assertEquals("1073741824.0 iB", binByteFormatter(1.0 * 1024 * 1024 * 1024, 'i')) 40 | assertEquals("1099511627776.0 iB", binByteFormatter(1.0 * 1024 * 1024 * 1024 * 1024, 'i')) 41 | } 42 | 43 | @Test 44 | fun testSiByteFormatter() { 45 | assertEquals("0.0 BiB", siByteFormatter(0.0, 'B')) 46 | assertEquals("-999.0 BiB", siByteFormatter(-999.0, 'B')) 47 | assertEquals("999.0 BiB", siByteFormatter(999.0, 'B')) 48 | assertEquals("1000.0 BiB", siByteFormatter(1000.0, 'B')) 49 | assertEquals("1500000.0 BiB", siByteFormatter(1.5 * 1000 * 1000, 'B')) 50 | assertEquals("1000000000.0 BiB", siByteFormatter(1.0 * 1000 * 1000 * 1000, 'B')) 51 | assertEquals("1000000000000.0 BiB", siByteFormatter(1.0 * 1000 * 1000 * 1000 * 1000, 'B')) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/LongX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import dev.shtanko.algorithms.DECIMAL 28 | 29 | /** 30 | * Checks if a Long number is a super palindrome. 31 | * A super palindrome is defined as a number that remains a palindrome 32 | * after dividing it by 2 twice. 33 | * 34 | * @return `true` if the number is a super palindrome, `false` otherwise. 35 | */ 36 | fun Long.isSuperPalindrome(): Boolean { 37 | var currentNumber = this 38 | var isSuperPalindrome = false 39 | repeat(2) { 40 | isSuperPalindrome = currentNumber.isPalindrome() 41 | currentNumber /= 2 42 | if (!isSuperPalindrome) { 43 | return false 44 | } 45 | } 46 | return isSuperPalindrome 47 | } 48 | 49 | /** 50 | * Checks if a Long number is a palindrome. 51 | * A palindrome is a number that reads the same forward and backward. 52 | * 53 | * @return `true` if the number is a palindrome, `false` otherwise. 54 | */ 55 | fun Long.isPalindrome(): Boolean = this == this.reverse() 56 | 57 | /** 58 | * Reverses the digits of a Long number. 59 | * 60 | * @return The reversed Long number. 61 | */ 62 | fun Long.reverse(): Long { 63 | var reversedNumber = 0L 64 | var currentNumber = this 65 | while (currentNumber > 0) { 66 | reversedNumber = DECIMAL * reversedNumber + currentNumber % DECIMAL 67 | currentNumber /= DECIMAL 68 | } 69 | return reversedNumber 70 | } 71 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/GnomeSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.swap 28 | 29 | /** 30 | * Gnome sort is a simple sorting algorithm that works by repeatedly moving an element one position 31 | * towards its correct position in the sorted part of the array. It does this by comparing adjacent 32 | * elements and swapping them if they are in the wrong order. This process is continued until the 33 | * entire array is sorted. The algorithm gets its name from the idea that a gnome always moves the 34 | * flower pots to put them in the correct order. 35 | * 36 | * Worst-case performance: O(n^2) 37 | * Best-case performance: O(n) 38 | * Average performance: O(n^2) 39 | * Worst-case space complexity: O(1) 40 | */ 41 | data object GnomeSort : Sortable { 42 | /** 43 | * Performs the gnome sort operation on the given array. 44 | * 45 | * @param arr The array to sort. 46 | * @param T The type of elements in the array, must be comparable. 47 | */ 48 | override fun > invoke(arr: Array) { 49 | var i = 1 50 | var j = 2 51 | while (i < arr.size) { 52 | if (arr[i - 1] < arr[i]) { 53 | i = j++ 54 | } else { 55 | arr.swap(i - 1, i) 56 | if (--i == 0) { 57 | i = j++ 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /doc/ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Learn Algorithms Roadmap 2 | 3 | ## Step 1: Strengthen the Fundamentals 4 | Before diving into complex algorithms, ensure you have a solid grasp of data structures since they are the building blocks of algorithms. 5 | 6 | ### 📌 Topics to Cover: 7 | - **Arrays & Strings** 8 | - **Linked Lists** (Singly, Doubly, Circular) 9 | - **Stacks & Queues** 10 | - **Hash Tables / HashMaps** 11 | - **Trees** (Binary Trees, BST, Trie) 12 | - **Graphs** (Adjacency List, Adjacency Matrix) 13 | - **Heaps & Priority Queues** 14 | - **Dynamic Arrays & Bit Manipulation** 15 | 16 | ### 🛠 Resources: 17 | - *Algorithms, 4th Edition* by Robert Sedgewick 18 | - **LeetCode:** Easy problems in Array, HashMap, Linked List 19 | 20 | --- 21 | 22 | ## Step 2: Learn Basic Algorithmic Techniques 23 | Once you're comfortable with data structures, learn problem-solving techniques. 24 | 25 | ### 📌 Key Concepts: 26 | - **Sorting Algorithms:** Bubble, Selection, Insertion, Merge, Quick, Counting, Radix 27 | - **Searching Algorithms:** Binary Search, BFS, DFS 28 | - **Two Pointers Technique** 29 | - **Sliding Window** 30 | - **Greedy Algorithms** 31 | - **Recursion & Backtracking** 32 | - **Divide and Conquer** 33 | 34 | ### 🛠 Resources: 35 | - *Introduction to the Design and Analysis of Algorithms* by Anany Levitin 36 | - **LeetCode:** Medium-level sorting/search problems 37 | - **Practice:** Implement sorting algorithms from scratch in Kotlin 38 | 39 | --- 40 | 41 | ## Step 3: Master Advanced Algorithms 42 | After mastering the basics, move to more complex topics. 43 | 44 | ### 📌 Topics to Master: 45 | - **Dynamic Programming (DP):** Top-down, Bottom-up, Memoization, Tabulation 46 | - **Graph Algorithms:** Dijkstra, Bellman-Ford, Floyd-Warshall, A* 47 | - **Minimum Spanning Tree (MST):** Kruskal, Prim 48 | - **Network Flow:** Ford-Fulkerson 49 | - **String Algorithms:** KMP, Rabin-Karp, Suffix Arrays 50 | - **Number Theory:** GCD, LCM, Primes, Modular Arithmetic 51 | - **Bit Manipulation** 52 | 53 | ### 🛠 Resources: 54 | - *The Algorithm Design Manual* by Steven Skiena 55 | - **Practice:** LeetCode / Codeforces / AtCoder 56 | 57 | --- 58 | 59 | ## Step 4: Practice, Practice, Practice! 60 | 61 | ### 📌 Daily Goals: 62 | ✅ Solve **1-2 easy problems per day** → LeetCode Easy 63 | ✅ Gradually move to **1 medium per day** → LeetCode Medium 64 | ✅ Challenge yourself with **1 hard problem per week** 65 | 66 | ### 📌 Where to Practice: 67 | - **LeetCode** → Best for interviews and structured learning 68 | - **Codeforces** → Great for competitive programming 69 | - **AtCoder** → Ideal for mathematical problems 70 | - **Advent of Code** → Fun yearly challenge 71 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/math/NewtonMethodTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import dev.shtanko.algorithms.EPSILON 28 | import org.junit.jupiter.api.Assertions.assertEquals 29 | import org.junit.jupiter.api.Assertions.assertTrue 30 | import org.junit.jupiter.api.Test 31 | 32 | class NewtonMethodTest { 33 | @Test 34 | fun `calculate sqrt newton method test one`() { 35 | assertTrue(sqrt(-2.0).isNaN()) 36 | assertTrue(sqrt(-2.0, 0.toDouble()).isNaN()) 37 | assertEquals(2.0000000929222947, sqrt(4.toDouble()), 1e-15) 38 | assertEquals(4.000000636692939, sqrt(16.toDouble()), 1e-12) 39 | } 40 | 41 | @Test 42 | fun `sqrt returns correct square root for positive double input`() { 43 | val result = sqrt(2.25) 44 | assertEquals(1.5, result, EPSILON) 45 | } 46 | 47 | @Test 48 | fun `sqrt returns correct square root for zero input`() { 49 | val result = sqrt(0.0) 50 | assertEquals(0.0, result, EPSILON) 51 | } 52 | 53 | @Test 54 | fun `sqrt returns correct square root for large input`() { 55 | val largeNumber = 1e10 56 | val result = sqrt(largeNumber) 57 | assertEquals(sqrt(largeNumber), result, EPSILON) 58 | } 59 | 60 | @Test 61 | fun `calculate sqrt newton method test two`() { 62 | assertTrue(sqrt(-2).isNaN()) 63 | assertEquals(2.0000000929222947, sqrt(4), 1e-15) 64 | assertEquals(4.000000636692939, sqrt(16), 1e-12) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/math/NarcissisticNumberTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | abstract class NarcissisticNumberTest(private val strategy: T) { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `is armstrong number test`(number: Int, expected: Boolean) { 40 | val actual = strategy.isArmstrong(number) 41 | assertThat(actual).isEqualTo(expected) 42 | } 43 | 44 | private class InputArgumentsProvider : ArgumentsProvider { 45 | override fun provideArguments( 46 | parameters: ParameterDeclarations, 47 | context: ExtensionContext, 48 | ): Stream = Stream.of( 49 | Arguments.of(370, true), 50 | Arguments.of(225, false), 51 | Arguments.of(-23, false), 52 | Arguments.of(153, true), 53 | Arguments.of(0, true), 54 | Arguments.of(12, false), 55 | ) 56 | } 57 | } 58 | 59 | class NarcissisticNumberImplTest : NarcissisticNumberTest(NarcissisticNumberImpl) 60 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/IntX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import kotlin.random.Random 28 | 29 | private const val EVEN_DIVISOR = 2 30 | 31 | /** 32 | * Checks if an Int value is even. 33 | * 34 | * @return `true` if the Int value is even, `false` otherwise. 35 | */ 36 | val isEven = IntPredicate { it % EVEN_DIVISOR == 0 } 37 | 38 | /** 39 | * Checks if an Int value is even. 40 | * 41 | * @return `true` if the Int value is even, `false` otherwise. 42 | */ 43 | fun Int.isEven(): Boolean = this % EVEN_DIVISOR == 0 44 | 45 | /** 46 | * Generates an IntArray of the specified size with random values. 47 | * 48 | * @return The generated IntArray. 49 | */ 50 | fun Int.generateRandomArray(): IntArray { 51 | val array = IntArray(this) 52 | for (i in 0 until this) { 53 | array[i] = Random.nextInt(this) 54 | } 55 | return array 56 | } 57 | 58 | /** 59 | * Checks if an Int value is less than zero. 60 | * 61 | * @return `true` if the Int value is less than zero, `false` otherwise. 62 | */ 63 | fun Int.isLessThanZero(): Boolean = this < 0 64 | 65 | /** 66 | * Checks if an Int value is a prime number. 67 | * 68 | * @return `true` if the Int value is a prime number, `false` otherwise. 69 | */ 70 | fun Int.isPrime(): Boolean { 71 | if (this < 2) { 72 | return false 73 | } 74 | val root = kotlin.math.sqrt(this.toDouble()).toInt() 75 | for (divisor in EVEN_DIVISOR..root) { 76 | if (this % divisor == 0) { 77 | return false 78 | } 79 | } 80 | return true 81 | } 82 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/extensions/IntArrayXTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | class IntArrayXTest { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `reverse int array test`( 40 | arr: IntArray, 41 | start: Int, 42 | end: Int, 43 | expected: IntArray, 44 | ) { 45 | arr.reverse(start, end) 46 | assertThat(arr).isEqualTo(expected) 47 | } 48 | 49 | class InputArgumentsProvider : ArgumentsProvider { 50 | override fun provideArguments( 51 | parameters: ParameterDeclarations, 52 | context: ExtensionContext, 53 | ): Stream = Stream.of( 54 | Arguments.of(intArrayOf(), 0, 0, intArrayOf()), 55 | Arguments.of(intArrayOf(1), 0, 0, intArrayOf(1)), 56 | Arguments.of(intArrayOf(1, 3), 0, 2, intArrayOf(3, 1)), 57 | Arguments.of(intArrayOf(4, 8, 15, 16, 23, 42), 0, 6, intArrayOf(42, 23, 16, 15, 8, 4)), 58 | Arguments.of(intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9), 5, 9, intArrayOf(1, 2, 3, 4, 5, 9, 8, 7, 6)), 59 | ) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/search/BinarySearch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | /** 28 | * Implementation of the binary search algorithm using iteration. 29 | * 30 | * In computer science, binary search, also known as half-interval search, logarithmic search, or binary chop, is a 31 | * search algorithm that finds the position of a target value within a sorted array. 32 | * Binary search compares the target value to the middle element of the array. 33 | * 34 | * Worst-case performance O(log(n)) 35 | * Best-case performance O(1) 36 | * Average performance O(log(n)) 37 | * Worst-case space complexity O(1) 38 | * 39 | * @param T The type of elements in the array, must be comparable. 40 | */ 41 | class BinarySearch> : Searchable { 42 | /** 43 | * Performs the binary search operation on the given array to find the index of the specified element. 44 | * 45 | * @param arr The array to search. 46 | * @param element The element to search for. 47 | * @return The index of the element in the array, or -1 if the element is not found. 48 | */ 49 | override operator fun invoke( 50 | arr: Array, 51 | element: T, 52 | ): Int { 53 | var low = 0 54 | var high = arr.size - 1 55 | while (low <= high) { 56 | val mid = (low + high) / 2 57 | when { 58 | element < arr[mid] -> high = mid - 1 59 | element > arr[mid] -> low = mid + 1 60 | else -> return mid 61 | } 62 | } 63 | return -1 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/utils/ToHumanReadableByteCountBin.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import dev.shtanko.algorithms.BYTE 28 | import dev.shtanko.algorithms.DECIMAL 29 | import java.text.CharacterIterator 30 | import java.text.StringCharacterIterator 31 | import java.util.Locale 32 | import kotlin.math.abs 33 | 34 | // Bit mask used to determine the maximum value for byte conversion 35 | private const val BIT_MASK = 0xf_ffc_ccc_ccc_ccc_ccL 36 | private const val MAX_LOOP_INDEX = 40 37 | private const val UNITS = "KMGTPE" 38 | 39 | /** 40 | * Converts a long value to a human-readable byte count representation using 41 | * binary prefixes. 42 | * 43 | * @param formatter The formatter to use for converting the byte count to a 44 | * string representation. 45 | * Defaults to `siByteFormatter`. 46 | * @return The human-readable byte count representation. 47 | */ 48 | fun Long.toHumanReadableByteCountBin(formatter: ByteFormatter = siByteFormatter): String { 49 | val bytes = this 50 | val absBytes = if (bytes == Long.MIN_VALUE) Long.MAX_VALUE else abs(bytes) 51 | if (absBytes < BYTE) { 52 | return String.format(Locale.getDefault(), "%d B", bytes) 53 | } 54 | var value = absBytes 55 | val ci: CharacterIterator = StringCharacterIterator(UNITS) 56 | var i = MAX_LOOP_INDEX 57 | while (i >= 0 && absBytes > BIT_MASK shr i) { 58 | value = value shr DECIMAL 59 | ci.next() 60 | i -= DECIMAL 61 | } 62 | value *= java.lang.Long.signum(bytes) 63 | .toLong() 64 | val kiloBytes = value / BYTE.toDouble() 65 | val current = ci.current() 66 | 67 | return formatter.invoke(kiloBytes, current) 68 | } 69 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/QuickSortRecursive.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | /** 28 | * Recursive Quick Sort is a sorting algorithm that works by selecting a pivot element from the array and 29 | * partitioning the other elements into two sub-arrays, according to whether they are less than or greater 30 | * than the pivot. 31 | * It then recursively sorts the sub-arrays. This implementation uses a functional approach with Kotlin's 32 | * extension functions. 33 | * 34 | * Worst-case performance: O(n^2) 35 | * Best-case performance: O(n log n) 36 | * Average performance: O(n log n) 37 | * Worst-case space complexity: O(log n) 38 | */ 39 | data object QuickSortRecursive : Sortable { 40 | /** 41 | * Performs the recursive quick sort operation on the given array. 42 | * 43 | * @param arr The array to sort. 44 | * @param T The type of elements in the array, must be comparable. 45 | */ 46 | override fun > invoke(arr: Array) { 47 | val sorted = arr.toList().quickSort() 48 | for (i in sorted.indices) { 49 | arr[i] = sorted[i] 50 | } 51 | } 52 | } 53 | 54 | /** 55 | * Extension function to perform quick sort on a list of comparable elements. 56 | * 57 | * @receiver List The list to be sorted. 58 | * @return List A new list containing the sorted elements. 59 | */ 60 | fun > List.quickSort(): List = 61 | when { 62 | size < 2 -> this 63 | else -> { 64 | val pivot = first() 65 | val (smaller, greater) = drop(1).partition { it <= pivot } 66 | smaller.quickSort() + pivot + greater.quickSort() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/leetcode/AppealSumTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | abstract class AppealSumTest(private val strategy: T) { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `appeal sum test`(str: String, expected: Long) { 40 | val actual = strategy(str) 41 | assertThat(actual).isEqualTo(expected) 42 | } 43 | 44 | private class InputArgumentsProvider : ArgumentsProvider { 45 | override fun provideArguments( 46 | parameters: ParameterDeclarations, 47 | context: ExtensionContext, 48 | ): Stream = Stream.of( 49 | Arguments.of( 50 | "abbca", 51 | 28L, 52 | ), 53 | Arguments.of( 54 | "code", 55 | 20L, 56 | ), 57 | Arguments.of( 58 | "", 59 | 0L, 60 | ), 61 | Arguments.of( 62 | "a", 63 | 1L, 64 | ), 65 | Arguments.of( 66 | "ab", 67 | 4L, 68 | ), 69 | ) 70 | } 71 | } 72 | 73 | class AppealSumDpTest : AppealSumTest(appealSumDp) 74 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/search/StringSearchTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | abstract class StringSearchTest>(private val strategy: T) { 38 | @DisplayName("String Array Search Test") 39 | @ParameterizedTest(name = "Array: {0}, Element: {1} -> Expected: {2}") 40 | @ArgumentsSource(InputStringArrayArgumentsProvider::class) 41 | fun `string array test`( 42 | arr: Array, 43 | element: String, 44 | expected: Int, 45 | ) { 46 | val actual = strategy(arr, element) 47 | assertEquals(expected, actual) 48 | } 49 | 50 | private class InputStringArrayArgumentsProvider : ArgumentsProvider { 51 | override fun provideArguments( 52 | parameters: ParameterDeclarations, 53 | context: ExtensionContext, 54 | ): Stream = Stream.of( 55 | Arguments.of(arrayOf(), "A", -1), 56 | Arguments.of(arrayOf("A"), "A", 0), 57 | Arguments.of(arrayOf("A"), "B", -1), 58 | Arguments.of(arrayOf("A", "B"), "A", 0), 59 | Arguments.of(arrayOf("A", "B"), "B", 1), 60 | Arguments.of(arrayOf("A", "B"), "C", -1), 61 | ) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/sorts/QuickSortRecursiveTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | class QuickSortRecursiveTest { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `quick sort test`(list: List, expected: List) { 40 | val actual = list.quickSort() 41 | assertEquals(expected, actual) 42 | } 43 | 44 | class InputArgumentsProvider : ArgumentsProvider { 45 | override fun provideArguments( 46 | parameters: ParameterDeclarations, 47 | context: ExtensionContext, 48 | ): Stream = Stream.of( 49 | Arguments.of( 50 | listOf(), 51 | listOf(), 52 | ), 53 | Arguments.of( 54 | listOf(1), 55 | listOf(1), 56 | ), 57 | Arguments.of( 58 | listOf(1, 2, 3), 59 | listOf(1, 2, 3), 60 | ), 61 | Arguments.of( 62 | listOf(3, 2, 1), 63 | listOf(1, 2, 3), 64 | ), 65 | Arguments.of( 66 | listOf(5, 0, 1, 5, 3, 7, 4, 2), 67 | listOf(0, 1, 2, 3, 4, 5, 5, 7), 68 | ), 69 | ) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/ShellSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.swap 28 | 29 | /** 30 | * Shell sort is an in-place comparison sort that can be seen as either a generalization of insertion sort or a 31 | * variation of bubble sort. It starts by sorting pairs of elements far apart from each other and progressively 32 | * reducing the gap between elements to be compared. The final iteration uses a gap of 1, which is equivalent to 33 | * an insertion sort. The algorithm's time complexity depends on the chosen gap sequence. 34 | * 35 | * Worst-case performance: O(n^2) 36 | * Best-case performance: O(n log n) 37 | * Average performance: Depends on the gap sequence 38 | * Worst-case space complexity: O(1) 39 | * Stable: No 40 | */ 41 | data object ShellSort : Sortable { 42 | // Constant used to calculate the gap sequence 43 | const val GAP = 3 44 | 45 | /** 46 | * Performs the Shell sort operation on the given array. 47 | * 48 | * @param arr The array to sort. 49 | * @param T The type of elements in the array, must be comparable. 50 | */ 51 | override fun > invoke(arr: Array) { 52 | val size = arr.size 53 | var gap = 1 54 | while (gap < size / GAP) { 55 | gap = gap * GAP + 1 56 | } 57 | 58 | while (gap >= 1) { 59 | for (i in gap until size) { 60 | var j = i 61 | while (j >= gap && arr[j - gap] > arr[j]) { 62 | arr.swap(j, j - gap) 63 | j -= gap 64 | } 65 | } 66 | // Reduce the gap for the next iteration 67 | gap /= GAP 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/math/GCDTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | class GCDTest { 38 | @DisplayName("GCD Iterative Test") 39 | @ParameterizedTest(name = "a: {0}, b: {1} -> gcd: {2}") 40 | @ArgumentsSource(InputArgumentsProvider::class) 41 | fun `gcd pair test`( 42 | a: Int, 43 | b: Int, 44 | expected: Int, 45 | ) { 46 | val actual = (a to b).gcd() 47 | assertEquals(expected, actual) 48 | } 49 | 50 | @DisplayName("GCD Recursive Test") 51 | @ParameterizedTest(name = "a: {0}, b: {1} -> gcd: {2}") 52 | @ArgumentsSource(InputArgumentsProvider::class) 53 | fun `gcd recursive test`( 54 | a: Int, 55 | b: Int, 56 | expected: Int, 57 | ) { 58 | val actual = gcd(a, b) 59 | assertEquals(expected, actual) 60 | } 61 | 62 | class InputArgumentsProvider : ArgumentsProvider { 63 | override fun provideArguments( 64 | parameters: ParameterDeclarations, 65 | context: ExtensionContext, 66 | ): Stream = Stream.of( 67 | Arguments.of(54, 24, 6), 68 | Arguments.of(42, 56, 14), 69 | Arguments.of(48, 18, 6), 70 | Arguments.of(48, 180, 12), 71 | ) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/graph/BreadthFirstSearch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.graph 26 | 27 | import java.util.LinkedList 28 | 29 | /** 30 | * Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. 31 | * It starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a 'search key') 32 | * and explores the neighbor nodes first, before moving to the next level neighbors. 33 | */ 34 | @Suppress("GENERIC_VARIABLE_WRONG_DECLARATION") 35 | object BreadthFirstSearch : GraphTraverseStrategy { 36 | /** 37 | * Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. 38 | * It starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a 'search key') 39 | * and explores the neighbor nodes first, before moving to the next level neighbors. 40 | * 41 | * @param graph The graph to traverse. 42 | * @param start The starting node. 43 | * @return The list of nodes in the order they were visited. 44 | */ 45 | override operator fun invoke(graph: Graph, start: Int): List { 46 | if (!graph.containsKey(start)) { 47 | return emptyList() 48 | } 49 | val queue = LinkedList() 50 | queue.offer(start) 51 | val visited = mutableSetOf() 52 | visited.add(start) 53 | val result = mutableListOf() 54 | 55 | while (queue.isNotEmpty()) { 56 | val node = queue.poll() ?: return emptyList() 57 | result.add(node) 58 | 59 | graph[node]?.forEach { neighbor -> 60 | if (neighbor !in visited) { 61 | queue.offer(neighbor) 62 | visited.add(neighbor) 63 | } 64 | } 65 | } 66 | 67 | return result 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/NarcissisticNumber.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import dev.shtanko.algorithms.DECIMAL 28 | import kotlin.math.pow 29 | 30 | /** 31 | * Functional interface representing a narcissistic number check. 32 | */ 33 | fun interface NarcissisticNumber { 34 | /** 35 | * Checks whether the given number is an Armstrong number. 36 | * 37 | * @param number The number to check. 38 | * @return `true` if the number is an Armstrong number, `false` otherwise. 39 | */ 40 | fun isArmstrong(number: Int): Boolean 41 | } 42 | 43 | /** 44 | * Implementation of the NarcissisticNumber interface. 45 | */ 46 | data object NarcissisticNumberImpl : NarcissisticNumber { 47 | /** 48 | * Checks whether the given number is an Armstrong number. 49 | * 50 | * @param number The number to check. 51 | * @return `true` if the number is an Armstrong number, `false` otherwise. 52 | */ 53 | override fun isArmstrong(number: Int): Boolean { 54 | if (number < 0) { 55 | return false 56 | } 57 | var sum = 0 58 | var temp = number 59 | val totalDigits = numberOfDigits(number) 60 | while (temp > 0) { 61 | val rem = temp % DECIMAL 62 | sum += rem.toDouble().pow(totalDigits.toDouble()).toInt() 63 | temp /= DECIMAL 64 | } 65 | return number == sum 66 | } 67 | 68 | /** 69 | * Calculates the number of digits in the given number. 70 | * 71 | * @param num The number to calculate the number of digits for. 72 | * @return The number of digits in the given number. 73 | */ 74 | private fun numberOfDigits(num: Int): Int { 75 | var res = num 76 | var totalDigits = 0 77 | while (res > 0) { 78 | res /= DECIMAL 79 | totalDigits++ 80 | } 81 | return totalDigits 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/math/BinomialTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | class BinomialTest { 38 | @DisplayName("Binomial Test") 39 | @ParameterizedTest(name = "n: {0}, k: {1} -> Expected: {2}") 40 | @ArgumentsSource(InputArgumentsProvider::class) 41 | fun `binomial coefficient test`( 42 | n: Int, 43 | k: Int, 44 | expected: Long, 45 | ) { 46 | val actual = binomial(n, k) 47 | assertThat(actual).isEqualTo(expected) 48 | } 49 | 50 | class InputArgumentsProvider : ArgumentsProvider { 51 | override fun provideArguments( 52 | parameters: ParameterDeclarations, 53 | context: ExtensionContext, 54 | ): Stream = Stream.of( 55 | Arguments.of(0, 1, 0), 56 | Arguments.of(1, 1, 1), 57 | Arguments.of(2, 1, 2), 58 | Arguments.of(3, 1, 3), 59 | Arguments.of(3, 2, 3), 60 | Arguments.of(4, 1, 4), 61 | Arguments.of(5, 0, 1), 62 | Arguments.of(5, 1, 5), 63 | Arguments.of(5, 2, 10), 64 | Arguments.of(5, 3, 10), 65 | Arguments.of(5, 4, 5), 66 | Arguments.of(5, 5, 1), 67 | Arguments.of(6, 0, 1), 68 | Arguments.of(6, 1, 6), 69 | Arguments.of(6, 2, 15), 70 | Arguments.of(6, 3, 20), 71 | Arguments.of(6, 4, 15), 72 | Arguments.of(6, 5, 6), 73 | ) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/search/BinaryRecursiveSearch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | /** 28 | * Implementation of the binary search algorithm using recursion. 29 | * Binary search is an algorithm which finds the position of a target value within an array (Sorted) 30 | * 31 | * Worst-case performance O(log(n)) 32 | * Best-case performance O(1) 33 | * Average performance O(log(n)) 34 | * Worst-case space complexity O(1) 35 | * 36 | * @param T The type of elements in the array, must be comparable. 37 | */ 38 | class BinaryRecursiveSearch> : Searchable { 39 | /** 40 | * Performs the binary search operation on the given array to find the index of the specified element. 41 | * 42 | * @param arr The array to search. 43 | * @param element The element to search for. 44 | * @return The index of the element in the array, or -1 if the element is not found. 45 | */ 46 | override operator fun invoke( 47 | arr: Array, 48 | element: T, 49 | ): Int = arr.search(0, arr.size - 1, element) 50 | 51 | /** 52 | * Recursive helper function to perform the binary search. 53 | * 54 | * @param low The lower bound of the search range. 55 | * @param high The upper bound of the search range. 56 | * @param element The element to search for. 57 | * @return The index of the element in the array, or -1 if the element is not found. 58 | */ 59 | private fun Array.search( 60 | low: Int, 61 | high: Int, 62 | element: T, 63 | ): Int { 64 | if (high >= low) { 65 | val mid = low.plus(high).div(2) 66 | 67 | if (this[mid] == element) { 68 | return mid 69 | } 70 | 71 | if (this[mid] > element) { 72 | return this.search(low, mid - 1, element) 73 | } 74 | return search(mid + 1, high, element) 75 | } 76 | return -1 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | 74 | 75 | @rem Execute Gradle 76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 77 | 78 | :end 79 | @rem End local scope for the variables with windows NT shell 80 | if %ERRORLEVEL% equ 0 goto mainEnd 81 | 82 | :fail 83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 84 | rem the _cmd.exe /c_ return code! 85 | set EXIT_CODE=%ERRORLEVEL% 86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 88 | exit /b %EXIT_CODE% 89 | 90 | :mainEnd 91 | if "%OS%"=="Windows_NT" endlocal 92 | 93 | :omega 94 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/utils/MeasureTime.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import dev.shtanko.algorithms.sorts.Sortable 28 | import java.util.Locale 29 | import java.util.concurrent.TimeUnit 30 | import kotlin.system.measureNanoTime 31 | import kotlin.time.DurationUnit 32 | import kotlin.time.toTimeUnit 33 | 34 | /** 35 | * Measures the execution time of a task using the specified `unit` for the result. 36 | * 37 | * @param unit The desired time unit for the result. 38 | * @param task The task to measure the execution time of. 39 | * @return The elapsed time in the specified time unit. 40 | */ 41 | fun measureTime( 42 | unit: DurationUnit, 43 | task: () -> Unit, 44 | ): Long = unit.toTimeUnit().convert(measureNanoTime(task), TimeUnit.NANOSECONDS) 45 | 46 | /** 47 | * Measures the execution time of a task and prints the result. 48 | * The task is associated with a strategy and an array length. 49 | * 50 | * @param strategy The strategy associated with the task. 51 | * @param array The array associated with the task. 52 | * @param task The task to measure the execution time of. 53 | */ 54 | @Suppress("DEBUG_PRINT") 55 | fun measureTime( 56 | strategy: Sortable, 57 | array: IntArray, 58 | task: () -> Unit, 59 | ) { 60 | val elapsed = measureTime(DurationUnit.MILLISECONDS, task) 61 | println( 62 | String.format( 63 | Locale.getDefault(), 64 | "Arrays of length %d Strategy %s Consumed time: %d ms", 65 | array.size, 66 | strategy::class.java.simpleName, 67 | elapsed, 68 | ), 69 | ) 70 | } 71 | 72 | /** 73 | * Measures the execution time of a task and prints the result. 74 | * 75 | * @param taskName The name of the task. 76 | * @param task The task to measure the execution time of. 77 | */ 78 | @Suppress("DEBUG_PRINT") 79 | fun measureTime( 80 | taskName: String, 81 | task: () -> Unit, 82 | ) { 83 | val elapsed = measureTime(DurationUnit.MILLISECONDS, task) 84 | println(String.format(Locale.getDefault(), "Task %s Consumed time: %d ms", taskName, elapsed)) 85 | } 86 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/leetcode/MinDistanceTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | abstract class MinDistanceTest(private val strategy: T) { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `min distance test`( 40 | word1: String, 41 | word2: String, 42 | expected: Int, 43 | ) { 44 | val actual = strategy(word1, word2) 45 | assertThat(actual).isEqualTo(expected) 46 | } 47 | 48 | class InputArgumentsProvider : ArgumentsProvider { 49 | override fun provideArguments( 50 | parameters: ParameterDeclarations, 51 | context: ExtensionContext, 52 | ): Stream = Stream.of( 53 | Arguments.of( 54 | "", 55 | "", 56 | 0, 57 | ), 58 | Arguments.of( 59 | "q", 60 | "q", 61 | 0, 62 | ), 63 | Arguments.of( 64 | "sea", 65 | "eat", 66 | 2, 67 | ), 68 | Arguments.of( 69 | "leetcode", 70 | "etco", 71 | 4, 72 | ), 73 | ) 74 | } 75 | } 76 | 77 | class MinDistanceLcsTest : MinDistanceTest(minDistanceLcs) 78 | class MinDistanceLcsMemoTest : MinDistanceTest(minDistanceLcsMemo) 79 | class MinDistanceLcsDpTest : MinDistanceTest(minDistanceLcsDp) 80 | class MinDistanceDpTest : MinDistanceTest(minDistanceDp) 81 | class MinDistance1DdpTest : MinDistanceTest(minDistance1Ddp) 82 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/utils/CharArrayExtTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import dev.shtanko.algorithms.extensions.reverse 28 | import org.junit.jupiter.api.Assertions.assertArrayEquals 29 | import org.junit.jupiter.api.DisplayName 30 | import org.junit.jupiter.api.extension.ExtensionContext 31 | import org.junit.jupiter.params.ParameterizedTest 32 | import org.junit.jupiter.params.provider.Arguments 33 | import org.junit.jupiter.params.provider.ArgumentsProvider 34 | import org.junit.jupiter.params.provider.ArgumentsSource 35 | import org.junit.jupiter.params.support.ParameterDeclarations 36 | import java.util.stream.Stream 37 | 38 | class CharArrayExtTest { 39 | @DisplayName("Reverse Char Array") 40 | @ParameterizedTest(name = "Array: {0}, Left: {1}, Right: {2} -> Expected: {3}") 41 | @ArgumentsSource(InputArgumentsProvider::class) 42 | fun `reverse char array test`( 43 | arr: CharArray, 44 | left: Int, 45 | right: Int, 46 | expected: CharArray, 47 | ) { 48 | arr.reverse(left, right) 49 | assertArrayEquals(expected, arr) 50 | } 51 | 52 | private class InputArgumentsProvider : ArgumentsProvider { 53 | override fun provideArguments( 54 | parameters: ParameterDeclarations, 55 | context: ExtensionContext, 56 | ): Stream = Stream.of( 57 | Arguments.of( 58 | charArrayOf(), 59 | 0, 60 | 0, 61 | charArrayOf(), 62 | ), 63 | Arguments.of( 64 | charArrayOf('a', 'b', 'c', 'd'), 65 | 0, 66 | 0, 67 | charArrayOf('a', 'b', 'c', 'd'), 68 | ), 69 | Arguments.of( 70 | charArrayOf('a', 'b'), 71 | 0, 72 | 1, 73 | charArrayOf('b', 'a'), 74 | ), 75 | Arguments.of( 76 | charArrayOf('a', 'b'), 77 | 1, 78 | 0, 79 | charArrayOf('a', 'b'), 80 | ), 81 | ) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/utils/HumanReadableDurationTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.utils 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | class HumanReadableDurationTest { 38 | @DisplayName("Human Readable Duration") 39 | @ParameterizedTest(name = "Duration: {0} -> Expected: {1}") 40 | @ArgumentsSource(InputArgumentsProvider::class) 41 | fun `to human readable duration test`(duration: Long, expected: String) { 42 | val actual = duration.toHumanReadableDuration() 43 | assertThat(actual).isEqualTo(expected) 44 | } 45 | 46 | private class InputArgumentsProvider : ArgumentsProvider { 47 | override fun provideArguments( 48 | parameters: ParameterDeclarations, 49 | context: ExtensionContext, 50 | ): Stream = Stream.of( 51 | Arguments.of( 52 | 0L, 53 | "Runtime: 0 ms", 54 | ), 55 | Arguments.of( 56 | 1_000_000L, 57 | "Runtime: 1 ms", 58 | ), 59 | Arguments.of( 60 | 2_000_000L, 61 | "Runtime: 2 ms", 62 | ), 63 | Arguments.of( 64 | 12_000_000, 65 | "Runtime: 12 ms", 66 | ), 67 | Arguments.of( 68 | 56_000_000, 69 | "Runtime: 56 ms", 70 | ), 71 | Arguments.of( 72 | 65_700_000_000, 73 | "Runtime: 65,700 ms", 74 | ), 75 | Arguments.of( 76 | 99_900_000_000, 77 | "Runtime: 99,900 ms", 78 | ), 79 | ) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/search/IntSearchTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.search 26 | 27 | import org.junit.jupiter.api.Assertions.assertEquals 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | @Suppress("ArrayPrimitive") 38 | abstract class IntSearchTest>(private val strategy: T) { 39 | @DisplayName("Int Array Search Test") 40 | @ParameterizedTest(name = "Array: {0}, Element: {1} -> Expected: {2}") 41 | @ArgumentsSource(InputIntArrayArgumentsProvider::class) 42 | fun `int array test`( 43 | arr: Array, 44 | element: Int, 45 | expected: Int, 46 | ) { 47 | val actual = strategy(arr, element) 48 | assertEquals(expected, actual) 49 | } 50 | 51 | private class InputIntArrayArgumentsProvider : ArgumentsProvider { 52 | override fun provideArguments( 53 | parameters: ParameterDeclarations, 54 | context: ExtensionContext, 55 | ): Stream = Stream.of( 56 | Arguments.of(arrayOf(), 1, -1), 57 | Arguments.of(arrayOf(1), 1, 0), 58 | Arguments.of(arrayOf(1), 2, -1), 59 | Arguments.of(arrayOf(4, 8), 4, 0), 60 | Arguments.of(arrayOf(4, 8), 8, 1), 61 | Arguments.of(arrayOf(4, 8), 9, -1), 62 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 4, 0), 63 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 8, 1), 64 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 15, 2), 65 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 16, 3), 66 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 23, 4), 67 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 42, 5), 68 | Arguments.of(arrayOf(4, 8, 15, 16, 23, 42), 43, -1), 69 | ) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/InsertionSorts.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.swap 28 | 29 | /** 30 | * Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. 31 | * Each iteration, insertion sort removes one element from the input data, finds the location it belongs within 32 | * the sorted list, and inserts it there. It repeats until no input elements remain. 33 | * 34 | * Worst-case performance: O(n^2) 35 | * Best-case performance: O(n) 36 | * Average performance: O(n^2) 37 | * Worst-case space complexity: O(1) 38 | */ 39 | data object InsertionSort : Sortable { 40 | /** 41 | * Performs the insertion sort operation on the given array. 42 | * 43 | * @param arr The array to sort. 44 | * @param T The type of elements in the array, must be comparable. 45 | */ 46 | override fun > invoke(arr: Array) { 47 | for (i in 1 until arr.size) { 48 | for (j in i downTo 1) { 49 | if (arr[j - 1] < arr[j]) { 50 | break 51 | } 52 | arr.swap(j, j - 1) 53 | } 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * Implementation of the generic insertion sort algorithm. 60 | * 61 | * Worst-case performance: O(n^2) 62 | * Best-case performance: O(n) 63 | * Average performance: O(n^2) 64 | * Worst-case space complexity: O(1) 65 | */ 66 | data object InsertionSort2 : Sortable { 67 | /** 68 | * Performs the insertion sort operation on the given array. 69 | * 70 | * @param arr The array to sort. 71 | * @param T The type of elements in the array, must be comparable. 72 | */ 73 | override fun > invoke(arr: Array) { 74 | for (currentIndex in 1 until arr.size) { 75 | val currentValue = arr[currentIndex] 76 | var j = currentIndex 77 | while (j > 0 && arr[j - 1] > currentValue) { 78 | arr[j] = arr[j - 1] 79 | j-- 80 | } 81 | arr[j] = currentValue 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/math/Fibonacci.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | /** 28 | * Enum class representing different strategies for calculating Fibonacci numbers. 29 | */ 30 | enum class Fibonacci { 31 | ITERATIVE { 32 | override fun invoke(index: Long): Long = 33 | if (index < 2) { 34 | index 35 | } else { 36 | var previous = 0L 37 | var current = 1L 38 | var remainingSteps = index 39 | do { 40 | val sum = previous + current 41 | previous = current 42 | current = sum 43 | } while (remainingSteps-- > 1) 44 | previous 45 | } 46 | }, 47 | RECURSIVE { 48 | override fun invoke(index: Long): Long = if (index < 2) { 49 | index 50 | } else { 51 | this(index - 1) + this(index - 2) 52 | } 53 | }, 54 | ; 55 | 56 | /** 57 | * Calculates the Fibonacci number at the given index using the specified strategy. 58 | * 59 | * @param index The index of the Fibonacci number. 60 | * @return The Fibonacci number at the given index. 61 | */ 62 | abstract operator fun invoke(index: Long): Long 63 | } 64 | 65 | /** 66 | * Calculates the Fibonacci number at the given index using recursion. 67 | * 68 | * @receiver The index of the Fibonacci number. 69 | * @return The Fibonacci number at the given index. 70 | */ 71 | fun Int.toFibonacciSequence(): Int { 72 | if (this <= 1) { 73 | return this 74 | } 75 | return (this - 1).toFibonacciSequence() + (this - 2).toFibonacciSequence() 76 | } 77 | 78 | /** 79 | * Calculates the Fibonacci number at the given index using iteration. 80 | * 81 | * @param num The index of the Fibonacci number. 82 | * @return The Fibonacci number at the given index. 83 | */ 84 | fun fibonacciAt(num: Int) = 85 | run { 86 | tailrec fun fibonacciAcc( 87 | count: Int, 88 | prev: Long, 89 | curr: Long, 90 | ): Long = when (count == 0) { 91 | true -> curr 92 | false -> fibonacciAcc(count - 1, prev + curr, prev) 93 | } 94 | fibonacciAcc(num, 1, 0) 95 | } 96 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/bitwise/BinaryRepresentationTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.bitwise 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | class BinaryRepresentationTest { 37 | @ParameterizedTest 38 | @ArgumentsSource(LongArgs::class) 39 | fun `long to bin string test`(n: Long, expected: String) { 40 | val actual = n.bin() 41 | assertThat(actual).isEqualTo(expected) 42 | } 43 | 44 | private class LongArgs : ArgumentsProvider { 45 | override fun provideArguments( 46 | parameters: ParameterDeclarations, 47 | context: ExtensionContext, 48 | ): Stream = Stream.of( 49 | Arguments.of( 50 | 7L, 51 | "00000000000000000000000000000111", 52 | ), 53 | Arguments.of( 54 | 4L, 55 | "00000000000000000000000000000100", 56 | ), 57 | Arguments.of( 58 | 0L, 59 | "00000000000000000000000000000000", 60 | ), 61 | Arguments.of( 62 | 1L, 63 | "00000000000000000000000000000001", 64 | ), 65 | Arguments.of( 66 | 2L, 67 | "00000000000000000000000000000010", 68 | ), 69 | Arguments.of( 70 | 234L, 71 | "00000000000000000000000011101010", 72 | ), 73 | Arguments.of( 74 | 2_342_354_676L, 75 | "00001011100111010111111011110100", 76 | ), 77 | Arguments.of( 78 | Long.MAX_VALUE, 79 | "01111111111111111111111111111111", 80 | ), 81 | Arguments.of( 82 | Long.MIN_VALUE, 83 | "00000000000000000000000000000000", 84 | ), 85 | ) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/leetcode/dp/linear/ClimbingStairsTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode.dp.linear 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | abstract class ClimbingStairsTest(private val strategy: T) { 37 | private class InputArgumentsProvider : ArgumentsProvider { 38 | override fun provideArguments( 39 | parameters: ParameterDeclarations, 40 | context: ExtensionContext, 41 | ): Stream = Stream.of( 42 | Arguments.of( 43 | 0, 44 | 0, 45 | ), 46 | Arguments.of( 47 | 1, 48 | 1, 49 | ), 50 | Arguments.of( 51 | 2, 52 | 2, 53 | ), 54 | Arguments.of( 55 | 3, 56 | 3, 57 | ), 58 | Arguments.of( 59 | 5, 60 | 8, 61 | ), 62 | Arguments.of( 63 | 20, 64 | 10946, 65 | ), 66 | Arguments.of( 67 | 30, 68 | 1346269, 69 | ), 70 | Arguments.of( 71 | 40, 72 | 165580141, 73 | ), 74 | Arguments.of( 75 | 60, 76 | 764848393, 77 | ), 78 | Arguments.of( 79 | 70, 80 | 696897233, 81 | ), 82 | ) 83 | } 84 | 85 | @ParameterizedTest 86 | @ArgumentsSource(InputArgumentsProvider::class) 87 | fun `climbing stairs test`(num: Int, expected: Int) { 88 | val actual = strategy(num) 89 | assertThat(actual).isEqualTo(expected) 90 | } 91 | } 92 | 93 | class ClimbingStairsBottomUpDPTest : ClimbingStairsTest(climbingStairsBottomUpDp) 94 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/extensions/CharXTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.extension.ExtensionContext 29 | import org.junit.jupiter.params.ParameterizedTest 30 | import org.junit.jupiter.params.provider.Arguments 31 | import org.junit.jupiter.params.provider.ArgumentsProvider 32 | import org.junit.jupiter.params.provider.ArgumentsSource 33 | import org.junit.jupiter.params.support.ParameterDeclarations 34 | import java.util.stream.Stream 35 | 36 | class CharXTest { 37 | @ParameterizedTest 38 | @ArgumentsSource(InputArgumentsProvider::class) 39 | fun `random string test`( 40 | range: CharRange, 41 | len: Int, 42 | expected: Int, 43 | ) { 44 | val randomString = range.randomString(len) 45 | val actual = randomString.length 46 | assertThat(actual).isEqualTo(expected) 47 | } 48 | 49 | @ParameterizedTest 50 | @ArgumentsSource(InputVowelArgumentsProvider::class) 51 | fun `is vowel test`(c: Char, expected: Boolean) { 52 | val actual = c.isVowel() 53 | assertThat(actual).isEqualTo(expected) 54 | } 55 | 56 | class InputArgumentsProvider : ArgumentsProvider { 57 | override fun provideArguments( 58 | parameters: ParameterDeclarations, 59 | context: ExtensionContext, 60 | ): Stream = Stream.of( 61 | Arguments.of('a'..'z', 0, 0), 62 | Arguments.of('a'..'z', 6, 6), 63 | Arguments.of('A'..'Z', 6, 6), 64 | Arguments.of('A'..'Z', 600, 600), 65 | ) 66 | } 67 | 68 | class InputVowelArgumentsProvider : ArgumentsProvider { 69 | override fun provideArguments( 70 | parameters: ParameterDeclarations, 71 | context: ExtensionContext, 72 | ): Stream = Stream.of( 73 | Arguments.of('a', true), 74 | Arguments.of('e', true), 75 | Arguments.of('i', true), 76 | Arguments.of('o', true), 77 | Arguments.of('u', true), 78 | Arguments.of('r', false), 79 | Arguments.of('q', false), 80 | Arguments.of('z', false), 81 | Arguments.of('x', false), 82 | ) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/leetcode/AppealSum.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode 26 | 27 | import dev.shtanko.algorithms.ALPHABET_LETTERS_COUNT 28 | 29 | /** 30 | * # Intuition 31 | * The problem is to calculate the sum of the appeal of all substrings of a 32 | * given string. The appeal of a string is defined as the number of distinct 33 | * characters in it. The challenge is to efficiently compute this for all 34 | * substrings. 35 | * 36 | * # Approach 37 | * We can use dynamic programming to solve this problem. The key idea is to keep 38 | * track of the last position where each character appeared. For each character 39 | * in the string, we can calculate the contribution to the total appeal based on 40 | * its position and the previous positions of the same character. We maintain an 41 | * array `prev` where `prev[char - 'a']` keeps the last index of character 42 | * `char`. For each character at index `i`, the contribution to the appeal 43 | * is calculated as `i + 1 - prev[char - 'a']`. We then update the `prev` array 44 | * with the current index. 45 | * 46 | * # Complexity 47 | * - Time complexity: O(n) 48 | * The time complexity is linear with respect to the length of the string, since 49 | * we process each character exactly once. 50 | * 51 | * - Space complexity: O(1) 52 | * The space complexity is constant, as we use a fixed-size array of length 26 53 | * to keep track of the last positions of each 54 | * character (assuming only lowercase English letters). 55 | */ 56 | val appealSumDp = AppealSum { str: String -> 57 | var cur: Long = 0 58 | val prev = LongArray(ALPHABET_LETTERS_COUNT) 59 | str.mapIndexed { index, char -> 60 | cur += index + 1 - prev[char - 'a'] 61 | prev[char - 'a'] = index.toLong() + 1 62 | cur 63 | }.sum() 64 | } 65 | 66 | /** 67 | * 2262. Total Appeal of A String 68 | * @see 69 | * Source 70 | * Functional interface representing an appeal sum operation on a String. 71 | */ 72 | fun interface AppealSum { 73 | /** 74 | * Performs an appeal sum operation on the given String. 75 | * 76 | * @param str The input String to perform the appeal sum on. 77 | * @return The result of the appeal sum operation. 78 | */ 79 | operator fun invoke(str: String): Long 80 | } 81 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/HeapSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.swap 28 | 29 | /** 30 | * Heap sort is a comparison-based sorting algorithm that uses a binary heap data structure. 31 | * It divides the input into a sorted and an unsorted region, and it iteratively shrinks the unsorted region 32 | * by extracting the largest element from it and inserting it into the sorted region. The algorithm 33 | * efficiently builds a max heap on the input array to facilitate the extraction of maximum elements. 34 | * 35 | * Worst-case performance: O(n log n) 36 | * Best-case performance: O(n log n) 37 | * Average performance: O(n log n) 38 | * Worst-case space complexity: O(1) 39 | */ 40 | data object HeapSort : Sortable { 41 | /** 42 | * Performs the heap sort operation on the given array. 43 | * 44 | * @param arr The array to sort. 45 | * @param T The type of elements in the array, must be comparable. 46 | */ 47 | override fun > invoke(arr: Array) { 48 | val size = arr.size 49 | for (i in size / 2 - 1 downTo 0) { 50 | heapify(arr, size, i) 51 | } 52 | 53 | for (i in size - 1 downTo 0) { 54 | arr.swap(0, i) 55 | heapify(arr, i, 0) 56 | } 57 | } 58 | 59 | /** 60 | * Performs heapify operation on the array. 61 | * 62 | * @param array The array to heapify. 63 | * @param size The size of the heap. 64 | * @param index The index of the current element in the heap. 65 | * @param T The type of elements in the array, must be comparable. 66 | */ 67 | @Suppress("SAY_NO_TO_VAR") 68 | private fun > heapify( 69 | array: Array, 70 | size: Int, 71 | index: Int, 72 | ) { 73 | var largest = index 74 | val left = 2 * index + 1 75 | val right = 2 * index + 2 76 | 77 | if (left < size && array[left] > array[largest]) { 78 | largest = left 79 | } 80 | 81 | if (right < size && array[right] > array[largest]) { 82 | largest = right 83 | } 84 | 85 | if (largest != index) { 86 | array.swap(index, largest) 87 | heapify(array, size, largest) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/README.md: -------------------------------------------------------------------------------- 1 | ```kotlin 2 | 3 | sealed interface Complexity { 4 | /** 5 | * O(1) 6 | * Provides an unvarying execution time, no matter how much input you provide. 7 | * Each input requires a single unit of execution time. 8 | */ 9 | data object Constant : Complexity() 10 | 11 | /** 12 | * O(log n) 13 | * The number of operations grows at a slower rate than the input, 14 | * making the algorithm less efficient with small inputs and more efficient with larger ones. 15 | * A typical algorithm of this class is the binary search. 16 | */ 17 | data object Logarithmic : Complexity() 18 | 19 | /** 20 | * O(n) 21 | * Operations grow with the input in a 1:1 ratio. 22 | * A typical algorithm is iteration, when you scan input once and apply an operation to each element of it. 23 | */ 24 | data object Linear : Complexity() 25 | 26 | /** 27 | * O(n log n) 28 | * Complexity is a mix between logarithmic and linear complexity. 29 | * It is typical of some smart algorithms used to order data, such as Mergesortsort, Heapsort, and Quicksort. 30 | */ 31 | data object Linearithmic : Complexity() 32 | 33 | /** 34 | * O(n2) 35 | * Operations grow as a square of the number of inputs. 36 | * When you have one iteration inside another iteration (called nested iterations in computer science), 37 | * you have quadratic complexity. For instance, you have a list of names and, 38 | * in order to find the most similar ones, you compare each name against all the other names. 39 | * Some less efficient ordering algorithms present such complexity: bubble sort, selection sort, and insertion sort. 40 | * This level of complexity means that your algorithms may run for hours or even days before reaching a solution. 41 | */ 42 | data object Quadratic : Complexity() 43 | 44 | /** 45 | * O(n3) 46 | * Operations grow even faster than quadratic complexity because now you have multiple nested iterations. 47 | * When an algorithm has this order of complexity and you need to process a modest amount of data (100,000 elements), 48 | * your algorithm may run for years. When you have a number of operations that is a power of the input, 49 | * it is common to refer to the algorithm as running in polynomial time. 50 | */ 51 | data object Cubic : Complexity() 52 | 53 | /** 54 | * O(2n) 55 | * The algorithm takes twice the number of previous operations for every new element added. 56 | * When an algorithm has this complexity, even small problems may take forever. 57 | * Many algorithms doing exhaustive searches have exponential complexity. 58 | * However, the classic example for this level of complexity is the calculation of Fibonacci numbers. 59 | */ 60 | data object Exponential : Complexity() 61 | 62 | /** 63 | * O(n!) 64 | * This algorithm presents a real nightmare of complexity because of the large number of possible combinations 65 | * between the elements. Just imagine: If your input is 100 objects, 66 | * and an operation on your computer takes 10-6 seconds (a reasonable speed for every computer nowadays), 67 | * you will need about 10140 years to complete the task successfully (an impossible amount of time because the 68 | * age of the universe is estimated as being 1014 years). A famous factorial complexity problem is the traveling 69 | * salesman problem, in which a salesman has to find the shortest route for visiting many cities 70 | * and coming back to the starting city. 71 | */ 72 | data object Factorial : Complexity() 73 | } 74 | 75 | ``` 76 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/math/MatrixTranspositionTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.math 26 | 27 | import org.assertj.core.api.Assertions.assertThat 28 | import org.junit.jupiter.api.DisplayName 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | class MatrixTranspositionTest { 38 | @DisplayName("Transposes the matrix by swapping rows and columns") 39 | @ParameterizedTest(name = "matrix: {0} -> Expected: {1}") 40 | @ArgumentsSource(InputArgumentsProvider::class) 41 | fun `transpose matrix test`(matrix: Array, expected: Array) { 42 | val actual = matrix.transpose() 43 | assertThat(actual).isEqualTo(expected) 44 | } 45 | 46 | class InputArgumentsProvider : ArgumentsProvider { 47 | override fun provideArguments( 48 | parameters: ParameterDeclarations, 49 | context: ExtensionContext, 50 | ): Stream = Stream.of( 51 | Arguments.of( 52 | arrayOf( 53 | intArrayOf(1, 2, 3), 54 | intArrayOf(4, 5, 6), 55 | intArrayOf(7, 8, 9), 56 | ), 57 | arrayOf( 58 | intArrayOf(1, 4, 7), 59 | intArrayOf(2, 5, 8), 60 | intArrayOf(3, 6, 9), 61 | ), 62 | ), 63 | Arguments.of( 64 | emptyArray(), 65 | emptyArray(), 66 | ), 67 | Arguments.of( 68 | arrayOf(intArrayOf(5)), 69 | arrayOf(intArrayOf(5)), 70 | ), 71 | Arguments.of( 72 | arrayOf( 73 | intArrayOf(1, 2, 3), 74 | intArrayOf(4, 5, 6), 75 | ), 76 | arrayOf( 77 | intArrayOf(1, 4), 78 | intArrayOf(2, 5), 79 | intArrayOf(3, 6), 80 | ), 81 | ), 82 | ) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/sorts/MemoryTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.utils.measureTime 28 | import org.junit.jupiter.api.Assertions.assertTrue 29 | import org.junit.jupiter.api.DisplayName 30 | import org.junit.jupiter.api.extension.ExtensionContext 31 | import org.junit.jupiter.params.ParameterizedTest 32 | import org.junit.jupiter.params.provider.Arguments 33 | import org.junit.jupiter.params.provider.ArgumentsProvider 34 | import org.junit.jupiter.params.provider.ArgumentsSource 35 | import org.junit.jupiter.params.support.ParameterDeclarations 36 | import java.util.stream.Stream 37 | 38 | class MemoryTest { 39 | @DisplayName("Sorts Memory Test") 40 | @ParameterizedTest(name = "Strategy: {0}") 41 | @ArgumentsSource(InputArgumentsProvider::class) 42 | fun `sorts test`(testCase: Sortable) { 43 | execute(testCase, getSortedArray()) 44 | } 45 | 46 | private fun execute(strategy: Sortable, array: IntArray) { 47 | measureTime(strategy, array) { 48 | strategy.invoke(array.toTypedArray()) 49 | } 50 | assertTrue(array.isSorted()) 51 | } 52 | 53 | class InputArgumentsProvider : ArgumentsProvider { 54 | override fun provideArguments( 55 | parameters: ParameterDeclarations, 56 | context: ExtensionContext, 57 | ): Stream = Stream.of( 58 | Arguments.of(BubbleSort), 59 | Arguments.of(SimpleBubbleSort), 60 | Arguments.of(InsertionSort), 61 | Arguments.of(InsertionSort2), 62 | Arguments.of(MergeSort), 63 | Arguments.of(BottomUpMergeSort), 64 | Arguments.of(QuickSort), 65 | Arguments.of(SelectionSort), 66 | Arguments.of(ShellSort), 67 | Arguments.of(HeapSort), 68 | Arguments.of(JvmSort), 69 | Arguments.of(PancakeSort), 70 | Arguments.of(GnomeSort), 71 | ) 72 | } 73 | 74 | companion object { 75 | // 1000_000 // uncomment for original test 76 | private const val ARRAY_SIZE = 1000 77 | 78 | private fun getSortedArray(): IntArray { 79 | val array = IntArray(ARRAY_SIZE) 80 | for (i in 0 until ARRAY_SIZE) { 81 | array[i] = i 82 | } 83 | return array 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths-ignore: 8 | - '**.md' 9 | pull_request: 10 | types: [ opened, synchronize, reopened ] 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 14 | cancel-in-progress: true 15 | 16 | permissions: 17 | actions: write 18 | contents: read 19 | id-token: write 20 | 21 | jobs: 22 | build: 23 | name: Build 24 | runs-on: ubuntu-latest 25 | 26 | steps: 27 | - name: Checkout code 28 | uses: actions/checkout@v6 29 | with: 30 | fetch-depth: 0 # Shallow clones should be disabled for better analysis relevancy 31 | 32 | - name: Set up JDK 17 33 | uses: actions/setup-java@v5 34 | with: 35 | java-version: '17' 36 | distribution: 'zulu' 37 | cache: 'gradle' 38 | 39 | - name: Validate Gradle Wrapper 40 | run: ./gradlew --version 41 | 42 | - name: Grant execute permission for gradlew 43 | run: chmod +x gradlew 44 | 45 | - name: Cache Gradle dependencies 46 | uses: actions/cache@v5.0.1 47 | with: 48 | path: ${{ env.GRADLE_HOME }}/caches 49 | key: | 50 | gradle-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} 51 | -${{ hashFiles('**/*.gradle*') }} 52 | -${{ hashFiles('**/buildSrc/**') }} 53 | -${{ github.sha }} 54 | restore-keys: | 55 | gradle-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} 56 | -${{ hashFiles('**/*.gradle*') }} 57 | -${{ hashFiles('**/buildSrc/**') }} 58 | 59 | - name: Run checks and test 60 | run: ./gradlew detekt ktlintCheck diktatCheck jacocoTestReport --build-cache --no-daemon --stacktrace --gradle-user-home "$GRADLE_HOME" 61 | 62 | - name: Run jacocoTestReport 63 | run: ./gradlew test jacocoTestReport 64 | 65 | - name: Build with Gradle and test 66 | run: ./gradlew build -x koverVerify # Skipping koverVerify to avoid failure if coverage has lowered 67 | 68 | - name: Run Codacy Analysis CLI 69 | uses: codacy/codacy-coverage-reporter-action@v1 70 | with: 71 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 72 | coverage-reports: ./build/reports/jacoco/test/jacocoTestReport.xml 73 | 74 | - name: Generate Test Coverage Xml Report 75 | run: ./gradlew koverXmlReport 76 | 77 | - name: Upload coverage to Codecov 78 | uses: codecov/codecov-action@v5 79 | with: 80 | token: ${{ secrets.CODECOV_TOKEN }} 81 | directory: ./build/reports/kover/ 82 | files: ./build/reports/kover/report.xml 83 | verbose: true 84 | 85 | - name: Upload coverage to qltysh 86 | uses: qltysh/qlty-action/coverage@main 87 | with: 88 | coverage-token: ${{ secrets.QLTY_COVERAGE_TOKEN }} 89 | files: ./build/reports/jacoco/test/jacocoTestReport.xml 90 | 91 | - name: Upload test coverage to qlty 92 | uses: qltysh/qlty-action/coverage@v2 93 | with: 94 | oidc: true 95 | files: build/reports/jacoco/test/jacocoTestReport.xml 96 | add-prefix: src/main/kotlin 97 | - name: Run codacy-coverage-reporter 98 | uses: codacy/codacy-coverage-reporter-action@v1.3.0 99 | with: 100 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 101 | coverage-reports: ./build/reports/jacoco/test/jacocoTestReport.xml 102 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | kotlin = "2.3.0" # https://github.com/JetBrains/kotlin 3 | coroutines = "1.10.2" # https://github.com/Kotlin/kotlinx.coroutines 4 | junit = "6.0.1" # https://junit.org/junit5 | https://central.sonatype.com/artifact/org.junit.jupiter/junit-jupiter 5 | mockk = "1.14.6" # https://mockk.io | https://central.sonatype.com/search?q=mockk&smo=true 6 | detekt = "1.23.8" # https://github.com/detekt/detekt 7 | dokka = "2.1.0" # https://github.com/Kotlin/dokka 8 | spotless = "8.1.0" # https://github.com/diffplug/spotless 9 | dependency = "1.33.0" # https://github.com/autonomousapps/dependency-analysis-gradle-plugin 10 | pitest = "1.19.0-rc.2" # https://plugins.gradle.org/plugin/info.solidsoft.pitest 11 | pinterestKtlint = "0.51.0-FINAL" # https://github.com/pinterest/ktlint 12 | ktlint = "14.0.1" # https://github.com/JLLeitschuh/ktlint-gradle 13 | assertj = "3.27.6" # https://mvnrepository.com/artifact/org.assertj/assertj-core | https://assertj.github.io/doc 14 | kover = "0.9.4" # https://github.com/Kotlin/kotlinx-kover 15 | diktat = "2.0.0" # https://github.com/saveourtool/diktat 16 | mockito = "5.21.0" # https://mvnrepository.com/artifact/org.mockito/mockito-core 17 | mockito_kotlin = "2.2.0" # https://mvnrepository.com/artifact/com.nhaarman.mockitokotlin2/mockito-kotlin 18 | 19 | [libraries] 20 | 21 | #region kotlin 22 | kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8", version.ref = "coroutines" } 23 | kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } 24 | kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } 25 | kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } 26 | # endregion 27 | 28 | #region code style 29 | detekt_formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" } 30 | pinterestKtlint = { module = "com.pinterest:ktlint", version.ref = "pinterestKtlint" } 31 | # endregion 32 | 33 | # region test libs 34 | kotlin-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } 35 | kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } 36 | mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" } 37 | mockito-kotlin = { module = "com.nhaarman.mockitokotlin2:mockito-kotlin", version.ref = "mockito_kotlin" } 38 | junit-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" } 39 | junit-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" } 40 | assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } 41 | mockk = { module = "io.mockk:mockk", version.ref = "mockk" } 42 | # endregion 43 | 44 | [plugins] 45 | kt-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 46 | kt-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } 47 | detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } 48 | dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } 49 | spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } 50 | dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependency" } 51 | pitest = { id = "info.solidsoft.pitest", version.ref = "pitest" } 52 | kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } 53 | diktat = { id = "com.saveourtool.diktat", version.ref = "diktat" } 54 | ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } 55 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/SelectionSorts.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.findMinimumIndex 28 | import dev.shtanko.algorithms.extensions.swap 29 | 30 | /** 31 | * Selection sort is a simple comparison-based sorting algorithm. It works by dividing the array into a sorted 32 | * and an unsorted region. It repeatedly selects the smallest (or largest) element from the unsorted region 33 | * and moves it to the sorted region. The algorithm maintains two subarrays: the subarray of sorted elements 34 | * and the subarray of unsorted elements. 35 | * 36 | * Worst-case performance: O(n^2) 37 | * Best-case performance: O(n^2) 38 | * Average performance: O(n^2) 39 | * Worst-case space complexity: O(1) 40 | */ 41 | data object SelectionSort : Sortable { 42 | /** 43 | * Performs the selection sort operation on the given array. 44 | * 45 | * @param arr The array to sort. 46 | * @param T The type of elements in the array, must be comparable. 47 | */ 48 | override fun > invoke(arr: Array) { 49 | for (i in arr.indices) { 50 | val min = arr.findMinimumIndex(i) 51 | if (min != i) { 52 | arr.swap(min, i) 53 | } 54 | } 55 | } 56 | } 57 | 58 | /** 59 | * Stable Selection Sort is a variation of the selection sort algorithm that maintains the relative order 60 | * of elements with equal values. It achieves this by moving the minimum element to the current position 61 | * and shifting the elements to the right, instead of swapping them directly. 62 | * 63 | * Worst-case performance: O(n^2) 64 | * Best-case performance: O(n^2) 65 | * Average performance: O(n^2) 66 | * Worst-case space complexity: O(1) 67 | */ 68 | data object StableSelectionSort : Sortable { 69 | /** 70 | * Performs the stable selection sort operation on the given array. 71 | * 72 | * @param arr The array to sort. 73 | * @param T The type of elements in the array, must be comparable. 74 | */ 75 | override fun > invoke(arr: Array) { 76 | for (i in arr.indices) { 77 | var min = arr.findMinimumIndex(i) 78 | for (j in i + 1 until arr.size) { 79 | if (arr[j] < arr[min]) { 80 | min = j 81 | } 82 | } 83 | // Move minimum element at current i. 84 | val key = arr[min] 85 | while (min > i) { 86 | arr[min] = arr[min - 1] 87 | min-- 88 | } 89 | arr[i] = key 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /config/main.md: -------------------------------------------------------------------------------- 1 | # Data structures and algorithms in pure Kotlin 2 | 3 | A repository that organizes various data structures, algorithms, and solutions to problems in Kotlin in a structured format 4 | 5 |

6 | Build 7 | Codebeat 8 | CodeFactor 9 | Codacy Badge 10 | Hits-of-Code 11 | License: MIT 12 | FOSSA Status 13 | CodeStyle 14 | Kotlin Version 15 | codacy test coverage 16 | Maintainability 17 | Code Coverage 18 | codecov test coverage 19 | Maintainability 20 |


21 | 22 | ## Overview 23 | 24 | The repository is a collection of open-source implementations of a variety of algorithms implemented in Kotlin and 25 | licensed under MIT License. 26 | The implementations and their associated documentations are meant to provide a learning resource for educators and 27 | students. 28 | Hence, one may find more than one implementation for the same objective but using different algorithm strategies and 29 | optimizations. 30 | 31 | ## Features 32 | 33 | * The repository provides implementations of various algorithms in one of the most fundamental general purpose languages 34 | - [Kotlin](https://kotlinlang.org/)). 35 | * Well documented source code with detailed explanations provide a valuable resource for educators and students alike. 36 | * Source codes are compiled and tested 37 | * Self-checks within programs ensure correct implementations with confidence. 38 | * Modular implementations and OpenSource licensing enable the functions to be utilized conveniently in other 39 | applications. 40 | * Makefile 41 | * JUnit 5 42 | * Code checks (detekt, ktlint, spotless) 43 | * CI 44 | -------------------------------------------------------------------------------- /src/test/kotlin/dev/shtanko/algorithms/leetcode/TwoSumTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.leetcode 26 | 27 | import dev.shtanko.algorithms.utils.measureTime 28 | import org.assertj.core.api.Assertions.assertThat 29 | import org.junit.jupiter.api.extension.ExtensionContext 30 | import org.junit.jupiter.params.ParameterizedTest 31 | import org.junit.jupiter.params.provider.Arguments 32 | import org.junit.jupiter.params.provider.ArgumentsProvider 33 | import org.junit.jupiter.params.provider.ArgumentsSource 34 | import org.junit.jupiter.params.support.ParameterDeclarations 35 | import java.util.stream.Stream 36 | 37 | abstract class TwoSumTest(private val strategy: T) { 38 | @ParameterizedTest 39 | @ArgumentsSource(InputArgumentsProvider::class) 40 | fun `two sum test`( 41 | array: IntArray, 42 | target: Int, 43 | expected: IntArray, 44 | ) { 45 | measureTime("Two sum array ${array.toList()}") { 46 | val actual = strategy(array, target) 47 | assertThat(actual).isEqualTo(expected) 48 | } 49 | } 50 | 51 | private class InputArgumentsProvider : ArgumentsProvider { 52 | override fun provideArguments( 53 | parameters: ParameterDeclarations, 54 | context: ExtensionContext, 55 | ): Stream = Stream.of( 56 | Arguments.of( 57 | intArrayOf(), 58 | 0, 59 | intArrayOf(), 60 | ), 61 | Arguments.of( 62 | intArrayOf(4, 8, 15, 16, 23), 63 | 9, 64 | intArrayOf(), 65 | ), 66 | Arguments.of( 67 | intArrayOf(4, 8, 15, 16, 23), 68 | 12, 69 | intArrayOf(0, 1), 70 | ), 71 | Arguments.of( 72 | intArrayOf(4, 8, 15, 16, 23), 73 | 39, 74 | intArrayOf(3, 4), 75 | ), 76 | Arguments.of( 77 | intArrayOf(2, 7, 11, 15), 78 | 9, 79 | intArrayOf(0, 1), 80 | ), 81 | Arguments.of( 82 | intArrayOf(3, 2, 4), 83 | 6, 84 | intArrayOf(1, 2), 85 | ), 86 | Arguments.of( 87 | intArrayOf(3, 3), 88 | 6, 89 | intArrayOf(0, 1), 90 | ), 91 | ) 92 | } 93 | } 94 | 95 | class TwoSumBruteForceTest : TwoSumTest(twoSumBruteForce) 96 | class TwoSumTwoPassHashTableTest : TwoSumTest(twoSumTwoPassHashTable) 97 | class TwoSumOnePassHashTableTest : TwoSumTest(twoSumOnePassHashTable) 98 | class TwoSumOneHashMapTest : TwoSumTest(twoSumOneHashMap) 99 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/BubbleSorts.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | import dev.shtanko.algorithms.extensions.swap 28 | 29 | /** 30 | * Bubble sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares 31 | * each pair of adjacent items and swaps them if they are in the wrong order. The pass through the list is repeated 32 | * until no swaps are needed, which indicates that the list is sorted. The algorithm, which is a comparison sort, 33 | * is named for the way smaller or larger elements "bubble" to the top of the list. Although the algorithm is simple, 34 | * it is too slow and impractical for most problems even when compared to insertion sort. It can be practical 35 | * if the input is usually in sorted order but may occasionally have some out-of-order elements nearly in position. 36 | * 37 | * Worst-case performance: O(n^2) 38 | * Best-case performance: O(n) 39 | * Average performance: O(n^2) 40 | * Worst-case space complexity: O(1) 41 | */ 42 | data object BubbleSort : Sortable { 43 | /** 44 | * Performs the bubble sort operation on the given array. 45 | * 46 | * @param arr The array to sort. 47 | * @param T The type of elements in the array, must be comparable. 48 | */ 49 | override fun > invoke(arr: Array) { 50 | var exchanged: Boolean 51 | 52 | do { 53 | exchanged = false 54 | for (i in 1 until arr.size) { 55 | if (arr[i] < arr[i - 1]) { 56 | arr.swap(i, i - 1) 57 | exchanged = true 58 | } 59 | } 60 | } while (exchanged) 61 | } 62 | } 63 | 64 | /** 65 | * SimpleBubbleSort is a basic implementation of the bubble sort algorithm. 66 | * It iterates through the array multiple times, comparing adjacent elements and swapping them if they are out of order. 67 | * The algorithm continues this process until the array is sorted. 68 | * 69 | * Worst-case performance: O(n^2) 70 | * Best-case performance: O(n^2) 71 | * Average performance: O(n^2) 72 | * Worst-case space complexity: O(1) 73 | */ 74 | data object SimpleBubbleSort : Sortable { 75 | /** 76 | * Performs the simple bubble sort operation on the given array. 77 | * 78 | * @param arr The array to sort. 79 | * @param T The type of elements in the array, must be comparable. 80 | */ 81 | override fun > invoke(arr: Array) { 82 | for (i in 0 until arr.size - 1) { 83 | for (j in i + 1 until arr.size) { 84 | if (arr[i] > arr[j]) { 85 | arr.swap(i, j) 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/sorts/BottomUpMergeSort.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.sorts 26 | 27 | /** 28 | * Implementation: Iterative 29 | * Space Complexity: O(n) 30 | * Ease of Use: Natural fit for linked lists 31 | * Stability: Stable 32 | * Performance: O(n log n) 33 | * Memory Usage: O(n), no recursion stack 34 | */ 35 | data object BottomUpMergeSort : Sortable { 36 | override fun > invoke(arr: Array) { 37 | val size = arr.size 38 | val tempArray = arr.copyOf() 39 | 40 | var width = 1 41 | while (width < size) { 42 | var i = 0 43 | while (i < size) { 44 | // Find the middle point 45 | val middle = kotlin.math.min(i + width, size) 46 | // Find the end of the current segment 47 | val end = kotlin.math.min(i + 2 * width, size) 48 | // Merge the sub-arrays array[i…middle-1] and array[middle…end-1] into tempArray 49 | merge(arr, tempArray, i, middle, end) 50 | i += 2 * width 51 | } 52 | // Copy the merged array back to the original array 53 | tempArray.copyInto(arr) 54 | width *= 2 55 | } 56 | } 57 | 58 | /** 59 | * Merge two sub-arrays of array[]. 60 | * 61 | * @param array the array to be sorted 62 | * @param tempArray the temporary array used for merging 63 | * @param start the start index of the first sub-array 64 | * @param middle the end index of the first sub-array 65 | * @param end the end index of the second sub-array 66 | * @param the type of elements in the array 67 | * @return the merged array 68 | */ 69 | private fun > merge( 70 | array: Array, 71 | tempArray: Array, 72 | start: Int, 73 | middle: Int, 74 | end: Int, 75 | ) { 76 | var i = start 77 | var j = middle 78 | var k = start 79 | 80 | // Merge the two sub-arrays into tempArray 81 | while (i < middle && j < end) { 82 | if (array[i] <= array[j]) { 83 | tempArray[k] = array[i] 84 | i++ 85 | } else { 86 | tempArray[k] = array[j] 87 | j++ 88 | } 89 | k++ 90 | } 91 | 92 | // Copy remaining elements of the left half, if any 93 | while (i < middle) { 94 | tempArray[k] = array[i] 95 | i++ 96 | k++ 97 | } 98 | 99 | // Copy remaining elements of the right half, if any 100 | while (j < end) { 101 | tempArray[k] = array[j] 102 | j++ 103 | k++ 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/shtanko/algorithms/extensions/ArrayX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | 4 | * Copyright (c) 2022 Oleksii Shtanko 5 | 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | package dev.shtanko.algorithms.extensions 26 | 27 | /** 28 | * Swaps elements at the specified indices in the array. 29 | * 30 | * @param i The index of the first element to swap. 31 | * @param j The index of the second element to swap. 32 | */ 33 | fun Array.swap( 34 | i: Int, 35 | j: Int, 36 | ) { 37 | val temp = this[i] 38 | this[i] = this[j] 39 | this[j] = temp 40 | } 41 | 42 | /** 43 | * Swaps elements at the specified indices in the IntArray. 44 | * 45 | * @param i The index of the first element to swap. 46 | * @param j The index of the second element to swap. 47 | */ 48 | fun IntArray.swap( 49 | i: Int, 50 | j: Int, 51 | ) { 52 | val tmp = this[i] 53 | this[i] = this[j] 54 | this[j] = tmp 55 | } 56 | 57 | /** 58 | * Reverses the elements in the array in place. 59 | */ 60 | fun Array.reverse() { 61 | val arraySize = this.size 62 | for (startIndex in 0 until arraySize / 2) { 63 | this.swap(startIndex, arraySize - 1 - startIndex) 64 | } 65 | } 66 | 67 | /** 68 | * Reverses the elements in the array in place using two pointers. 69 | */ 70 | fun Array.reverse2() { 71 | var i = 0 72 | var j = size - 1 73 | while (i < j) { 74 | swap(i, j) 75 | i++ 76 | j-- 77 | } 78 | } 79 | 80 | /** 81 | * Flips the elements in the array between the specified indices in place. 82 | * 83 | * @param leftIndex The starting index (inclusive) of the portion to flip. 84 | * @param rightIndex The ending index (inclusive) of the portion to flip. 85 | */ 86 | fun Array.flip( 87 | leftIndex: Int, 88 | rightIndex: Int, 89 | ) { 90 | var left = leftIndex 91 | var right = rightIndex 92 | while (left <= right) { 93 | swap(left++, right--) 94 | } 95 | } 96 | 97 | /** 98 | * Returns the second element of the IntArray. 99 | * 100 | * @return The second element of the IntArray. 101 | * @throws NoSuchElementException if the array is empty. 102 | */ 103 | fun IntArray.second(): Int { 104 | if (isEmpty()) { 105 | throw NoSuchElementException("Array is empty.") 106 | } 107 | return this[1] 108 | } 109 | 110 | /** 111 | * Finds the index of the minimum element in the array starting from the 112 | * specified index. 113 | * 114 | * @param i The starting index from which to search for the minimum element. 115 | * @return The index of the minimum element found in the array starting from the 116 | * specified index. 117 | */ 118 | fun > Array.findMinimumIndex(i: Int): Int { 119 | var min = i 120 | for (j in i + 1 until this.size) { 121 | if (this[j] < this[min]) { 122 | min = j 123 | } 124 | } 125 | return min 126 | } 127 | --------------------------------------------------------------------------------