diff --git a/.gitignore b/.gitignore index 7b15d454..53fbb490 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,91 @@ -# IDE-specific stuff -idea/ +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries # CMake cmake-build-*/ +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + # File-based project format *.iws # IntelliJ out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + # JIRA plugin atlassian-ide-plugin.xml +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + ### Kotlin ### # Compiled class file *.class diff --git a/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock b/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 00000000..9b355c03 Binary files /dev/null and b/.gradle/7.1/dependencies-accessors/dependencies-accessors.lock differ diff --git a/.gradle/7.1/dependencies-accessors/gc.properties b/.gradle/7.1/dependencies-accessors/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/.gradle/7.1/executionHistory/executionHistory.bin b/.gradle/7.1/executionHistory/executionHistory.bin new file mode 100644 index 00000000..8d707ec2 Binary files /dev/null and b/.gradle/7.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/7.1/executionHistory/executionHistory.lock b/.gradle/7.1/executionHistory/executionHistory.lock new file mode 100644 index 00000000..8323799a Binary files /dev/null and b/.gradle/7.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/7.1/fileChanges/last-build.bin b/.gradle/7.1/fileChanges/last-build.bin new file mode 100644 index 00000000..f76dd238 Binary files /dev/null and b/.gradle/7.1/fileChanges/last-build.bin differ diff --git a/.gradle/7.1/fileHashes/fileHashes.bin b/.gradle/7.1/fileHashes/fileHashes.bin new file mode 100644 index 00000000..0f1e3a51 Binary files /dev/null and b/.gradle/7.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/7.1/fileHashes/fileHashes.lock b/.gradle/7.1/fileHashes/fileHashes.lock new file mode 100644 index 00000000..4e4c0ca6 Binary files /dev/null and b/.gradle/7.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/7.1/fileHashes/resourceHashesCache.bin b/.gradle/7.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 00000000..23d883f8 Binary files /dev/null and b/.gradle/7.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/7.1/gc.properties b/.gradle/7.1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..c7e0fb6e Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..93cee923 --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sun Oct 17 18:57:42 OMST 2021 +gradle.version=7.1 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..68111229 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/checksums/checksums.lock b/.gradle/checksums/checksums.lock new file mode 100644 index 00000000..4d181c08 Binary files /dev/null and b/.gradle/checksums/checksums.lock differ diff --git a/.gradle/checksums/md5-checksums.bin b/.gradle/checksums/md5-checksums.bin new file mode 100644 index 00000000..795759f3 Binary files /dev/null and b/.gradle/checksums/md5-checksums.bin differ diff --git a/.gradle/checksums/sha1-checksums.bin b/.gradle/checksums/sha1-checksums.bin new file mode 100644 index 00000000..a2a44d01 Binary files /dev/null and b/.gradle/checksums/sha1-checksums.bin differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..8de8da2c --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Algorithms \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..659bf431 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..611e7c8a --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..fdc392fe --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 00000000..7e340a77 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..e2cfc0f9 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 00000000..2b63946d --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 4f5b8780..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Dmitry Tsyvtsyn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 0d32e721..867327ea 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # Kotlin Algorithms and Design Patterns + + This repository lists the most common algorithms, data structures, and design patterns written in the Kotlin programming language. All code is divided into separate packages: @@ -19,102 +21,67 @@ Also, whenever possible, I add *javadoc* for each class, method, and file Content: 1. package design_patterns - design patterns - * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt) - * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt) - * [Bridge](/src/main/kotlin/design_patterns/Bridge.kt) * [Builder](/src/main/kotlin/design_patterns/Builder.kt) - * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt) + * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt) * [Command](/src/main/kotlin/design_patterns/Command.kt) - * [Composite](/src/main/kotlin/design_patterns/Composite.kt) * [Decorator](/src/main/kotlin/design_patterns/Decorator.kt) * [Facade](/src/main/kotlin/design_patterns/Facade.kt) + * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt) * [Factory Method](/src/main/kotlin/design_patterns/Factory%20Method.kt) - * [Flyweight](/src/main/kotlin/design_patterns/Flyweight.kt) - * [Interpreter](/src/main/kotlin/design_patterns/Interpreter.kt) - * [Iterator](/src/main/kotlin/design_patterns/Iterator.kt) - * [Mediator](/src/main/kotlin/design_patterns/Mediator.kt) - * [Memento](/src/main/kotlin/design_patterns/Memento.kt) - * [Observer](/src/main/kotlin/design_patterns/Observer.kt) - * [Prototype](/src/main/kotlin/design_patterns/Prototype.kt) - * [Proxy](/src/main/kotlin/design_patterns/Proxy.kt) + * [Fluent Interface](/src/main/kotlin/design_patterns/Fluent%20Interface%20Pattern.kt) + * [Monostate](/src/main/kotlin/design_patterns/Monostate.kt) * [Singleton](/src/main/kotlin/design_patterns/Singleton.kt) - * [State](/src/main/kotlin/design_patterns/State.kt) * [Strategy](/src/main/kotlin/design_patterns/Strategy.kt) - * [Template Method](/src/main/kotlin/design_patterns/Template%20Method.kt) - * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt) + * [Observer](/src/main/kotlin/design_patterns/Observer.kt) + * [Dependency Injection](/src/main/kotlin/design_patterns/Dependency%20Injection.kt) + * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt) + * [Memento](/src/main/kotlin/design_patterns/Memento.kt) + * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt) 2. package structures - data structure * [Binary tree](/src/main/kotlin/structures/BinaryTree.kt) - * [Stack 1st implementation](/src/main/kotlin/structures/Stack1.kt) - * [Stack 2nd implementation](/src/main/kotlin/structures/Stack2.kt) + * [Stack](/src/main/kotlin/structures/Stack.kt) * [Queue](/src/main/kotlin/structures/Queue.kt) - * [Undirected Graph](/src/main/kotlin/structures/Graph.kt) - * [Directed Graph with weights](/src/main/kotlin/structures/GraphWithWeights.kt) - * [Matrix](/src/main/kotlin/structures/Matrix.kt) - * [Dynamic Array](/src/main/kotlin/structures/DynamicArray.kt) - * [Single linked list](/src/main/kotlin/structures/SingleLinkedList.kt) - * [Double linked list](/src/main/kotlin/structures/DoubleLinkedList.kt) + * [Graph](/src/main/kotlin/structures/Graph.kt) + * [ArrayList](/src/main/kotlin/structures/MyArrayList.kt) + * [Linked list](/src/main/kotlin/structures/LinkedList.kt) * [Min-heap](/src/main/kotlin/structures/MinHeap.kt) * [Max-heap](/src/main/kotlin/structures/MaxHeap.kt) 3. package sorting - sorting algorithms * [Bubble sort](/src/main/kotlin/sorting/BubbleSort.kt) + * [Bubble sort (improved)](/src/main/kotlin/sorting/BubbleSortImproved.kt) * [Insertion sort](/src/main/kotlin/sorting/InsertionSort.kt) * [Merge sort](/src/main/kotlin/sorting/MergeSort.kt) * [Quick sort](/src/main/kotlin/sorting/QuickSort.kt) * [Selection sort](/src/main/kotlin/sorting/SelectionSort.kt) * [Radix sort](/src/main/kotlin/sorting/RadixSort.kt) * [Tim sort](/src/main/kotlin/sorting/TimSort.kt) - * [Count sort](/src/main/kotlin/sorting/CountingSort.kt) + * [Count sort](/src/main/kotlin/sorting/CountSort.kt) 4. package search - search algorithms * [Binary search](/src/main/kotlin/search/BinarySearch.kt) + * [Binary search (recursive)](/src/main/kotlin/search/BinarySearchRecursive.kt) * [Linear search](/src/main/kotlin/search/LinearSearch.kt) 5. package other - other algorithms - * [Finite state machine](/src/main/kotlin/other/BinaryDigitsCounter.kt) - * [Euclid's algorithm](/src/main/kotlin/other/EuclidAlgorithm.kt) * [Factorial](/src/main/kotlin/other/Factorial.kt) - * [Factorial from Google Guava library](/src/main/kotlin/other/FactorialAdvanced.kt) - * [Factorial of BigInteger's with cache](/src/main/kotlin/other/FactorialBigWithCache.kt) - * [Factorial with cache](/src/main/kotlin/other/FactorialWithCache.kt) + * [Knut Morris Pratt's Algorithm for finding a substring](/src/main/kotlin/other/KnuthMorrisPratt.kt) + * [Levenshtein distance](/src/main/kotlin/other/LevensteinLength.kt) + * [Palindrome](/src/main/kotlin/other/Palindrome.kt) + * [Euclid's algorithm](/src/main/kotlin/other/Euclid.kt) * [FizzBuzz](/src/main/kotlin/other/FizzBuzz.kt) - * [Knut Morris Pratt's Algorithm for finding a substring](/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt) - * [Levenshtein distance](/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt) - * [Finding the maximum](/src/main/kotlin/other/MaxAlgorithm.kt) - * [Finding the minimum](/src/main/kotlin/other/MinAlgorithm.kt) - * [Palindrome](/src/main/kotlin/other/PalindromeAlgorithm.kt) - * [Parenthesis checking algorithm](/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt) - * [Reverse Array](/src/main/kotlin/other/ReverseArrayAlgorithm.kt) - * [Sieve of Eratosthenes](/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt) + * [Reverse Array](/src/main/kotlin/other/ReverseArray.kt) + * [Sieve of Eratosthenes](/src/main/kotlin/other/SieveOfEratosthenes.kt) + * [Finding the minimum](/src/main/kotlin/other/Min.kt) + * [Finding the maximum](/src/main/kotlin/other/Max.kt) * [The square root of a number](/src/main/kotlin/other/Sqrt.kt) - * [StringEqualsHash](/src/main/kotlin/other/StringEqualsHashAlgorithm.kt) - * [Swap algorithm](/src/main/kotlin/other/SwapAlgorithm.kt) + * [Finite state machine](/src/main/kotlin/other/BinaryDigitsCounter.kt) + * [ParenthesisCheck](/src/main/kotlin/other/ParenthesisCheck.kt) + * [StringEqualsHash](/src/main/kotlin/other/StringEqualsHash.kt) ## Your wishes and ideas -If you are interested in my repository or you have ideas on how to improve it or add something write: [Telegram](https://t.me/dmitry_tsyvtsyn), [Gmail](mailto:dmitry.kind.2@gmail.com) - -## License - - MIT License - - Copyright (c) 2023 Dmitry Tsyvtsyn - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. +If you are interested in my repository or you have ideas on how to improve it or add something, then let me know in telegram: - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. + diff --git a/README_ru.md b/README_ru.md index a2f1ac47..17a5b9bc 100644 --- a/README_ru.md +++ b/README_ru.md @@ -19,102 +19,67 @@ Структура: 1. пакет ru.design_patterns - паттерны проектирования - * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt) - * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt) - * [Bridge](/src/main/kotlin/design_patterns/Bridge.kt) * [Builder](/src/main/kotlin/design_patterns/Builder.kt) - * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt) + * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt) * [Command](/src/main/kotlin/design_patterns/Command.kt) - * [Composite](/src/main/kotlin/design_patterns/Composite.kt) * [Decorator](/src/main/kotlin/design_patterns/Decorator.kt) * [Facade](/src/main/kotlin/design_patterns/Facade.kt) + * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt) * [Factory Method](/src/main/kotlin/design_patterns/Factory%20Method.kt) - * [Flyweight](/src/main/kotlin/design_patterns/Flyweight.kt) - * [Interpreter](/src/main/kotlin/design_patterns/Interpreter.kt) - * [Iterator](/src/main/kotlin/design_patterns/Iterator.kt) - * [Mediator](/src/main/kotlin/design_patterns/Mediator.kt) - * [Memento](/src/main/kotlin/design_patterns/Memento.kt) - * [Observer](/src/main/kotlin/design_patterns/Observer.kt) - * [Prototype](/src/main/kotlin/design_patterns/Prototype.kt) - * [Proxy](/src/main/kotlin/design_patterns/Proxy.kt) + * [Fluent Interface](/src/main/kotlin/design_patterns/Fluent%20Interface%20Pattern.kt) + * [Monostate](/src/main/kotlin/design_patterns/Monostate.kt) * [Singleton](/src/main/kotlin/design_patterns/Singleton.kt) - * [State](/src/main/kotlin/design_patterns/State.kt) * [Strategy](/src/main/kotlin/design_patterns/Strategy.kt) - * [Template Method](/src/main/kotlin/design_patterns/Template%20Method.kt) - * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt) + * [Observer](/src/main/kotlin/design_patterns/Observer.kt) + * [Dependency Injection](/src/main/kotlin/design_patterns/Dependency%20Injection.kt) + * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt) + * [Memento](/src/main/kotlin/design_patterns/Memento.kt) + * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt) 2. пакет ru.structures - структуры данных * [Бинарное дерево](/src/main/kotlin/structures/BinaryTree.kt) - * [Стэк 1-ая реализация](/src/main/kotlin/structures/Stack1.kt) - * [Стэк 2-ая реализация](/src/main/kotlin/structures/Stack2.kt) + * [Стэк](/src/main/kotlin/structures/Stack.kt) * [Очередь](/src/main/kotlin/structures/Queue.kt) - * [Неориентированный граф](/src/main/kotlin/structures/Graph.kt) - * [Ориентированный граф с весами](/src/main/kotlin/structures/GraphWithWeights.kt) - * [Матрица](/src/main/kotlin/structures/Matrix.kt) - * [Динамический массив](/src/main/kotlin/structures/DynamicArray.kt) - * [Односвязный список](/src/main/kotlin/structures/SingleLinkedList.kt) - * [Двусвязный список](/src/main/kotlin/structures/DoubleLinkedList.kt) + * [Граф](/src/main/kotlin/structures/Graph.kt) + * [Динамический массив](/src/main/kotlin/structures/MyArrayList.kt) + * [Связанный список](/src/main/kotlin/structures/LinkedList.kt) * [Min-куча](/src/main/kotlin/structures/MinHeap.kt) * [Max-куча](/src/main/kotlin/structures/MaxHeap.kt) 3. пакет ru.sorting - алгоритмы сортировки * [Пузырьковая сортировка](/src/main/kotlin/sorting/BubbleSort.kt) + * [Пузырьковая сортировка (улучшенная)](/src/main/kotlin/sorting/BubbleSortImproved.kt) * [Сортировка вставками](/src/main/kotlin/sorting/InsertionSort.kt) * [Сортировака слиянием](/src/main/kotlin/sorting/MergeSort.kt) * [Быстрая сортировка](/src/main/kotlin/sorting/QuickSort.kt) * [Сортировка выбором](/src/main/kotlin/sorting/SelectionSort.kt) * [Поразрядная сортировка](/src/main/kotlin/sorting/RadixSort.kt) * [Tim sort](/src/main/kotlin/sorting/TimSort.kt) - * [Сортировка подсчётом](/src/main/kotlin/sorting/CountingSort.kt) + * [Сортировка подсчётом](/src/main/kotlin/sorting/CountSort.kt) 4. пакет ru.search - алгоритмы поиска * [Бинарный поиск](/src/main/kotlin/search/BinarySearch.kt) + * [Бинарный поиск (рекурсивный)](/src/main/kotlin/search/BinarySearchRecursive.kt) * [Линейный поиск](/src/main/kotlin/search/LinearSearch.kt) 5. пакет ru.other - другие алгоритмы - * [Конечный автомат](/src/main/kotlin/other/BinaryDigitsCounter.kt) - * [Алгоритм Эвклида](/src/main/kotlin/other/EuclidAlgorithm.kt) - * [Факториал](/src/main/kotlin/other/Factorial.kt) - * [Факториал из Google Guava библиотеки](/src/main/kotlin/other/FactorialAdvanced.kt) - * [Факториал BigInteger'ов с кэшем](/src/main/kotlin/other/FactorialBigWithCache.kt) - * [Факториал с кэшем](/src/main/kotlin/other/FactorialWithCache.kt) + * [Факториал числа](/src/main/kotlin/other/Factorial.kt) + * [Алгоритм Кнута Морриса Пратта для поиска подстроки](/src/main/kotlin/other/KnuthMorrisPratt.kt) + * [Расстояние Левенштейна](/src/main/kotlin/other/LevensteinLength.kt) + * [Палиндром](/src/main/kotlin/other/Palindrome.kt) + * [Алгоритм Эвклида](/src/main/kotlin/other/Euclid.kt) * [FizzBuzz](/src/main/kotlin/other/FizzBuzz.kt) - * [Алгоритм Кнута Морриса Пратта для поиска подстроки](/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt) - * [Расстояние Левенштейна](/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt) - * [Поиск максимума](/src/main/kotlin/other/MaxAlgorithm.kt) - * [Поиск минимума](/src/main/kotlin/other/MinAlgorithm.kt) - * [Палиндром](/src/main/kotlin/other/PalindromeAlgorithm.kt) - * [Проверка скобок на корректность](/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt) - * [Алгоритм переворота массива](/src/main/kotlin/other/ReverseArrayAlgorithm.kt) - * [Решето Эратосфена](/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt) + * [Алгоритм переворота массива](/src/main/kotlin/other/ReverseArray.kt) + * [Решето Эратосфена](/src/main/kotlin/other/SieveOfEratosthenes.kt) + * [Поиск минимума](/src/main/kotlin/other/Min.kt) + * [Поиск максимума](/src/main/kotlin/other/Max.kt) * [Квадратный корень из числа](/src/main/kotlin/other/Sqrt.kt) - * [Сравнение строк с помощью хэша](/src/main/kotlin/other/StringEqualsHashAlgorithm.kt) - * [Алгоритм обмена двух переменных](/src/main/kotlin/other/SwapAlgorithm.kt) + * [Конечный автомат](/src/main/kotlin/other/BinaryDigitsCounter.kt) + * [Проверка скобок на корректность](/src/main/kotlin/other/ParenthesisCheck.kt) + * [Сравнение строк с помощью хэша](/src/main/kotlin/other/StringEqualsHash.kt) ## Ваши пожелания и идеи -Если вы заинтересовались моим репозиторием или у вас появились идеи как его улучшить или что-то добавить, напишите: [Telegram](https://t.me/rwcwuwr), [Gmail](mailto:dmitry.kind.2@gmail.com) - -## Лицензия - - MIT License - - Copyright (c) 2023 Dmitry Tsyvtsyn - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. +Если вы заинтересовались моим репозиторием или у вас появились идеи как его улучшить или что-то добавить, то сообщите мне об этом в телеграме: - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. + diff --git a/assets/russian_version.png b/assets/russian_version.png new file mode 100644 index 00000000..efee2f80 Binary files /dev/null and b/assets/russian_version.png differ diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..bcc221cf --- /dev/null +++ b/build.gradle @@ -0,0 +1,16 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' version '1.5.10' +} + +group 'org.example' +version '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib" + implementation 'junit:junit:4.13.1' + implementation 'org.junit.jupiter:junit-jupiter:5.7.0' +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index d11a8acf..00000000 --- a/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -plugins { - id("org.jetbrains.kotlin.jvm") version "1.8.22" -} - -group = "io.github.dmitrytsyvtsyn.algorithmsdesignpatterns" -version = "1.0.1" - -repositories { - mavenCentral() -} - -dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib") - testImplementation("junit:junit:4.13.1") -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..69a97150 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..744e882e 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/bin/sh +#!/usr/bin/env sh # -# Copyright © 2015-2021 the original authors. +# Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,101 +17,67 @@ # ############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# +## +## Gradle start up script for UN*X +## ############################################################################## # Attempt to set APP_HOME - # Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} +APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum +MAX_FD="maximum" warn () { echo "$*" -} >&2 +} die () { echo echo "$*" echo exit 1 -} >&2 +} # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -121,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java + JAVACMD="$JAVA_HOME/jre/sh/java" else - JAVACMD=$JAVA_HOME/bin/java + JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -132,7 +98,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD=java + JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -140,95 +106,80 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi fi -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg + i=`expr $i + 1` done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..2a12a1db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,4 @@ -@rem +git @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..16a6d377 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'Algorithms' + diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 629422ea..00000000 --- a/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "Kotlin-Algorithms-and-Design-Patterns" \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Abstract Factory.kt b/src/main/kotlin/design_patterns/Abstract Factory.kt index 876330f8..09af3498 100644 --- a/src/main/kotlin/design_patterns/Abstract Factory.kt +++ b/src/main/kotlin/design_patterns/Abstract Factory.kt @@ -1,8 +1,10 @@ package design_patterns +import java.util.* + /** * - * Abstract factory is a generative design pattern that allows + * An abstract factory is a generative design pattern that allows * * you to create families of related objects without being tied to * diff --git a/src/main/kotlin/design_patterns/Adapter.kt b/src/main/kotlin/design_patterns/Adapter.kt index 0173986f..00f5a403 100644 --- a/src/main/kotlin/design_patterns/Adapter.kt +++ b/src/main/kotlin/design_patterns/Adapter.kt @@ -1,31 +1,45 @@ package design_patterns /** + * pattern: Adapter * - * Adapter is a structural design pattern that allows objects with incompatible interfaces to work together + * using: used when we cannot directly use the functionality of an object * + * description: to use the functionality of an object, a special class is created, which is called an adapter */ -interface EnglishSpeaker { - fun speakEnglish(): String +interface Adapter { + fun getItem(position: Int) : T + fun getItemCount() : Int } -class EnglishSpeakerImpl : EnglishSpeaker { - override fun speakEnglish(): String { - return "Hello, friend!" - } -} +/** + * here is a simplified imitation of RecyclerView component from android + */ +class RecyclerView { -interface SpainSpeaker { - fun speakSpanish(): String -} + private var adapter: Adapter? = null -class SpainSpeakerAdapter(private val englishSpeaker: EnglishSpeaker) : SpainSpeaker { + fun changeAdapter(adapter: Adapter) { + this.adapter = adapter + } - override fun speakSpanish(): String = - when (englishSpeaker.speakEnglish()) { - "Hello, friend!" -> "Hola, amigo!" - else -> "No te entiendo" + /** + * renders elements from the adapter + * + * @return returns a list of elements to test + */ + fun draw() : List { + val items = mutableListOf() + val myAdapter = adapter + if (myAdapter != null) { + val count = myAdapter.getItemCount() + for (i in 0 until count) { + items.add(myAdapter.getItem(i)) + // draw item + } } + return items + } } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Bridge.kt b/src/main/kotlin/design_patterns/Bridge.kt deleted file mode 100644 index 88e8e501..00000000 --- a/src/main/kotlin/design_patterns/Bridge.kt +++ /dev/null @@ -1,86 +0,0 @@ -package design_patterns - -/** - * - * Bridge is a structural design pattern used to separate abstraction and implementation - * - * so they can change independently - * - */ - -// OperatingSystem implements an internal algorithm for drawing primitives (operating systems are implementations in this example) -abstract class OperatingSystem(private val name: String, private val version: Int) { - - protected val lines = mutableListOf() - protected val circles = mutableListOf() - - abstract fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int) - - abstract fun drawCircle(centerX: Int, centerY: Int, radius: Int) - - override fun toString(): String { - return """ - $name $version - Lines: - ${lines.joinToString("\n")} - Circles: - ${circles.joinToString("\n")} - """.trimIndent() - } - -} - -// different implementations have different algorithms for drawing primitives -class WindowsSystem : OperatingSystem("Windows", 10) { - - override fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int) { - lines.add("Windows graphic subsystem -> startX: $startX, startY: $startY, endX: $endX, endY: $endY") - } - - override fun drawCircle(centerX: Int, centerY: Int, radius: Int) { - circles.add("Windows graphic subsystem -> centerX: $centerX, centerY: $centerY, radius: $radius") - } - -} - -class MacOSSystem : OperatingSystem("MacOS", 14) { - - override fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int) { - lines.add("MacOS graphic subsystem -> startX: $startX, startY: $startY, endX: $endX, endY: $endY") - } - - override fun drawCircle(centerX: Int, centerY: Int, radius: Int) { - circles.add("MacOS graphic subsystem -> centerX: $centerX, centerY: $centerY, radius: $radius") - } - -} - -// we can add new primitives without changing OperatingSystem implementations (primitives are abstractions in this example) -abstract class GraphicPrimitive { - abstract fun draw(system: OperatingSystem) -} - -class GraphicCirclePrimitive( - private val centerX: Int, - private val centerY: Int, - private val radius: Int -) : GraphicPrimitive() { - - override fun draw(system: OperatingSystem) { - system.drawCircle(centerX, centerY, radius) - } - -} - -class GraphicLinePrimitive( - private val startX: Int, - private val startY: Int, - private val endX: Int, - private val endY: Int -) : GraphicPrimitive() { - - override fun draw(system: OperatingSystem) { - system.drawLine(startX, startY, endX, endY) - } - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Builder.kt b/src/main/kotlin/design_patterns/Builder.kt index b832598d..9875a815 100644 --- a/src/main/kotlin/design_patterns/Builder.kt +++ b/src/main/kotlin/design_patterns/Builder.kt @@ -1,134 +1,121 @@ package design_patterns /** + * pattern: Builder * - * Builder is is a generative design pattern that is used to create complex objects, - * - * separates the construction of an object from its representation + * using: used to create complex objects * + * description: to create an object, an auxiliary class Builder is used, which has methods for changing the fields of our main class. */ + /** + * * The first variant + * */ -class HttpConnectionClient1 private constructor( - private val dnsServerAddress: String, - private val callTimeout: Int, - private val connectTimeout: Int, - private val readTimeout: Int, - private val writeTimeout: Int, - // class can have many more fields -) { - override fun toString() = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() +class Pony1 { + private val name: String + private val family: String + private val cutieMark: String + private val city: String + + private constructor(name: String, family: String, cutieMark: String, city: String) { + this.name = name + this.family = family + this.cutieMark = cutieMark + this.city = city + } + + override fun toString(): String { + return "$name, $family, $cutieMark, $city" + } class Builder { - private var dnsServerAddress: String = "8.8.8.8" - private var callTimeout: Int = 0 - private var connectTimeout: Int = 10_000 - private var readTimeout: Int = 10_000 - private var writeTimeout: Int = 0 - - fun dnsServerAddress(address: String) = apply { - dnsServerAddress = address - } + private var name: String = "" + private var family: String = "" + private var cutieMark: String = "" + private var city: String = "" - fun callTimeout(timeout: Int) = apply { - // we can add some checks such as: - // if (timeout < 0) throw IllegalArgumentException("Uncorrected timeout: $timeout") - callTimeout = timeout - } + fun changeName(name: String) = apply { + this.name = name + } - fun connectTimeout(timeout: Int) = apply { - connectTimeout = timeout - } + fun changeFamily(family: String) = apply { + this.family = family + } - fun readTimeout(timeout: Int) = apply { - readTimeout = timeout - } + fun changeCutieMark(cutieMark: String) = apply { + this.cutieMark = cutieMark + } - fun writeTimeout(timeout: Int) = apply { - writeTimeout = timeout - } + fun changeCity(city: String) = apply { + this.city = city + } - fun build() = HttpConnectionClient1(dnsServerAddress, callTimeout, connectTimeout, readTimeout, writeTimeout) + fun build() = Pony1(name, family, cutieMark, city) } } /** + * * The second variant + * */ -class HttpConnectionClient2 private constructor() { - private var dnsServerAddress: String = "8.8.8.8" - private var callTimeout: Int = 0 - private var connectTimeout: Int = 10_000 - private var readTimeout: Int = 10_000 - private var writeTimeout: Int = 0 - - override fun toString() = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() + +class Pony2 { + private var name: String = "" + private var family: String = "" + private var cutieMark: String = "" + private var city: String = "" + + override fun toString(): String { + return "$name, $family, $cutieMark, $city" + } companion object { - fun newBuilder() = HttpConnectionClient2().Builder() + fun newBuilder() = Pony2().Builder() } inner class Builder { - fun dnsServerAddress(address: String) = apply { - dnsServerAddress = address + fun changeName(name: String) = apply { + this@Pony2.name = name } - fun callTimeout(timeout: Int) = apply { - // we can add some checks such as: - // if (timeout < 0) throw IllegalArgumentException("Uncorrected timeout: $timeout") - callTimeout = timeout + fun changeFamily(family: String) = apply { + this@Pony2.family = family } - fun connectTimeout(timeout: Int) = apply { - connectTimeout = timeout + fun changeCutieMark(cutieMark: String) = apply { + this@Pony2.cutieMark = cutieMark } - fun readTimeout(timeout: Int) = apply { - readTimeout = timeout + fun changeCity(city: String) = apply { + this@Pony2.city = city } - fun writeTimeout(timeout: Int) = apply { - writeTimeout = timeout - } - - fun build() = this@HttpConnectionClient2 + fun build() = this@Pony2 } } /** + * * Kotlin variant with default arguments + * */ -class HttpConnectionClient3( - private val dnsServerAddress: String = "8.8.8.8", - private val callTimeout: Int = 0, - private val connectTimeout: Int = 10_000, - private val readTimeout: Int = 10_000, - private val writeTimeout: Int = 0 + +class Pony3( + private var name: String = "", + private var family: String = "", + private var cutieMark: String = "", + private var city: String = "" ) { - override fun toString() = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() + override fun toString(): String { + return "$name, $family, $cutieMark, $city" + } } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Command.kt b/src/main/kotlin/design_patterns/Command.kt index d8d6e477..cd50b510 100644 --- a/src/main/kotlin/design_patterns/Command.kt +++ b/src/main/kotlin/design_patterns/Command.kt @@ -1,144 +1,31 @@ package design_patterns /** + * pattern: Command * - * Command is a behavioral pattern that encapsulates a request to perform an action as a separate object + * description: it's a behavioral pattern that allows you to wrap requests or simple operations in separate objects. * + * P.S. Kotlin variant of this pattern is shown in tests */ -// StereoSystem is the receiver that performs the action -class StereoSystem { - - private var hasTurnedOn = false - private var volume = 50 - - val currentState: String - get() = """ - running status: $hasTurnedOn - volume value: $volume - """.trimIndent() - - fun turnOn() { - hasTurnedOn = true - } - - fun turnOff() { - hasTurnedOn = false - } - - fun increaseVolume() { - if (!hasTurnedOn) return - if (volume < 100) { - volume += 10 - } - } - - fun decreaseVolume() { - if (!hasTurnedOn) return - if (volume > 0) { - volume -= 10 - } - } - +interface ArithmeticCommand { + fun execute(number: Int) : Int } -interface StereoSystemCommand { - fun execute() - fun undo() : Boolean -} - -// this command encapsulates a request to increase the volume in StereoSystem -class IncreaseVolumeCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand { - - override fun execute() { - stereoSystem.increaseVolume() - } - - override fun undo(): Boolean { - stereoSystem.decreaseVolume() - return true +class AddCommand(private val addendum: Int) : ArithmeticCommand { + override fun execute(number: Int): Int { + return number + addendum } - } -// this command encapsulates a request to decrease the volume in StereoSystem -class DecreaseVolumeCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand { - - override fun execute() { - stereoSystem.decreaseVolume() +class MinusCommand(private val subtrahend: Int) : ArithmeticCommand { + override fun execute(number: Int): Int { + return number - subtrahend } - - override fun undo(): Boolean { - stereoSystem.increaseVolume() - return true - } - } -// this command encapsulates a request to turn on StereoSystem -class TurnOnCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand { - - override fun execute() { - stereoSystem.turnOn() +class MultiCommand(private val coefficient: Int) : ArithmeticCommand { + override fun execute(number: Int): Int { + return number * coefficient } - - override fun undo(): Boolean { - stereoSystem.turnOff() - return true - } - -} - -// this command encapsulates a request to turn off StereoSystem -class TurnOffCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand { - - override fun execute() { - stereoSystem.turnOff() - } - - override fun undo() = false - -} - -// we can also create the command that combines others -class MacroCommand(private vararg val commands: StereoSystemCommand) : StereoSystemCommand { - - override fun execute() { - for (command in commands) { - command.execute() - } - } - - override fun undo(): Boolean { - for (command in commands.reversed()) { - val isNotCancelableCommand = !command.undo() - if (isNotCancelableCommand) return false - } - return true - } - } - -// StereoSystemRemoteControl executes commands without breaking their encapsulation -class StereoSystemRemoteControl(private val buttons: Map = mapOf()) { - - // we only know about StereoSystemCommand interface - private val commandHistory = mutableListOf() - - fun pressButton(name: String) { - val command = buttons[name] - if (command != null) { - command.execute() - commandHistory.add(command) - } - } - - fun pressUndoButton() { - val lastCommand = commandHistory.removeLastOrNull() - if (lastCommand != null) { - val isNotCancelableCommand = !lastCommand.undo() - if (isNotCancelableCommand) commandHistory.clear() - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Composite.kt b/src/main/kotlin/design_patterns/Composite.kt deleted file mode 100644 index 2c9a71d9..00000000 --- a/src/main/kotlin/design_patterns/Composite.kt +++ /dev/null @@ -1,53 +0,0 @@ -package design_patterns - -/** - * - * Composite is a structural design pattern that organizes objects into a tree structure - * - * and allows clients to access individual objects and groups of objects in the same way. - * - */ - -// all components have a common interface -abstract class MenuComponent(val title: String) { - // menus and items can give information about themselves - abstract fun fetchMenuInformation() : String -} - -class Menu(title: String) : MenuComponent(title) { - - // menu can contain other menus and items - private val childMenuComponents = mutableListOf() - - // addComponent/removeComponent operations are only available for the menu - fun addComponent(component: MenuComponent) { - childMenuComponents.add(component) - } - - fun removeComponent(component: MenuComponent) { - childMenuComponents.remove(component) - } - - override fun fetchMenuInformation(): String { - val builder = StringBuilder() - builder.append("Menu: $title") - childMenuComponents.forEach { component -> - builder.append("\n") - builder.append(component.fetchMenuInformation()) - } - return builder.toString() - } - -} - -// the simple component that contains no others -class MenuItem(title: String, private val price: Int) : MenuComponent(title) { - - override fun fetchMenuInformation(): String = - """ - title: $title - price: $price - ------------- - """.trimIndent() - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Decorator.kt b/src/main/kotlin/design_patterns/Decorator.kt index 69011bab..9e3d7939 100644 --- a/src/main/kotlin/design_patterns/Decorator.kt +++ b/src/main/kotlin/design_patterns/Decorator.kt @@ -1,11 +1,11 @@ package design_patterns /** + * pattern: Decorator * - * Decorator is a structural design pattern that adds new functionality to an object: - * - * classes implement a common interface and to extend the functionality of the previous object, + * using: used to add additional functionality to our object * + * description: classes implement a common interface and to extend the functionality of the previous object, * the old object is passed through the constructor * */ @@ -14,35 +14,50 @@ interface MyPrinter { fun printedText() : String } -// just returns "Hello" +/** + * returns "Hello" + * + */ class HelloPrinter : MyPrinter { override fun printedText() : String { return "Hello" } } -// adds a comma to the previous value of the printedText() function +/** + * adds a comma to the previous value of the printedText() function + * + */ class CommaPrinter(private val printer: MyPrinter) : MyPrinter { override fun printedText() : String { return "${printer.printedText()}," } } -// adds a space to the previous value of the printedText() function +/** + * adds a space to the previous value of the printedText() function + * + */ class SpacePrinter(private val printer: MyPrinter) : MyPrinter { override fun printedText() : String { return "${printer.printedText()} " } } -// adds the word "World" to the previous value of the printedText() function +/** + * adds the word World to the previous value of the printedText() function + * + */ class WorldPrinter(private val printer: MyPrinter) : MyPrinter { override fun printedText() : String { return "${printer.printedText()}World" } } -// adds an exclamation mark to the previous value of the printedText() function +/** + * adds an exclamation mark to the previous value of the printedText() function + * + */ class ExclamationPrinter(private val printer: MyPrinter) : MyPrinter { override fun printedText() : String { return "${printer.printedText()}!" diff --git a/src/main/kotlin/design_patterns/Dependency Injection.kt b/src/main/kotlin/design_patterns/Dependency Injection.kt new file mode 100644 index 00000000..123a792f --- /dev/null +++ b/src/main/kotlin/design_patterns/Dependency Injection.kt @@ -0,0 +1,26 @@ +package design_patterns + +/** + * pattern: Dependency Injection + * + * using: used when we have classes that depend on others + * + * description: all dependencies (classes that ours depends on) are passed through the constructor + * + */ + +class NewsApiService { + fun fetchNews() = listOf( + "event 1", + "event 2", + "event 3" + ) +} + +class NewsRepository(private val service: NewsApiService) { + fun news() = service.fetchNews() +} + +class NewsViewModel(repo: NewsRepository) { + val news = repo.news() +} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Facade.kt b/src/main/kotlin/design_patterns/Facade.kt index 632b1cf2..b61db907 100644 --- a/src/main/kotlin/design_patterns/Facade.kt +++ b/src/main/kotlin/design_patterns/Facade.kt @@ -1,102 +1,53 @@ package design_patterns /** + * pattern: Facade * - * Facade is a structural design pattern that simplifies the interface to a group of interfaces + * using: used to simplify access to an object with a complex implementation * - * with a more complex implementation + * description: a complex object contains several dependencies within itself, which it combines with each other * */ -data class GoodsEntity( - private val id: Long, - private val name: String, - private val description: String, - private val price: Double -) -class GoodsDatabase { - private val cachedGoods = mutableListOf() - - fun save(goods: List) { - cachedGoods.addAll(goods) - } - - fun read() = cachedGoods -} - -class GoodsNetworkService { - - fun fetch() = listOf( - GoodsEntity( - id = 1, - name = "Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition", - description = "You know you don't want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who've faced the same software design problems.", - price = 41.94 - ) - ) - -} - -data class CategoryEntity( - private val id: Long, - private val name: String -) +/** + * imitation of local data storage (database) + * + */ +class LocalDataSource { -class CategoryDatabase { - private val cachedCategories = mutableListOf() + private val data = mutableListOf() - fun save(goods: List) { - cachedCategories.addAll(goods) + fun save(data: List) { + this.data.addAll(data) } - fun read() = cachedCategories -} + fun read() = data + fun isEmpty() = data.isEmpty() -class CategoryNetworkService { +} - fun fetch() = listOf( - CategoryEntity( - id = 1, - name = "Books" - ) +/** + * network request simulation + * + */ +class NetworkDataSource { + fun get() = listOf( + "Harry Potter", + "Ronald Weasley", + "Hermione Granger" ) - } -data class GoodsResult( - val goods: List, - val categories: List -) - -// we have a group of interfaces (databases and network services) -class GoodsRepository( - private val goodsDatabase: GoodsDatabase, - private val goodsNetworkService: GoodsNetworkService, - private val categoryDatabase: CategoryDatabase, - private val categoryNetworkService: CategoryNetworkService -) { +class Repository(private val localSource: LocalDataSource, private val networkSource: NetworkDataSource) { - // we need a simpler interface - fun goodsAndCategories() : GoodsResult { - val goods = goodsDatabase.read().toMutableList() - if (goods.isEmpty()) { - val networkGoods = goodsNetworkService.fetch() - goodsDatabase.save(networkGoods) - goods.addAll(networkGoods) + fun fetch() : List { + // I omitted error handling for simplicity + if (localSource.isEmpty()) { + val data = networkSource.get() + localSource.save(data) } - - val categories = categoryDatabase.read().toMutableList() - if (categories.isEmpty()) { - val networkCategories = categoryNetworkService.fetch() - categoryDatabase.save(networkCategories) - categories.addAll(networkCategories) - } - - return GoodsResult( - goods = goods, - categories = categories - ) + return localSource.read() } } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Factory Method.kt b/src/main/kotlin/design_patterns/Factory Method.kt index e73d4db4..9b7e2334 100644 --- a/src/main/kotlin/design_patterns/Factory Method.kt +++ b/src/main/kotlin/design_patterns/Factory Method.kt @@ -10,63 +10,33 @@ package design_patterns * */ -abstract class House(private val address: String, private val price: Int) { +abstract class Pony4 - override fun toString() = """ - address = $address - price = $price - """.trimIndent() +class EarthPony4 : Pony4() +class Pegasus4 : Pony4() +class Unicorn4 : Pony4() -} - -// the factory method makes sense if we have a hierarchy of objects -class WoodenCheapHouse(address: String) : House(address, 50_000) -class WoodenAverageHouse(address: String) : House(address, 250_000) -class WoodenExpensiveHouse(address: String) : House(address, 1_000_000) - -class StoneCheapHouse(address: String) : House(address, 45_000) -class StoneAverageHouse(address: String) : House(address, 230_000) -class StoneExpensiveHouse(address: String) : House(address, 900_000) - -// we have a common logic for every HouseCompany -abstract class HouseCompany { +abstract class Place { + private var numberOfPonies = 0 - private val alreadyBuiltHouses = mutableListOf() + abstract fun pony() : Pony4 - val examplesAlreadyBuiltHouses: String - get() = alreadyBuiltHouses.joinToString("\n\n") - - fun orderHouse(address: String, cost: HouseCompanyCost): House { - val house = buildHouse(address, cost) - alreadyBuiltHouses.add(house) - return house + fun newPony() : Pony4 { + numberOfPonies++ + return pony() } - // the subclasses define a specific implementation - protected abstract fun buildHouse(address: String, cost: HouseCompanyCost): House - - enum class HouseCompanyCost { CHEAP, AVERAGE, EXPENSIVE } - + fun count() = numberOfPonies } -// WoodenHouseCompany only builds wooden houses -class WoodenHouseCompany : HouseCompany() { - - override fun buildHouse(address: String, cost: HouseCompanyCost) = when(cost) { - HouseCompanyCost.CHEAP -> WoodenCheapHouse(address) - HouseCompanyCost.AVERAGE -> WoodenAverageHouse(address) - HouseCompanyCost.EXPENSIVE -> WoodenExpensiveHouse(address) - } - +class Cloudsdale : Place() { + override fun pony() = Pegasus4() } -// StoneHouseCompany only builds stone houses -class StoneHouseCompany : HouseCompany() { - - override fun buildHouse(address: String, cost: HouseCompanyCost) = when(cost) { - HouseCompanyCost.CHEAP -> StoneCheapHouse(address) - HouseCompanyCost.AVERAGE -> StoneAverageHouse(address) - HouseCompanyCost.EXPENSIVE -> StoneExpensiveHouse(address) - } +class Canterlot : Place() { + override fun pony() = Unicorn4() +} +class Ponyville : Place() { + override fun pony() = EarthPony4() } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Fluent Interface Pattern.kt b/src/main/kotlin/design_patterns/Fluent Interface Pattern.kt new file mode 100644 index 00000000..e4817b53 --- /dev/null +++ b/src/main/kotlin/design_patterns/Fluent Interface Pattern.kt @@ -0,0 +1,36 @@ +package design_patterns + +/** + * pattern: Fluent Interface + * + * using: used to implement chaining methods + * + * description: the object has special methods that change it and return it + * with a new state for further manipulations + * + */ + +class View { + private var isFocusable = false + private var isClickable = false + private var bgColor: Int = 0x444444 + + fun hasFocus() = isFocusable + fun isClickable() = isClickable + fun bgColor() = bgColor + + fun focusable() = apply { + isFocusable = true + } + + fun clickable() = apply { + isClickable = true + } + + fun bg(color: Int) = apply { + bgColor = color + } + + fun draw() {} + +} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Flyweight.kt b/src/main/kotlin/design_patterns/Flyweight.kt deleted file mode 100644 index afb68613..00000000 --- a/src/main/kotlin/design_patterns/Flyweight.kt +++ /dev/null @@ -1,46 +0,0 @@ -package design_patterns - -/** - * - * Flyweight is a structural design pattern that reduces memory costs by reusing a family of objects - * - * and storing mutable state outside the object. - * - */ - -class BeautifulGarden { - - // we reuse objects with immutable state, in this example trees - private val existingTrees = mutableListOf() - - // mutable state (coordinates) are stored outside the object - private val placedTrees = mutableListOf>() - - fun placeTree(name: String, description: String, height: Int, x: Int, y: Int) { - // check if such a tree already exists reuse it otherwise create a new one - val tree = existingTrees.find { tree -> tree.name == name && tree.description == description && tree.height == height } - ?: Tree(name, description, height).apply(existingTrees::add) - - placedTrees.add(Triple(x, y, tree)) - } - - fun placedTreesAsString(): String { - val builder = StringBuilder() - builder.append("Beautiful Garden:\n") - - placedTrees.forEach { (x, y, tree) -> - builder.append("name: ${tree.name}, height: ${tree.height}, x: $x, y: $y\n") - } - - builder.append("-|-|-|-|-|-|-|-|-|-|-") - - return builder.toString() - } - - data class Tree( - val name: String, - val description: String, - val height: Int - ) - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Interpreter.kt b/src/main/kotlin/design_patterns/Interpreter.kt deleted file mode 100644 index dcb4f60d..00000000 --- a/src/main/kotlin/design_patterns/Interpreter.kt +++ /dev/null @@ -1,68 +0,0 @@ -package design_patterns - -/** - * - * Interpreter is a behavioral design pattern that defines a simple language grammar for a problem domain, - * - * represents grammatical rules as language sentences and interprets them to solve commonly encountered problems - * - */ - -// contains general information for the interpreter -class InterpreterContext { - private val variables = mutableMapOf() - - fun putVariable(key: String, value: Int) { - variables[key] = value - } - - fun fetchVariable(key: String): Int { - return variables[key] ?: 0 - } -} - -// represents a specific interpreter grammar expression -interface InterpreterExpression { - fun interpret(context: InterpreterContext) -} - -class SetIntVariableExpression( - private val key: String, - private val intValue: Int -) : InterpreterExpression { - override fun interpret(context: InterpreterContext) { - context.putVariable(key = key, value = intValue) - } -} - -class PerformExpression(private vararg val expressions: InterpreterExpression) : InterpreterExpression { - override fun interpret(context: InterpreterContext) { - expressions.forEach { it.interpret(context) } - } -} - -class AddVariablesExpression( - private val key0: String, - private val key1: String, - private val result: String -) : InterpreterExpression { - override fun interpret(context: InterpreterContext) { - context.putVariable( - key = result, - value = context.fetchVariable(key0) + context.fetchVariable(key1) - ) - } -} - -class MultipleVariablesExpression( - private val key0: String, - private val key1: String, - private val result: String -) : InterpreterExpression { - override fun interpret(context: InterpreterContext) { - context.putVariable( - key = result, - value = context.fetchVariable(key0) * context.fetchVariable(key1) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Iterator.kt b/src/main/kotlin/design_patterns/Iterator.kt deleted file mode 100644 index 8e76c7af..00000000 --- a/src/main/kotlin/design_patterns/Iterator.kt +++ /dev/null @@ -1,38 +0,0 @@ -package design_patterns - -/** - * - * Iterator is a behavioral design pattern that provides a mechanism for sequentially enumerating the elements - * - * of a collection without revealing its internal representation. - * - */ - -interface BoxIterator { - fun hasNext(): Boolean - fun next(): T -} - -interface BoxIterable { - fun iterator(): BoxIterator -} - -class GiftBox(private val presents: Array) : BoxIterable { - - override fun iterator() = object : BoxIterator { - private var current = -1 - - override fun next(): String { - return presents[current] - } - - override fun hasNext(): Boolean { - if (current < presents.size - 1) { - current++ - return true - } - return false - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Mediator.kt b/src/main/kotlin/design_patterns/Mediator.kt deleted file mode 100644 index c0d17b85..00000000 --- a/src/main/kotlin/design_patterns/Mediator.kt +++ /dev/null @@ -1,88 +0,0 @@ -package design_patterns - -/** - * - * Mediator is a behavioral design pattern that reduces the coupling of many classes among themselves - * - * by moving these couplings into one mediator class - * - */ - -// SoftwareDevelopmentManager is a mediator for the customer, designer, programmer and tester -class SoftwareDevelopmentManager { - - private lateinit var customer: SoftwareDevelopmentMember - private lateinit var designer: SoftwareDevelopmentMember - private lateinit var programmer: SoftwareDevelopmentMember - private lateinit var tester: SoftwareDevelopmentMember - - fun changeCustomer(member: SoftwareDevelopmentMember) { customer = member } - fun changeDesigner(member: SoftwareDevelopmentMember) { designer = member } - fun changeProgrammer(member: SoftwareDevelopmentMember) { programmer = member } - fun changeTester(member: SoftwareDevelopmentMember) { tester = member } - - private val stages = mutableListOf() - val stagesAsString: String - get() = stages.joinToString("\n") - - // members do not interact directly with each other because the mediator does it - // which reduces the coupling between them - fun nextStage(work: String, member: SoftwareDevelopmentMember) { - val finishedStage = when (member) { - - is CustomerSoftwareDevelopmentMember -> designer.receiveWork(work) - - is DesignerSoftwareDevelopmentMember -> programmer.receiveWork(work) - - is ProgrammerSoftwareDevelopmentMember -> tester.receiveWork(work) - - is TesterSoftwareDevelopmentMember -> customer.receiveWork(work) - - else -> "" - } - - stages.add(finishedStage) - } - -} - -// SoftwareDevelopmentMember works with other members through the mediator -abstract class SoftwareDevelopmentMember(protected val mediator: SoftwareDevelopmentManager) { - - abstract fun receiveWork(work: String): String - - abstract fun finishWork() - -} - -class CustomerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) { - override fun receiveWork(work: String) = "Customer accepted the work: $work" - - override fun finishWork() { - mediator.nextStage("design development", this) - } -} - -class DesignerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) { - override fun receiveWork(work: String) = "Designer accepted the work: $work" - - override fun finishWork() { - mediator.nextStage("writing code", this) - } -} - -class ProgrammerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) { - override fun receiveWork(work: String) = "Programmer accepted the work: $work" - - override fun finishWork() { - mediator.nextStage("application testing", this) - } -} - -class TesterSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) { - override fun receiveWork(work: String) = "Tester accepted the work: $work" - - override fun finishWork() { - mediator.nextStage("business valuation", this) - } -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Memento.kt b/src/main/kotlin/design_patterns/Memento.kt index 1a2effde..c69bf6cb 100644 --- a/src/main/kotlin/design_patterns/Memento.kt +++ b/src/main/kotlin/design_patterns/Memento.kt @@ -2,50 +2,54 @@ package design_patterns /** * - * Memento is a behavioral design pattern that allows without violating encapsulation to capture + * pattern: Memento * - * and save the internal state of an object so that it can be restored to this state later + * allows without violating encapsulation, to fix and save the state of an object + * in such a way as to restore it to this state * */ class Bundle(val str: String) -// Android system saves the application state in special bundles -// I gave this as an example, Android system’s saving mechanism is much more complicated +/** + * + * Android system emulating + * + */ class AndroidSystem { - - private var savedBundle: Bundle = Bundle("") + private var bundle: Bundle = Bundle("") fun saveBundle(bundle: Bundle) { - savedBundle = bundle + this.bundle = bundle } - fun restoreBundle() = savedBundle + fun restoreBundle() = bundle } -// TextView is an Android component that draws text on the screen -class TextView { - - private var currentText: String = "" +/** + * + * TextView is an Android component that draws text on the screen + * + */ +class TextView1 { + private var text: String = "" fun setText(text: String) { - currentText = text + this.text = text } - fun text() = currentText + fun text() = text fun draw() { - println(currentText) + println(text) } - // saves the current state of TextView before re-creating it fun onSaveInstanceState(): Bundle { - return Bundle(currentText) + return Bundle(text) } - // restores the current state after TextView is recreated fun onRestoreInstanceState(bundle: Bundle) { - currentText = bundle.str + text = bundle.str } } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Monostate.kt b/src/main/kotlin/design_patterns/Monostate.kt new file mode 100644 index 00000000..f0139173 --- /dev/null +++ b/src/main/kotlin/design_patterns/Monostate.kt @@ -0,0 +1,34 @@ +package design_patterns + +/** + * pattern: MonoState + * + * using: used where you need to have common data for different objects of the same class + * + * description: The Monostate pattern is very similar to the Singleton pattern. The difference is + * that in the Singleton pattern we have only one object, while in Monostate the objects use the same data. + */ + +class TextView { + companion object { + /** + * stores the number of TextView elements created + * + */ + private var count = 0 + } + + /** + * + * @return returns the number of TextView elements created + */ + fun textViewCount() = count + + init { + count++ + } + + fun onDetachView() { + count-- + } +} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Observer.kt b/src/main/kotlin/design_patterns/Observer.kt index d5c30421..5c86e61c 100644 --- a/src/main/kotlin/design_patterns/Observer.kt +++ b/src/main/kotlin/design_patterns/Observer.kt @@ -1,41 +1,50 @@ package design_patterns /** + * pattern: Observer * - * Observer is is a behavioral design pattern that defines a one-to-many relationship between objects + * using: used when we need to subscribe to changes of some object * - * such that when the state of one object changes all dependent objects are automatically notified and updated + * description: the object communicates its changes to observers + * who previously subscribed to its changes * */ -fun interface PonyObserver { +fun interface Observer { fun update(item: List) } -interface PonyObservable { - fun addObserver(observer: PonyObserver) - fun removeObserver(observer: PonyObserver) +/** + * the interface of the object whose changes we will listen to + * + */ +interface Observable { + fun observe(observer: Observer) + fun cancel(observer: Observer) fun notifyObservers() } -// PonyList contains some data and when it changes we will notify observers -class PonyList : PonyObservable { +/** + * contains some data, when it changes we will notify observers + * + */ +class PonyList : Observable { private val ponies = mutableListOf() - private val observers = mutableSetOf() + private val observers = mutableSetOf() fun add(pony: String) { ponies.add(pony) - // notify observers that the data has changed + // notify our observers that the data has changed notifyObservers() } - override fun addObserver(observer: PonyObserver) { + override fun observe(observer: Observer) { observers.add(observer) } - override fun removeObserver(observer: PonyObserver) { + override fun cancel(observer: Observer) { observers.remove(observer) } diff --git a/src/main/kotlin/design_patterns/Prototype.kt b/src/main/kotlin/design_patterns/Prototype.kt deleted file mode 100644 index d1e46797..00000000 --- a/src/main/kotlin/design_patterns/Prototype.kt +++ /dev/null @@ -1,71 +0,0 @@ -package design_patterns - -/** - * - * Prototype is a generative design pattern that allows you to copy objects - * - * without going into the details of their implementation. - * - */ - -abstract class Sweets( - protected val title: String, - protected val description: String, - protected val price: Int -) { - - // we only have a copy interface and don't know about its implementation - abstract fun copy(): Sweets - -} - -class OreoCookies( - title: String, - private val flavor: String, - price: Int -) : Sweets( - title = title, - price = price, - description = "Take a delicious break with OREO Chocolate Sandwich Cookies, America's favorite sandwich cookie for over 100 years..." -) { - - // each implementation creates its own copy - override fun copy(): Sweets { - return OreoCookies(title, flavor, price) - } - - override fun equals(other: Any?): Boolean { - if (other == null) return false - if (this === other) return true - if (other !is OreoCookies) return false - - return title == other.title && description == other.description && - flavor == other.flavor && price == other.price - } - -} - -class `M&MsChocolate`( - private val taste: String, - price: Int, -) : Sweets( - title = "M&M's chocolate", - price = price, - description = "M&M's are a chocolate jelly bean produced by Mars LLC. It first appeared in the United States in 1941 and is now sold in more than 100 countries..." -) { - - override fun copy(): Sweets { - return `M&MsChocolate`(taste, price) - } - - override fun equals(other: Any?): Boolean { - if (other == null) return false - if (this === other) return true - if (other !is `M&MsChocolate`) return false - - return title == other.title && description == other.description && - taste == other.taste && price == other.price - } - -} - diff --git a/src/main/kotlin/design_patterns/Proxy.kt b/src/main/kotlin/design_patterns/Proxy.kt deleted file mode 100644 index d0f3eac3..00000000 --- a/src/main/kotlin/design_patterns/Proxy.kt +++ /dev/null @@ -1,103 +0,0 @@ -package design_patterns - -/** - * - * Proxy is a structural design pattern that provides an object - * - * that controls access to another object by intercepting all calls. - * - * There are several types of this pattern: - * - * 1) Logging proxy - saves all calls to a real object with their parameters to the log (shown in this example) - * 2) Remote proxy - provides communication with an object which is located in a different address space or on a remote machine (Java Remote Procedure Call) - * 3) Virtual proxy - ensures that a real object is created only when it is actually needed (shown in this example) - * 4) Protection proxy - checks whether the caller has the necessary rights to execute the request - * 5) Caching proxy - provides temporary storage of calculation results - * 6) Synchronizing proxy - performs synchronized access control to an object in a multi-threaded environment (Collections.synchronized** methods) - * 7) Smart reference proxy - performs additional actions when a link is created to an object - * - */ - -interface AudioPlayer { - val currentState: String - - fun play(audio: String) - fun pause() - fun resume() - fun stop() -} - -// we have the simple player simulation -class AudioPlayerImpl : AudioPlayer { - - private var currentAudio: String = "" - private var currentStatus = MediaPlayerStatus.NOT_INITIALIZED - - override val currentState: String - get() = """ - current audio: $currentAudio - current status: $currentStatus - """.trimIndent() - - override fun play(audio: String) { - if (audio.isNotBlank()) { - currentAudio = audio - currentStatus = MediaPlayerStatus.RUNNING - } - } - override fun pause() { - if (currentStatus == MediaPlayerStatus.RUNNING) { - currentStatus = MediaPlayerStatus.PAUSED - } - } - - override fun resume() { - if (currentStatus == MediaPlayerStatus.PAUSED) { - currentStatus = MediaPlayerStatus.RUNNING - } - } - - override fun stop() { - if (currentStatus != MediaPlayerStatus.NOT_INITIALIZED) { - currentAudio = "" - currentStatus = MediaPlayerStatus.NOT_INITIALIZED - } - } - - enum class MediaPlayerStatus { - NOT_INITIALIZED, PAUSED, RUNNING - } - -} - -// MediaPlayerProxy defers the creation of a real object (virtual proxy) and logs all its calls (logging proxy) -class AudioPlayerProxy : AudioPlayer { - - // deferred creation of the real player - private val player: AudioPlayer by lazy { AudioPlayerImpl() } - - override val currentState: String - get() = player.currentState - - override fun play(audio: String) { - player.play(audio) - // logs real player calls - println("play audio: $audio") - } - - override fun pause() { - player.pause() - println("pause") - } - - override fun resume() { - player.resume() - println("resume") - } - - override fun stop() { - player.stop() - println("stop") - } - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Singleton.kt b/src/main/kotlin/design_patterns/Singleton.kt index 64648f3e..388dab12 100644 --- a/src/main/kotlin/design_patterns/Singleton.kt +++ b/src/main/kotlin/design_patterns/Singleton.kt @@ -1,39 +1,21 @@ package design_patterns /** + * pattern: Singleton * - * Singleton is a generative design pattern that guarantees the existence of one instance of a class + * using: used when we need to have the same object throughout + * the entire execution of our program * - * and provides a global access point to it + * description: class allows you to create only a single object * */ -object SQLiteDatabase { +object LocalData { + private val names = mutableListOf() - // SQLiteDatabase instance state - private var connectionId = -1 - - // These methods provide a global access point to SQLiteDatabase instance state - fun openConnection() { - if (connectionId < 0) { - // open connection... - connectionId = 1 - } - } - - fun execSQL(sql: String): List { - if (connectionId < 0) return emptyList() - return when (sql) { - "select * from names" -> listOf("Rick", "Morty", "Jerry", "Beth") - else -> emptyList() - } - } - - fun closeConnection() { - if (connectionId > 0) { - // close connection... - connectionId = -1 - } + fun addName(nm: String) { + names.add(nm) } + fun names() = names.toList() } \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/State.kt b/src/main/kotlin/design_patterns/State.kt deleted file mode 100644 index 12eb14aa..00000000 --- a/src/main/kotlin/design_patterns/State.kt +++ /dev/null @@ -1,90 +0,0 @@ -package design_patterns - -/** - * - * State is a behavioral design pattern that controls changes in the behavior of an object - * - * when its internal state changes - * - */ - -// the common interface for all states -interface CocaColaState { - fun insertDollar() : Boolean - fun takeBackDollar() : Boolean - fun pressButton(numberOfDrinks: Int) : Boolean -} - -// we don't have drinks in the machine -class EmptyCocaColaState : CocaColaState { - override fun insertDollar() = false - override fun takeBackDollar() = false - override fun pressButton(numberOfDrinks: Int) = false - override fun toString(): String = "EmptyCocaColaState" -} - -// we have drinks, but we don't have a dollar in the machine -class NoDollarCocaColaState(private val machine: CocaColaMachine) : CocaColaState { - override fun insertDollar(): Boolean { - machine.setState(HaveDollarCocaColaState(machine)) - return true - } - - override fun takeBackDollar() = false - override fun pressButton(numberOfDrinks: Int) = false - override fun toString(): String = "NoDollarCocaColaState" -} - -// we have a dollar in the machine -class HaveDollarCocaColaState(private val machine: CocaColaMachine) : CocaColaState { - override fun insertDollar() = false - override fun takeBackDollar(): Boolean { - machine.setState(NoDollarCocaColaState(machine)) - return true - } - override fun pressButton(numberOfDrinks: Int): Boolean { - if (numberOfDrinks == 1) { - machine.setState(EmptyCocaColaState()) - } else { - machine.setState(NoDollarCocaColaState(machine)) - } - return true - } - override fun toString(): String = "HaveDollarCocaColaState" -} - -// CocaColaMachine switches between states -class CocaColaMachine { - - private var numberOfDrinks = 3 - private var state: CocaColaState = NoDollarCocaColaState(this) - - val currentState: String - get() = state.toString() - - fun insertDollar() = state.insertDollar() - - fun takeBackDollar() = state.takeBackDollar() - - fun pressButton(): Boolean { - val isSuccess = state.pressButton(numberOfDrinks) - if (isSuccess) { - numberOfDrinks -= 1 - } - return isSuccess - } - - fun loadDrinks(count: Int) { - numberOfDrinks += count - if (numberOfDrinks > 0) { - setState(NoDollarCocaColaState(this)) - } else { - setState(EmptyCocaColaState()) - } - } - - fun setState(newState: CocaColaState) { - state = newState - } - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Strategy.kt b/src/main/kotlin/design_patterns/Strategy.kt index 40065ead..95fe1bcb 100644 --- a/src/main/kotlin/design_patterns/Strategy.kt +++ b/src/main/kotlin/design_patterns/Strategy.kt @@ -1,84 +1,35 @@ package design_patterns /** + * pattern: Strategy * - * Strategy is a behavioral design pattern used to define a family of algorithms, - * - * encapsulate each one and make them interchangeable + * using: used when we need to change the behavior of an object * */ -// encapsulates the filtering algorithm -interface FoodFilterStrategy { - fun filter(items: List): List -} +interface ExchangeStrategy { + fun into(price: Double) : Double -class OnlyChipsFilterStrategy : FoodFilterStrategy { - override fun filter(items: List): List { - return items.filter { it.category == "chips" } + class Dollar : ExchangeStrategy { + override fun into(price: Double): Double { + return price / 70 + } } -} -class OnlyChocolateFilterStrategy : FoodFilterStrategy { - override fun filter(items: List): List { - return items.filter { it.category == "chocolate" } + class Tenge : ExchangeStrategy { + override fun into(price: Double): Double { + return price * 6 + } } } -class PriceFilterStrategy(private val price: Int) : FoodFilterStrategy { - override fun filter(items: List): List { - return items.filter { it.price >= price } - } -} +class RubleExchangeRate { + private var strategy : ExchangeStrategy = ExchangeStrategy.Dollar() -class SearchWordFilterStrategy(private val search: String) : FoodFilterStrategy { - override fun filter(items: List): List { - return items.filter { it.title.contains(search, ignoreCase = true) } + fun changeStrategy(strategy: ExchangeStrategy) { + this.strategy = strategy } -} - -data class FoodEntity( - val title: String, - val price: Int, - val category: String -) - -// FoodStore returns a list of food filtered by strategy -class FoodStore(private var filterStrategy: FoodFilterStrategy) { - - // we can change strategy - fun changeStrategy(strategy: FoodFilterStrategy) { - filterStrategy = strategy - } - - fun foodItems(): List { - val foodItems = fetchFoodItems() - return filterStrategy.filter(foodItems) - } - - private fun fetchFoodItems() = - listOf( - FoodEntity( - "Lays Potato Chips Fried Crab Flavor", - 2, - "chips" - ), - FoodEntity( - "Lay's Potato Chips, Classic", - 3, - "chips" - ), - FoodEntity( - "Dove Chocolate", - 3, - "chocolate" - ), - FoodEntity( - "Ritter Sport Chocolate", - 4, - "chocolate" - ) - ) + fun exchange(priceInRuble: Double) = strategy.into(priceInRuble) } diff --git a/src/main/kotlin/design_patterns/Template Method.kt b/src/main/kotlin/design_patterns/Template Method.kt deleted file mode 100644 index eb69548f..00000000 --- a/src/main/kotlin/design_patterns/Template Method.kt +++ /dev/null @@ -1,55 +0,0 @@ -package design_patterns - -/** - * - * Template method a behavioral design pattern that defines the basis of an algorithm - * - * and allows subclasses to redefine some steps of the algorithm without changing its overall structure - * - */ - -data class Cake( - val layers: List, - val cream: String, - val sprinkles: String -) - -abstract class CakeBaker { - - protected abstract fun layer(): String - - protected abstract fun cream(): String - - protected abstract fun sprinkles(): String - - // we have the basis of an algorithm - fun makeCake(numberOfLayers: Int): Cake { - return Cake( - layers = List(numberOfLayers) { layer() }, - cream = cream(), - sprinkles = sprinkles() - ) - } - -} - -class ChocolateCakeBaker : CakeBaker() { - - // subclasses redefines some steps of the algorithm - override fun cream(): String = "chocolate cream" - - override fun layer(): String = "chocolate cake layer" - - override fun sprinkles(): String = "chocolate chips" - -} - -class WaffleCakeBaker : CakeBaker() { - - override fun cream(): String = "custard cream" - - override fun layer(): String = "waffle cake layer" - - override fun sprinkles(): String = "coconut flakes" - -} \ No newline at end of file diff --git a/src/main/kotlin/design_patterns/Visitor.kt b/src/main/kotlin/design_patterns/Visitor.kt index c7352327..6294a3a3 100644 --- a/src/main/kotlin/design_patterns/Visitor.kt +++ b/src/main/kotlin/design_patterns/Visitor.kt @@ -2,8 +2,9 @@ package design_patterns /** * - * Visitor is a behavioral design pattern that allows you to add a new operation + * pattern: Visitor * + * description: it's a behavioral pattern that allows you to add a new operation * to an entire class hierarchy without changing the code of these classes. * */ diff --git "a/src/main/kotlin/design_patterns/\320\241hain Of Responsibilities.kt" "b/src/main/kotlin/design_patterns/\320\241hain Of Responsibilities.kt" index 64536167..1b26e027 100644 --- "a/src/main/kotlin/design_patterns/\320\241hain Of Responsibilities.kt" +++ "b/src/main/kotlin/design_patterns/\320\241hain Of Responsibilities.kt" @@ -2,22 +2,34 @@ package design_patterns /** * - * Chain of responsibility is a behavioral design pattern that allows requests to be sent sequentially + * pattern: Chain of responsibility * - * through a chain of handlers + * description: a design pattern consisting of “a source of command objects and a series of processing objects”. + * Each processing object in the chain is responsible for a certain type of command, and the processing is done, + * it forwards the command to the next processor in the chain. * */ -enum class BlockFactor { ONE, TWO, THREE } +enum class BlockFactor { + ONE, TWO, THREE +} -// I decided to give an analogy from the Minecraft game. -// In this game there are blocks that can be broken with a stone pickaxe, iron and diamond. -// For example: diamond may mine by iron and diamond pickaxes unlike cobblestone, which is mined by any pickaxe +/** + * + * I decided to give an analogy from the Minecraft game. + * In this game there are blocks that can be broken with a stone pickaxe, iron and diamond. + * For example: diamond may mine by iron and diamond pickaxes unlike cobblestone, which is mined by any + * + */ abstract class Block(private val factor: BlockFactor) { fun mayMine(factor: BlockFactor) = this.factor.ordinal <= factor.ordinal } -// the blocks are from the game +/** + * + * blocks from the game + * + */ class StoneBlock: Block(BlockFactor.ONE) class DiamondBlock: Block(BlockFactor.TWO) class ObsidianBlock: Block(BlockFactor.THREE) @@ -25,21 +37,30 @@ class ObsidianBlock: Block(BlockFactor.THREE) abstract class Pickaxe(private val factor: BlockFactor) { private var nextPickaxe: Pickaxe? = null - fun changeNextPickaxe(pickaxe: Pickaxe) { - nextPickaxe = pickaxe + this.nextPickaxe = pickaxe } - // we mine the block, if it doesn't work, we take another pickaxe, if there is one, returns true if a pickaxe can mine - fun mine(block: Block): Boolean { - if (block.mayMine(factor)) return true - - return nextPickaxe?.mine(block) ?: false - } + /** + * + * we mine the block, if it doesn't work, we take another pickaxe, if there is one + * + * @return return true if a pickaxe can mine + */ + fun mine(block: Block): Boolean = + if (block.mayMine(factor)) { + true + } else { + nextPickaxe?.mine(block) ?: false + } } -// the pickaxes are from the game +/** + * + * pickaxes from the game + * + */ class StonePickaxe: Pickaxe(BlockFactor.ONE) class IronPickaxe: Pickaxe(BlockFactor.TWO) diff --git a/src/main/kotlin/other/BinaryDigitsCounter.kt b/src/main/kotlin/other/BinaryDigitsCounter.kt index a9ed604a..91b9e523 100644 --- a/src/main/kotlin/other/BinaryDigitsCounter.kt +++ b/src/main/kotlin/other/BinaryDigitsCounter.kt @@ -1,20 +1,24 @@ package other /** - * * This algorithm counts the number of ones and zeros in a binary string - * * and implemented on a finite state machine * */ - class BinaryDigitsCounter { - + + /** + * Stores the result of the algorithm + * + */ data class Result(private val ones: Int = 0, private val zeros: Int = 0) - // represents two states - private enum class State { - ONE, ZERO + /** + * Represents two states + * + */ + private enum class State { + ONE, ZERO } fun compute(binaryString: String): Result { // 1010010011 diff --git a/src/main/kotlin/other/Euclid.kt b/src/main/kotlin/other/Euclid.kt new file mode 100644 index 00000000..cc8c2d9f --- /dev/null +++ b/src/main/kotlin/other/Euclid.kt @@ -0,0 +1,31 @@ +package other + +/** + * + * Euclid's algorithm for finding the greatest common divisor + * + */ + +class Euclid { + + /** + * + * finds the greatest common divisor of two numbers + * + * @return returns the greatest common divisor + * + */ + fun compute(num1: Int, num2: Int) : Int { + var copyNum1 = num1 + var copyNum2 = num2 + while (copyNum1 != 0 && copyNum2 != 0) { + if (copyNum1 > copyNum2) { + copyNum1 %= copyNum2 + } else { + copyNum2 %= copyNum1 + } + } + return copyNum1 + copyNum2 + } + +} \ No newline at end of file diff --git a/src/main/kotlin/other/EuclidAlgorithm.kt b/src/main/kotlin/other/EuclidAlgorithm.kt deleted file mode 100644 index a419fac3..00000000 --- a/src/main/kotlin/other/EuclidAlgorithm.kt +++ /dev/null @@ -1,37 +0,0 @@ -package other - -/** - * - * Euclid's algorithm for finding the greatest common divisor - * - */ - -class EuclidAlgorithm { - - fun computeByDivisionWithRemainder(number1: Int, number2: Int) : Int { - var copyNumber1 = number1 - var copyNumber2 = number2 - while (copyNumber1 != 0 && copyNumber2 != 0) { - if (copyNumber1 > copyNumber2) { - copyNumber1 %= copyNumber2 - } else { - copyNumber2 %= copyNumber1 - } - } - return copyNumber1 + copyNumber2 - } - - fun computeBySubtraction(number1: Int, number2: Int): Int { - var copyNumber1 = number1 - var copyNumber2 = number2 - while (copyNumber1 != copyNumber2) { - if (copyNumber1 > copyNumber2) { - copyNumber1 -= copyNumber2 - } else { - copyNumber2 -= copyNumber1 - } - } - return copyNumber1 - } - -} \ No newline at end of file diff --git a/src/main/kotlin/other/Factorial.kt b/src/main/kotlin/other/Factorial.kt index a9c38e77..57c2ac48 100644 --- a/src/main/kotlin/other/Factorial.kt +++ b/src/main/kotlin/other/Factorial.kt @@ -1,7 +1,6 @@ package other /** - * * Algorithm for finding the factorial of a positive number n * */ @@ -9,9 +8,10 @@ package other class Factorial { /** - * iterative method * worst time: O(n) * amount of memory: O(1) + * + * @return returns the factorial of a number by an iterative method */ fun compute(number: Int) : Int { if (number <= 1) { @@ -26,9 +26,10 @@ class Factorial { } /** - * recursive method * worst time: O(n) * amount of memory: O(n) - stack for recursion + * + * @return returns factorial recursively */ fun computeRecursive(number: Int) : Int { return if (number <= 1) { @@ -38,8 +39,11 @@ class Factorial { } } - // read more: https://kotlinlang.org/docs/functions.html#tail-recursive-functions - tailrec fun computeRecursiveWithKotlinOptimization(number: Int, result: Int = 1) : Int = - if (number <= 1) result else computeRecursiveWithKotlinOptimization(number - 1, result * number) + /** + * @see tailrec functions + * + */ + tailrec fun computeRecursiveWithKotlinOptimization(number: Int) : Int = + if (number <= 1) 1 else number * computeRecursiveWithKotlinOptimization(number - 1) } \ No newline at end of file diff --git a/src/main/kotlin/other/FactorialAdvanced.kt b/src/main/kotlin/other/FactorialAdvanced.kt index 647060b9..bac69a79 100644 --- a/src/main/kotlin/other/FactorialAdvanced.kt +++ b/src/main/kotlin/other/FactorialAdvanced.kt @@ -3,14 +3,12 @@ package other import java.math.BigInteger /** - * * This algorithm is taken from Google Guava library * */ class FactorialAdvanced { - // precomputed factorials private val factorials = longArrayOf( 1L, 1L, @@ -35,7 +33,7 @@ class FactorialAdvanced { 1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 ) - fun compute(n: Int): BigInteger { + fun compute(n: Int): BigInteger? { if (n <= 0) { return BigInteger.ZERO } @@ -44,38 +42,38 @@ class FactorialAdvanced { return BigInteger.valueOf(factorials[n]) } - // pre-allocate space for our list of intermediate BigIntegers. - val approxSize = divide(n * log2Celling(n), Long.SIZE_BITS) + // Pre-allocate space for our list of intermediate BigIntegers. + val approxSize = divide(n * log2Celling(n), java.lang.Long.SIZE) val bigNumbers = ArrayList(approxSize) - // start from the pre-computed maximum long factorial. + // Start from the pre-computed maximum long factorial. val startingNumber = factorials.size var number = factorials[startingNumber - 1] - // strip off 2s from this value. - var shift = number.countTrailingZeroBits() + // Strip off 2s from this value. + var shift = java.lang.Long.numberOfTrailingZeros(number) number = number shr shift - // use floor(log2(num)) + 1 to prevent overflow of multiplication. + // Use floor(log2(num)) + 1 to prevent overflow of multiplication. var numberBits = log2Floor(number) + 1 var bits = log2Floor(startingNumber.toLong()) + 1 - // check for the next power of two boundary, to save us a CLZ operation. + // Check for the next power of two boundary, to save us a CLZ operation. var nextPowerOfTwo = 1 shl bits - 1 - // iteratively multiply the longs as big as they can go. + // Iteratively multiply the longs as big as they can go. for (num in startingNumber..n) { - // check to see if the floor(log2(num)) + 1 has changed. + // Check to see if the floor(log2(num)) + 1 has changed. if ((num and nextPowerOfTwo) != 0) { nextPowerOfTwo = nextPowerOfTwo shl 1 bits++ } - // get rid of the 2s in num. - val tz = num.toLong().countTrailingZeroBits() + // Get rid of the 2s in num. + val tz = java.lang.Long.numberOfTrailingZeros(num.toLong()) val normalizedNum = (num shr tz).toLong() shift += tz - // adjust floor(log2(num)) + 1. + // Adjust floor(log2(num)) + 1. val normalizedBits = bits - tz - // if it won't fit in a long, then we store off the intermediate product. - if (normalizedBits + numberBits >= Long.SIZE_BITS) { + // If it won't fit in a long, then we store off the intermediate product. + if (normalizedBits + numberBits >= java.lang.Long.SIZE) { bigNumbers.add(BigInteger.valueOf(number)) number = 1 numberBits = 0 @@ -83,11 +81,11 @@ class FactorialAdvanced { number *= normalizedNum numberBits = log2Floor(number) + 1 } - // check for leftovers. + // Check for leftovers. if (number > 1) { bigNumbers.add(BigInteger.valueOf(number)) } - // efficiently multiply all the intermediate products together. + // Efficiently multiply all the intermediate products together. return listNumbers(bigNumbers).shiftLeft(shift) } @@ -105,7 +103,7 @@ class FactorialAdvanced { if (rem == 0) { return div } - val signedNumber = 1 or (number xor divider shr Int.SIZE_BITS - 1) + val signedNumber = 1 or (number xor divider shr Integer.SIZE - 1) val increment = signedNumber > 0 return if (increment) div + signedNumber else div } @@ -117,21 +115,26 @@ class FactorialAdvanced { 2 -> numbers[start].multiply(numbers[start + 1]) 3 -> numbers[start].multiply(numbers[start + 1]).multiply(numbers[start + 2]) else -> { - // otherwise, split the list in half and recursively do this. + // Otherwise, split the list in half and recursively do this. val m = end + start ushr 1 listNumbers(numbers, start, m).multiply(listNumbers(numbers, m, end)) } } } - // returns the base-2 logarithm of number, rounded according to the celling. + /** + * Returns the base-2 logarithm of number, rounded according to the celling. + * + */ private fun log2Celling(number: Int): Int { - return Int.SIZE_BITS - (number - 1).countLeadingZeroBits() + return Integer.SIZE - Integer.numberOfLeadingZeros(number - 1) } - // returns the base-2 logarithm of number rounded according to the floor. + /** + * Returns the base-2 logarithm of number rounded according to the floor. + * + */ private fun log2Floor(number: Long): Int { - return Long.SIZE_BITS - 1 - number.countLeadingZeroBits() + return java.lang.Long.SIZE - 1 - java.lang.Long.numberOfLeadingZeros(number) } - } \ No newline at end of file diff --git a/src/main/kotlin/other/FactorialBigWithCache.kt b/src/main/kotlin/other/FactorialBigWithCache.kt index 489059d3..42ad01b0 100644 --- a/src/main/kotlin/other/FactorialBigWithCache.kt +++ b/src/main/kotlin/other/FactorialBigWithCache.kt @@ -3,32 +3,33 @@ package other import java.math.BigInteger /** - * * Algorithm for finding the factorial of a positive number n * * optimization: caching previous factorial values * * also adding large numbers - * - * worst time: O(n) - * the best time: O(1) - * amount of memory: O(n) - * problem: creating a huge number of BigInteger objects - * */ class FactorialBigWithCache { private val cache = hashMapOf() + /** + * + * worst time: O(n) + * the best time: O(1) + * amount of memory: O(n) + * problem: creating a huge number of BigInteger objects + * + * @return returns the factorial of a number + */ fun compute(number: Int) : BigInteger { if (number <= 1) { return BigInteger.ONE } - val cachedResult = cache[number] - if (cachedResult != null) { - return cachedResult + if (cache.contains(number)) { + return cache[number]!! } var result = BigInteger.ONE diff --git a/src/main/kotlin/other/FactorialWithCache.kt b/src/main/kotlin/other/FactorialWithCache.kt index 00915327..f2a27379 100644 --- a/src/main/kotlin/other/FactorialWithCache.kt +++ b/src/main/kotlin/other/FactorialWithCache.kt @@ -1,29 +1,30 @@ package other /** - * * Algorithm for finding the factorial of a positive number n * * optimization: caching previous factorial values - * - * worst time: O(n) - * the best time: O(1) - * amount of memory: O(n) - * */ class FactorialWithCache { private val cache = hashMapOf() + /** + * + * worst time: O(n) + * the best time: O(1) + * amount of memory: O(n) + * + * @return returns the factorial of a number + */ fun compute(number: Int) : Int { if (number <= 1) { return 1 } - val cachedResult = cache[number] - if (cachedResult != null) { - return cachedResult + if (cache.contains(number)) { + return cache[number]!! } var result = 1 diff --git a/src/main/kotlin/other/FizzBuzz.kt b/src/main/kotlin/other/FizzBuzz.kt index 9f68dc7d..2624dead 100644 --- a/src/main/kotlin/other/FizzBuzz.kt +++ b/src/main/kotlin/other/FizzBuzz.kt @@ -12,7 +12,11 @@ package other class FizzBuzz { - // determines what to say for a number in the FizzBuzz game and returns Fizz, Buzz, FizzBuzz or number + /** + * determines what to say for a number in the FizzBuzz game + * + * @return returns Fizz, Buzz, FizzBuzz or number + */ fun compute(number: Int) : String { return when { number % 3 == 0 && number % 5 == 0 -> "FizzBuzz" diff --git a/src/main/kotlin/other/KnuthMorrisPratt.kt b/src/main/kotlin/other/KnuthMorrisPratt.kt new file mode 100644 index 00000000..def149ed --- /dev/null +++ b/src/main/kotlin/other/KnuthMorrisPratt.kt @@ -0,0 +1,47 @@ +package other + +/** + * Knut Morris Pratt's Algorithm for finding a substring in a string + * + */ + +class KnuthMorrisPratt { + + /** + * + * @return returns an array of prefix functions for a string + */ + private fun prefixFunction(str: String) : Array { + val pi = Array(str.length) { 0 } + for (index in 1 until str.length) { + var k = pi[index - 1] + while (k > 0 && str[index] != str[k]) { + k = pi[k - 1] + } + if (str[index] == str[k]) { + k++ + } + pi[index] = k + } + return pi + } + + /** + * + * @return returns true if the substring is in the string + */ + fun contains(sub: String, str: String) : Boolean { + val summary = "$sub#$str" + val pi = prefixFunction(summary) + return pi.any { value -> value == sub.length } + } + + /** + * + * @return returns the number of occurrences of a substring in a string + */ + fun count(sub: String, str: String) : Int { + val summary = "$sub#$str" + return prefixFunction(summary).count { value -> value == sub.length } + } +} \ No newline at end of file diff --git a/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt b/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt deleted file mode 100644 index f90b7dc9..00000000 --- a/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt +++ /dev/null @@ -1,45 +0,0 @@ -package other - -/** - * - * Knut Morris Pratt's Algorithm for finding a substring in a string - * - */ - -class KnuthMorrisPrattAlgorithm { - - // returns true if the substring is in the string - fun contains(sub: String, str: String) : Boolean { - val summary = "$sub$SEPARATOR$str" - val prefixFunctionValue = prefixFunction(summary) - return prefixFunctionValue.any { value -> value == sub.length } - } - - // returns the number of occurrences of a substring in a string - fun count(sub: String, str: String) : Int { - val summary = "$sub$SEPARATOR$str" - return prefixFunction(summary).count { value -> value == sub.length } - } - - // returns an array of prefix functions for a string - private fun prefixFunction(str: String) : Array { - val prefixFunctionsValues = Array(str.length) { 0 } - for (index in 1 until str.length) { - var prefixFunctionValue = prefixFunctionsValues[index - 1] - while (prefixFunctionValue > 0 && str[index] != str[prefixFunctionValue]) { - prefixFunctionValue = prefixFunctionsValues[prefixFunctionValue - 1] - } - if (str[index] == str[prefixFunctionValue]) { - prefixFunctionValue++ - } - prefixFunctionsValues[index] = prefixFunctionValue - } - return prefixFunctionsValues - } - - companion object { - // delimiter must not occur in source strings - private const val SEPARATOR = "#" - } - -} \ No newline at end of file diff --git a/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt b/src/main/kotlin/other/LevensteinLength.kt similarity index 80% rename from src/main/kotlin/other/LevenshteinLengthAlgorithm.kt rename to src/main/kotlin/other/LevensteinLength.kt index 40508680..e135d9e3 100644 --- a/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt +++ b/src/main/kotlin/other/LevensteinLength.kt @@ -8,8 +8,15 @@ import java.lang.Integer.min * */ -class LevenshteinLengthAlgorithm { - +class LevenshteinLength { + + /** + * + * determines the Levenshtein distance for two strings and returns it + * + * @return returns the Levenshtein distance for two strings + * + */ fun compute(str1: String, str2: String) : Int { val matrix = Array(str1.length + 1) { Array(str2.length + 1) { 0 } diff --git a/src/main/kotlin/other/MaxAlgorithm.kt b/src/main/kotlin/other/Max.kt similarity index 61% rename from src/main/kotlin/other/MaxAlgorithm.kt rename to src/main/kotlin/other/Max.kt index 30ca6bc6..508c3bfb 100644 --- a/src/main/kotlin/other/MaxAlgorithm.kt +++ b/src/main/kotlin/other/Max.kt @@ -3,16 +3,20 @@ package other import java.lang.IllegalArgumentException /** - * * Algorithm for finding the maximum value from a list * */ -class MaxAlgorithm { +class Max> { - fun > compute(items: List) : T { + /** + * + * @return returns the maximum element from the list + * + */ + fun compute(items: List) : T { if (items.isEmpty()) { - throw IllegalArgumentException("items list is empty!") + throw IllegalArgumentException("items is empty!") } var max = items[0] for (i in 1 until items.size) { @@ -24,12 +28,11 @@ class MaxAlgorithm { } /** - * returns the maximum element from the list recursively + * + * @return returns the maximum element from the list recursively + * */ - fun > computeRecursive(items: List) : T { - if (items.isEmpty()) { - throw IllegalArgumentException("items list is empty!") - } + fun computeRecursive(items: List) : T { if (items.size == 1) { return items.first() } diff --git a/src/main/kotlin/other/MinAlgorithm.kt b/src/main/kotlin/other/Min.kt similarity index 63% rename from src/main/kotlin/other/MinAlgorithm.kt rename to src/main/kotlin/other/Min.kt index e2fc8e99..ba27a78b 100644 --- a/src/main/kotlin/other/MinAlgorithm.kt +++ b/src/main/kotlin/other/Min.kt @@ -3,16 +3,19 @@ package other import java.lang.IllegalArgumentException /** - * * Algorithm for finding the minimum value from a list * */ -class MinAlgorithm { +class Min> { - fun > compute(items: List) : T { + /** + * + * @return returns the minimum element from the list + */ + fun compute(items: List) : T { if (items.isEmpty()) { - throw IllegalArgumentException("items list is empty!") + throw IllegalArgumentException("items is empty!") } var min = items[0] for (i in 1 until items.size) { @@ -23,10 +26,11 @@ class MinAlgorithm { return min } - fun > computeRecursive(items: List) : T { - if (items.isEmpty()) { - throw IllegalArgumentException("items list is empty!") - } + /** + * + * @return returns the minimum element from the list recursively + */ + fun computeRecursive(items: List) : T { if (items.size == 1) { return items.first() } diff --git a/src/main/kotlin/other/Palindrome.kt b/src/main/kotlin/other/Palindrome.kt new file mode 100644 index 00000000..2a80b5c3 --- /dev/null +++ b/src/main/kotlin/other/Palindrome.kt @@ -0,0 +1,28 @@ +package other + +/** + * + * Algorithm for checking a string for a palindrome + * +*/ + +class Palindrome(private val text: String) { + + /** + * + * checks a string for a palindrome + * + * @return returns true if the string is a palindrome + * + */ + fun isYes() = text == text.reversed() + + /** + * checks if a string is not a palindrome + * + * @return returns true if the string is not a palindrome + * + */ + fun isNot() = !isYes() + +} \ No newline at end of file diff --git a/src/main/kotlin/other/PalindromeAdvanced.kt b/src/main/kotlin/other/PalindromeAdvanced.kt new file mode 100644 index 00000000..4a31cd29 --- /dev/null +++ b/src/main/kotlin/other/PalindromeAdvanced.kt @@ -0,0 +1,39 @@ +package other + +/** + * + * Algorithm for checking a string for a palindrome + * + */ + +class PalindromeAdvanced(private val text: String) { + + /** + * + * checks a string for a palindrome + * + * @return returns true if the string is a palindrome + * + */ + fun isYes() : Boolean { + if (text.length <= 1) { + return true + } + for (i in 0 until text.length / 2) { + if (text[i] != text[text.length - 1 - i]) { + return false + } + } + return true + } + + /** + * + * checks if a string is not a palindrome + * + * @return returns true if the string is not a palindrome + * + */ + fun isNot() = !isYes() + +} \ No newline at end of file diff --git a/src/main/kotlin/other/PalindromeAlgorithm.kt b/src/main/kotlin/other/PalindromeAlgorithm.kt deleted file mode 100644 index 9119efc4..00000000 --- a/src/main/kotlin/other/PalindromeAlgorithm.kt +++ /dev/null @@ -1,33 +0,0 @@ -package other - -/** - * - * Algorithm for checking a string for a palindrome - * - * P.S. A palindrome is a word, number, phrase, or other sequence of symbols - * that reads the same backwards as forwards, such as "madam" - */ - -class PalindromeAlgorithm { - - // checks a string for a palindrome and returns true if the string is a palindrome - fun isPalindrome(text: String): Boolean { - if (text.length <= 1) { - return true - } - - val length = text.length - for (index in 0 until length / 2) { - if (text[index] != text[length - index - 1]) { - return false - } - } - - return true - } - - fun isPalindromeSimplifiedVersion(text: String): Boolean { - return text == text.reversed() - } - -} \ No newline at end of file diff --git a/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt b/src/main/kotlin/other/ParenthesisCheck.kt similarity index 64% rename from src/main/kotlin/other/ParenthesisCheckAlgorithm.kt rename to src/main/kotlin/other/ParenthesisCheck.kt index c6b3296b..ebc71016 100644 --- a/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt +++ b/src/main/kotlin/other/ParenthesisCheck.kt @@ -2,7 +2,7 @@ package other /** * - * Algorithm for checking a string for correct placement of parentheses using stack + * checks a string for correct placement of parentheses using stack * * ([]) - correctly * ()(){} - correctly @@ -11,10 +11,16 @@ package other * */ -class ParenthesisCheckAlgorithm { +class ParenthesisCheck { - fun check(code: String = DEFAULT_CODE): Boolean { - // we use a regular kotlin list to create a stack + /** + * + * we use a regular kotlin list to create a stack + * + * @return returns true if parentheses are correctly spaced otherwise false + * + */ + fun check(code: String = defaultCode): Boolean { val stack = mutableListOf() var index = 0 @@ -33,12 +39,16 @@ class ParenthesisCheckAlgorithm { index++ } - return stack.isEmpty() + return true } companion object { - // the correct C program - private const val DEFAULT_CODE = """ + /** + * + * correct C program + * + */ + private const val defaultCode = """ void main() { printf("Hello, World!"); } diff --git a/src/main/kotlin/other/ReverseArray.kt b/src/main/kotlin/other/ReverseArray.kt new file mode 100644 index 00000000..306cf070 --- /dev/null +++ b/src/main/kotlin/other/ReverseArray.kt @@ -0,0 +1,26 @@ +package other + +/** + * + * reverse array + * + * algorithm complexity: n/2 operations + * + */ + +class ReverseArray { + + /** + * creates and returns a reverse array + * + */ + fun compute(array: Array) : Array { + val newArray = array.copyOf() + for (index in 0 until array.size / 2) { + newArray[index] = newArray[array.size - index - 1].apply { + newArray[array.size - index - 1] = newArray[index] + } + } + return newArray + } +} \ No newline at end of file diff --git a/src/main/kotlin/other/ReverseArrayAlgorithm.kt b/src/main/kotlin/other/ReverseArrayAlgorithm.kt deleted file mode 100644 index d0dfab77..00000000 --- a/src/main/kotlin/other/ReverseArrayAlgorithm.kt +++ /dev/null @@ -1,22 +0,0 @@ -package other - -/** - * - * Algorithm for reversing the order of an array - * - * complexity: O(n/2) + O(n) - * - */ - -class ReverseArrayAlgorithm { - - fun compute(array: Array) { - val size = array.size - for (index in 0 until size / 2) { - array[index] = array[size - index - 1].apply { - array[size - index - 1] = array[index] - } - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt b/src/main/kotlin/other/SieveOfEratosthenes.kt similarity index 77% rename from src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt rename to src/main/kotlin/other/SieveOfEratosthenes.kt index 396a87a1..d5c70766 100644 --- a/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt +++ b/src/main/kotlin/other/SieveOfEratosthenes.kt @@ -8,9 +8,16 @@ package other * */ -class SieveOfEratosthenesAlgorithm { - - // computes a series of primes up to the maximum value and returns a list of prime numbers +class SieveOfEratosthenes { + + /** + * + * computes a series of primes for the maximum value + * + * @param maxNumber - maximum value + * @return returns a list of prime numbers + * + */ fun compute(maxNumber: Int) : List { val numbers = Array(maxNumber + 1) { index -> index >= 2 } diff --git a/src/main/kotlin/other/Sqrt.kt b/src/main/kotlin/other/Sqrt.kt index b2cd6c06..6b039b79 100644 --- a/src/main/kotlin/other/Sqrt.kt +++ b/src/main/kotlin/other/Sqrt.kt @@ -1,19 +1,21 @@ package other /** - * * Algorithm for finding the square root of a number * - * read the wikipedia article: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Heron's_method - * + * Wikipedia: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BD%D0%B0%D1%85%D0%BE%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F_n-%D0%BD%D0%BE%D0%B9_%D1%81%D1%82%D0%B5%D0%BF%D0%B5%D0%BD%D0%B8 */ class Sqrt { - // calculates the root of a number and returns result + /** + * calculates the root of a number + * + * @number - number + * @return returns the root of a number + */ fun compute(number: Double) : Double { var value = number / 2 - // the number of loop iterations is selected depending on the required accuracy for (i in 1..100) { value = (value + number / value) / 2 } diff --git a/src/main/kotlin/other/StringEqualsHashAlgorithm.kt b/src/main/kotlin/other/StringEqualsHash.kt similarity index 78% rename from src/main/kotlin/other/StringEqualsHashAlgorithm.kt rename to src/main/kotlin/other/StringEqualsHash.kt index 6100beb9..182ebbcf 100644 --- a/src/main/kotlin/other/StringEqualsHashAlgorithm.kt +++ b/src/main/kotlin/other/StringEqualsHash.kt @@ -2,14 +2,11 @@ package other /** * - * Algorithm for comparing two strings with a hash + * comparing two strings with a hash * */ -class StringEqualsHashAlgorithm { - - fun equals(source: String, pattern: String) : Boolean = - if (source.length != pattern.length) false else source.hash() == pattern.hash() +class StringEqualsHash { /** * @@ -17,18 +14,22 @@ class StringEqualsHashAlgorithm { * * hash(abc) = a.code * primeCoefficient⁰ + b.code * primeCoefficient¹ + c.code * primeCoefficient² * + * @return returns the hash of the string + * */ private fun String.hash() : Int { var result = 0 var factor = 1 forEach { symbol -> result += symbol.code * factor - factor *= PRIME_COEFFICIENT + factor *= primeCoefficient } - // the hash can exceed the maximum Int value, so we limit it return result.mod(Int.MAX_VALUE) } + fun equals(source: String, pattern: String) : Boolean = + if (source.length != pattern.length) false else source.hash() == pattern.hash() + companion object { /** * @@ -39,6 +40,6 @@ class StringEqualsHashAlgorithm { * size of the alphabet = 26 + 26 + 3 = 55 (is not prime) * */ - private const val PRIME_COEFFICIENT = 53 + private const val primeCoefficient = 53 } } \ No newline at end of file diff --git a/src/main/kotlin/other/Swap.kt b/src/main/kotlin/other/Swap.kt new file mode 100644 index 00000000..8f43ec69 --- /dev/null +++ b/src/main/kotlin/other/Swap.kt @@ -0,0 +1,84 @@ +package other + +/** + * Algorithm for exchanging two variables without a third additional + * + */ + +class Swap { + + /** + * Kotlin Extension for checking list index for correctness + * + * @return returns true if the element is accessible by index + */ + private fun List.inIndex(index: Int) = index in 0 until size + + /** + * Kotlin Extension to check array index for correctness + * + * @return returns true if the element is accessible by index + */ + private fun Array.inIndex(index: Int) = index in 0 until size + + /** + * swaps two list values at the specified indexes + * + * @list - list + * @old - index of first element + * @new - index of the second element + */ + fun swap(list: MutableList, old: Int, new: Int) { + if (list.inIndex(old) && list.inIndex(new)) { + list[old] = list[old] + list[new] + list[new] = list[old] - list[new] + list[old] = list[old] - list[new] + } + } + + /** + * swaps two array values at the specified indexes + * + * @array - array + * @old - index of first element + * @new - index of the second element + */ + fun swap(array: Array, old: Int, new: Int) { + if (array.inIndex(old) && array.inIndex(new)) { + array[old] = array[old] + array[new] + array[new] = array[old] - array[new] + array[old] = array[old] - array[new] + } + } + + /** + * swaps two values using Kotlin language features + * + * @list - list + * @old - index of first element + * @new - index of the second element + */ + fun swapKotlin(list: MutableList, old: Int, new: Int) { + if (list.inIndex(old) && list.inIndex(new)) { + list[old] = list[new].apply { + list[new] = list[old] + } + } + } + + /** + * swaps two values using Kotlin language features + * + * @array - array + * @old - index of first element + * @new - index of the second element + */ + fun swapKotlin(array: Array, old: Int, new: Int) { + if (array.inIndex(old) && array.inIndex(new)) { + array[old] = array[new].apply { + array[new] = array[old] + } + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/other/SwapAlgorithm.kt b/src/main/kotlin/other/SwapAlgorithm.kt deleted file mode 100644 index 356b295c..00000000 --- a/src/main/kotlin/other/SwapAlgorithm.kt +++ /dev/null @@ -1,47 +0,0 @@ -package other - -/** - * - * Algorithm for exchanging two variables without a third additional - * - */ - -class SwapAlgorithm { - - // swaps two list values at the specified indexes - fun swap(list: MutableList, oldIndex: Int, newIndex: Int) { - if (oldIndex in list.indices && newIndex in list.indices) { - list[oldIndex] = list[oldIndex] + list[newIndex] - list[newIndex] = list[oldIndex] - list[newIndex] - list[oldIndex] = list[oldIndex] - list[newIndex] - } - } - - // swaps two array values at the specified indexes - fun swap(array: Array, oldIndex: Int, newIndex: Int) { - if (oldIndex in array.indices && newIndex in array.indices) { - array[oldIndex] = array[oldIndex] + array[newIndex] - array[newIndex] = array[oldIndex] - array[newIndex] - array[oldIndex] = array[oldIndex] - array[newIndex] - } - } - - // swaps two list values using Kotlin language features - fun swapKotlin(list: MutableList, oldIndex: Int, newIndex: Int) { - if (oldIndex in list.indices && newIndex in list.indices) { - list[oldIndex] = list[newIndex].apply { - list[newIndex] = list[oldIndex] - } - } - } - - // swaps two array values using Kotlin language features - fun swapKotlin(array: Array, oldIndex: Int, newIndex: Int) { - if (oldIndex in array.indices && newIndex in array.indices) { - array[oldIndex] = array[newIndex].apply { - array[newIndex] = array[oldIndex] - } - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/search/BinarySearch.kt b/src/main/kotlin/search/BinarySearch.kt index f65ad918..9ec268b6 100644 --- a/src/main/kotlin/search/BinarySearch.kt +++ b/src/main/kotlin/search/BinarySearch.kt @@ -1,57 +1,24 @@ package search /** + * name: binary search algorithm * - * Binary search algorithm only works for sorted lists and arrays + * description: one of the most important features of this algorithm + * is that it only works for sorted lists and arrays * - * best time: 1 - * worst time: log(n) + * time: log(n) * amount of memory: 1 - * */ -class BinarySearch { - - // searches for an element in the array and returns the index of the searched element or -1 - fun > search(array: Array, element: T) : Int { - if (array.isEmpty()) return -1 - - var left = 0 - var right = array.size - while (left < right) { - val middle = left + (right - left) / 2 - if (array[middle] < element) { - left = middle + 1 - } else if (array[middle] > element) { - right = middle - } else { - return middle - } - } - return -1 - } - - // recursive method - // P.S. The tailrec modifier tells the compiler to optimize the recursion and turn it into an iterative version - tailrec fun > searchRecursive(array: Array, element: T, left: Int = 0, right: Int = array.size - 1): Int { - if (left <= right) { - val middle = left + (right - left) / 2 - if (array[middle] == element) { - return middle - } - return if (array[middle] > element) { - searchRecursive(array, element, left, middle - 1) - } else { - searchRecursive(array, element, middle + 1, right) - } - } - return -1 - } - - // finds the left border index to insert an element into a sorted array - fun > leftBound(array: Array, element: T) : Int { - if (array.isEmpty()) return 0 +class BinarySearch> : Search { + /** + * finds the left border to insert an element into a sorted array + * + * @array - sorted array to be searched + * @element - the element for which the left border is being searched + */ + fun leftBound(array: Array, element: T) : Int { var left = -1 var right = array.size while ((right - left) > 1) { @@ -65,10 +32,13 @@ class BinarySearch { return left } - // finds the right border index to insert an element into a sorted array - fun > rightBound(array: Array, element: T) : Int { - if (array.isEmpty()) return -1 - + /** + * finds the right border to insert an element into a sorted array + * + * @array - sorted array to be searched + * @element - the element for which the right border is being searched + */ + fun rightBound(array: Array, element: T) : Int { var left = -1 var right = array.size while ((right - left) > 1) { @@ -82,4 +52,40 @@ class BinarySearch { return right } + /** + * checks if an element is in an array + * + * @array - the array in which we are looking for the element + * @element - search element + * + * @return returns true if the element is present in the array, false otherwise + */ + override fun exists(array: Array, element: T): Boolean { + return search(array, element) != -1 + } + + /** + * searches for an element in an array + * + * @array - array + * @element - search element + * + * @return returns the index of the searched element or -1 + */ + override fun search(array: Array, element: T) : Int { + var left = 0 + var right = array.size - 1 + while (left <= right) { + val middle = (left + right) / 2 + if (array[middle] < element) { + left = middle + 1 + } else if (array[middle] > element) { + right = middle + } else { + return middle + } + } + return -1 + } + } \ No newline at end of file diff --git a/src/main/kotlin/search/BinarySearchRecursive.kt b/src/main/kotlin/search/BinarySearchRecursive.kt new file mode 100644 index 00000000..97a5c7e5 --- /dev/null +++ b/src/main/kotlin/search/BinarySearchRecursive.kt @@ -0,0 +1,58 @@ +package search + +/** + * name: binary search algorithm implemented in a recursive way + * + * worst time: log(n) + * amount of memory: log(n) - recursion stack + */ + +class BinarySearchRecursive> : Search { + + /** + * проверяет присутствие элемента в массиве + * возвращает индекс искомого элемента, в противном случае -1 + * + * @array - отсортированный массив + * @element - искомый элемент + */ + override fun search(array: Array, element: T): Int { + return searchRecursive(array, 0, array.size - 1, element) + } + + /** + * проверяет присутствие элемента в массиве + * возвращает true или false + * + * @array - отсортированный массив + * @element - искомый элемент + */ + override fun exists(array: Array, element: T): Boolean { + return searchRecursive(array, 0, array.size - 1, element) != -1 + } + + /** + * возвращает индекс искомого элемента, в противном случае -1 + * + * @array - отсортированный массив + * @left - левая граница + * @right - правая граница + * @element - искомый элемент + */ + private tailrec fun searchRecursive(array: Array, left: Int, right: Int, element: T) : Int { + if (left <= right) { + val middle = left + (right - left) / 2 + if (array[middle] == element) { + return middle + } + return if (array[middle] > element) { + searchRecursive(array, left, middle - 1, element) + } else { + searchRecursive(array, middle + 1, right, element) + } + } + return -1 + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/search/LinearSearch.kt b/src/main/kotlin/search/LinearSearch.kt index c8f5bd3c..a11e0ac9 100644 --- a/src/main/kotlin/search/LinearSearch.kt +++ b/src/main/kotlin/search/LinearSearch.kt @@ -1,24 +1,35 @@ package search /** + * name: linear search algorithm * - * Linear search algorithm - * - * best time: 1 * worst time: n * amount of memory: 1 - * */ -class LinearSearch { +class LinearSearch> : Search { + + /** + * returns true if the element was found in the array + * + * @array - sorted array + * @element - search element + */ + override fun exists(array: Array, element: T) : Boolean { + return search(array, element) != -1 + } - fun > search(array: Array, element: T) : Int { - var index = 0 - while (index < array.size) { - if (element == array[index]) { - return index + /** + * returns the index of the searched element, otherwise -1 + * + * @array - sorted array + * @element - search element + */ + override fun search(array: Array, element: T) : Int { + for (i in array.indices) { + if (element == array[i]) { + return i } - index++ } return -1 } diff --git a/src/main/kotlin/search/Search.kt b/src/main/kotlin/search/Search.kt new file mode 100644 index 00000000..6e50dec5 --- /dev/null +++ b/src/main/kotlin/search/Search.kt @@ -0,0 +1,6 @@ +package search + +interface Search> { + fun search(array: Array, element: T) : Int + fun exists(array: Array, element: T) : Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/sorting/BubbleSort.kt b/src/main/kotlin/sorting/BubbleSort.kt index 01916042..933db3f4 100644 --- a/src/main/kotlin/sorting/BubbleSort.kt +++ b/src/main/kotlin/sorting/BubbleSort.kt @@ -1,59 +1,37 @@ package sorting /** + * bubble sort * - * Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm - * - * that repeatedly steps through the input list element by element, comparing the current element - * - * with the one after it, swapping their values if needed + * worst time: n² + * the best time: n² + * average time: n² * + * amount of memory: 1 */ -class BubbleSort { - - /** - * worst time: n² - * best time: n² - * average time: n² - * - * amount of memory: 1 - */ - fun > sort(array: Array) { - val arraySize = array.size - for (i in 0 until arraySize - 1) { - for (j in 0 until arraySize - 1 - i) { - if (array[j] > array[j + 1]) { - val tmp = array[j + 1] +fun > Array.bubbleSort() { + val array = this + for (i in 0 until size - 1) { + for (j in 0 until size - 1 - i) { + if (array[j] > array[j + 1]) { + array[j] = array[j + 1].apply { array[j + 1] = array[j] - array[j] = tmp } } } } +} - /** - * worst time: n² - * best time: n - * average time: n² - * - * amount of memory: 1 - */ - fun > sortImproved(array: Array) { - val arraySize = array.size - var isSorted = true - for (i in 0 until arraySize - 1) { - for (j in 0 until arraySize - 1 - i) { - if (array[j] > array[j + 1]) { - val tmp = array[j + 1] - array[j + 1] = array[j] - array[j] = tmp - - isSorted = false +fun > MutableList.bubbleSort() { + val list = this + for (i in 0 until size - 1) { + for (j in 0 until size - 1 - i) { + if (list[j] > list[j + 1]) { + list[j] = list[j + 1].apply { + list[j + 1] = list[j] } } - if (isSorted) break } } - } diff --git a/src/main/kotlin/sorting/BubbleSortImproved.kt b/src/main/kotlin/sorting/BubbleSortImproved.kt new file mode 100644 index 00000000..78bdb001 --- /dev/null +++ b/src/main/kotlin/sorting/BubbleSortImproved.kt @@ -0,0 +1,44 @@ +package sorting + +/** + * improved bubble sort + * + * worst time: n² + * the best time: n + * average time: n² + * + * amount of memory: 1 + */ + + +fun > Array.bubbleSortImproved() { + val array = this + var isSorted = true + for (i in 0 until size - 1) { + for (j in 0 until size - 1 - i) { + if (array[j] > array[j + 1]) { + isSorted = false + array[j] = array[j + 1].apply { + array[j + 1] = array[j] + } + } + } + if (isSorted) break + } +} + +fun > MutableList.bubbleSortImproved() { + val list = this + var isSorted = true + for (i in 0 until size - 1) { + for (j in 0 until size - 1 - i) { + if (list[j] > list[j + 1]) { + isSorted = false + list[j] = list[j + 1].apply { + list[j + 1] = list[j] + } + } + } + if (isSorted) break + } +} diff --git a/src/main/kotlin/sorting/CountSort.kt b/src/main/kotlin/sorting/CountSort.kt new file mode 100644 index 00000000..c6d49473 --- /dev/null +++ b/src/main/kotlin/sorting/CountSort.kt @@ -0,0 +1,36 @@ +package sorting + +/** + * count sort + * + * worst time: n + * the best time: n + * average time: n + * + * amount of memory: equals to the size of the range of numbers plus 1 (for example: 1001 for numbers from 0 to 1000) + * + * The use of counting sort is useful only when the sorted numbers have (or can be mapped to) a range of possible + * values that is small enough compared to the sorted set, for example, a million natural numbers less than 1000 + * + */ + +fun Array.countSort(start: Int, end: Int) { // sorts numbers in the range from start to end + val countedNumbers = Array(end + 1) { 0 } + + var index = 0 + while (index < size) { + countedNumbers[this[index]]++ + index++ + } + + index = 0 + var currentNumber = start + while (currentNumber < countedNumbers.size) { + var frequency = countedNumbers[currentNumber] + while (frequency > 0) { + this[index++] = currentNumber + frequency-- + } + currentNumber++ + } +} \ No newline at end of file diff --git a/src/main/kotlin/sorting/CountingSort.kt b/src/main/kotlin/sorting/CountingSort.kt deleted file mode 100644 index f720824a..00000000 --- a/src/main/kotlin/sorting/CountingSort.kt +++ /dev/null @@ -1,43 +0,0 @@ -package sorting - -/** - * - * Counting sort is a sorting technique based on keys between a specific range - * - * worst time: n - * best time: n - * average time: n - * - * amount of memory: equals to the size of the range of numbers plus 1 (for example: 1001 for numbers from 0 to 1000) - * - * P.S. The use of counting sort is useful only when the sorted numbers have (or can be mapped to) a range of possible - * values that is small enough compared to the sorted set, for example, a million natural numbers less than 1000 - * - */ - -class CountingSort { - - // sorts numbers in the range from start to end - fun sort(array: Array, start: Int, end: Int) { - val arraySize = array.size - val countedNumbers = Array(end + 1) { 0 } - - var index = 0 - while (index < arraySize) { - countedNumbers[array[index]]++ - index++ - } - - index = 0 - var currentNumber = start - while (currentNumber < countedNumbers.size) { - var frequency = countedNumbers[currentNumber] - while (frequency > 0) { - array[index++] = currentNumber - frequency-- - } - currentNumber++ - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/sorting/InsertionSort.kt b/src/main/kotlin/sorting/InsertionSort.kt index be0d77f9..9175e50a 100644 --- a/src/main/kotlin/sorting/InsertionSort.kt +++ b/src/main/kotlin/sorting/InsertionSort.kt @@ -1,34 +1,38 @@ package sorting /** - * - * Insertion sort is a simple sorting algorithm that works similar to the way you sort playing cards in your hands. - * - * The array is virtually split into a sorted and an unsorted part. - * - * Values from the unsorted part are picked and placed at the correct position in the sorted part. + * insertion sort algorithm * * worst time: n² - * best time: n + * the best time: n * average time: n² * * amount of time: 1 - * */ -class InsertionSort { - fun > sort(array: Array) { - val arraySize = array.size - for (i in 1 until arraySize) { - val current = array[i] - var j = i - 1 - while (j >= 0 && array[j] > current) { - array[j + 1] = array[j] - j-- - } - array[j + 1] = current +fun > Array.insertionSort() { + val array = this + for (i in 1 until size) { + val current = array[i] + var j = i - 1 + while (j >= 0 && array[j] > current) { + array[j + 1] = array[j] + j-- } + array[j + 1] = current } +} +fun > MutableList.insertionSort() { + val list = this + for (i in 1 until size) { + val current = list[i] + var j = i - 1 + while (j >= 0 && list[j] > current) { + list[j + 1] = list[j] + j-- + } + list[j + 1] = current + } } diff --git a/src/main/kotlin/sorting/MergeSort.kt b/src/main/kotlin/sorting/MergeSort.kt index 743ceb83..16241350 100644 --- a/src/main/kotlin/sorting/MergeSort.kt +++ b/src/main/kotlin/sorting/MergeSort.kt @@ -1,140 +1,116 @@ package sorting /** + * merge sort algorithm implemented without recursion * - * Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945 + * the best time: n * log(n) + * average time: n * log(n) + * worst time: n * log(n) * - * Conceptually, a merge sort works as follows: - * - * 1) Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted). - * - * 2) Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. - * This will be the sorted list. + * amount of memory: n * */ -class MergeSort { - - /** - * worst time: n * log(n) - * best time: n * log(n) - * average time: n * log(n) - * - * amount of memory: n - */ - fun > sort(array: Array) { - val arraySize = array.size - val temporaryArray = array.copyOf() - - var windowSize = 1 - while (windowSize < arraySize) { - - var left = 0 - while (left + windowSize < arraySize) { - - val middle = left + windowSize - var right = middle + windowSize - if (right > arraySize) right = arraySize - - var i = left - var k = left - var j = middle - while (i < middle && j < right) { - if (array[i] <= array[j]) { - temporaryArray[k] = array[i] - i++ - } else { - temporaryArray[k] = array[j] - j++ - } - k++ - } +fun > Array.mergeSort() { + val temporaryArray = this.copyOf() - while (i < middle) { - temporaryArray[k] = array[i] - i++ - k++ - } + var winSize = 1 + while (winSize < size) { - while (j < right) { - temporaryArray[k] = array[j] - j++ - k++ - } + var left = 0 + while (left + winSize < size) { - i = left - while (i < right) { - array[i] = temporaryArray[i] + val middle = left + winSize + var right = middle + winSize + if (right > size) right = size + + var i = left + var k = left + var j = middle + while (i < middle && j < right) { + if (this[i] <= this[j]) { + temporaryArray[k] = this[i] i++ + } else { + temporaryArray[k] = this[j] + j++ } + k++ + } - left += windowSize * 2 + while (i < middle) { + temporaryArray[k] = this[i] + i++ + k++ } - windowSize *= 2 - } - } + while (j < right) { + temporaryArray[k] = this[j] + j++ + k++ + } - /** - * worst time: n * log(n) - * best time: n * log(n) - * average time: n * log(n) - * - * amount of memory: n * log(n) - */ - fun sortRecursive(array: Array) { - val arraySize = array.size + i = left + while (i < right) { + this[i] = temporaryArray[i] + i++ + } - if (arraySize < 2) - return + left += winSize * 2 + } - val middle = arraySize / 2 + winSize *= 2 + } +} - val left = Array(middle) { 0 } - val right = Array(arraySize - middle) { 0 } +fun > MutableList.mergeSort() { + val temporaryArray = this.toMutableList() - var i = 0 - while (i < middle) { - left[i] = array[i] - i++ - } + var winSize = 1 + while (winSize < size) { - while (i < arraySize) { - right[i - middle] = array[i] - i++ - } + var left = 0 + while (left + winSize < size) { - sortRecursive(left) - sortRecursive(right) + val middle = left + winSize + var right = middle + winSize + if (right > size) right = size - val leftSize = left.size - val rightSize = right.size + var i = left + var k = left + var j = middle + while (i < middle && j < right) { + if (this[i] <= this[j]) { + temporaryArray[k] = this[i] + i++ + } else { + temporaryArray[k] = this[j] + j++ + } + k++ + } - i = 0 - var j = 0 - var k = 0 - while (i < leftSize && j < rightSize) { - if (left[i] <= right[j]) { - array[k] = left[i] + while (i < middle) { + temporaryArray[k] = this[i] i++ - } else { - array[k] = right[j] + k++ + } + + while (j < right) { + temporaryArray[k] = this[j] j++ + k++ } - k++ - } - while (i < leftSize) { - array[k] = left[i] - i++ - k++ - } + i = left + while (i < right) { + this[i] = temporaryArray[i] + i++ + } - while (j < rightSize) { - array[k] = right[j] - j++ - k++ + left += winSize * 2 } - } + winSize *= 2 + } } \ No newline at end of file diff --git a/src/main/kotlin/sorting/MergeSortRecursive.kt b/src/main/kotlin/sorting/MergeSortRecursive.kt new file mode 100644 index 00000000..ce491b33 --- /dev/null +++ b/src/main/kotlin/sorting/MergeSortRecursive.kt @@ -0,0 +1,100 @@ +package sorting + +/** + * merge sort algorithm implemented with recursion + * + * the best time: n * log(n) + * average time: n * log(n) + * worst time: n * log(n) + * + * amount of memory: n + * + */ + +fun Array.mergeSortRecursive() { + val array = this + + if (size < 2) + return + + val mid = size / 2 + + val left = Array(mid) { 0 } + val right = Array(size - mid) { 0 } + + for (i in 0 until mid) { + left[i] = array[i] + } + + for (i in mid until size) { + right[i - mid] = array[i] + } + + left.mergeSortRecursive() + right.mergeSortRecursive() + + var i = 0; var j = 0; var k = 0 + + val leftSize = left.size + val rightSize = right.size + + while (i < leftSize && j < rightSize) { + if (left[i] <= right[j]) { + array[k++] = left[i++] + } else { + array[k++] = right[j++] + } + } + + while (i < leftSize) { + array[k++] = left[i++] + } + + while (j < rightSize) { + array[k++] = right[j++] + } +} + +fun MutableList.mergeSortRecursive() { + val list = this + + if (size < 2) + return + + val mid = size / 2 + + val left = Array(mid) { 0 } + val right = Array(size - mid) { 0 } + + for (i in 0 until mid) { + left[i] = list[i] + } + + for (i in mid until size) { + right[i - mid] = list[i] + } + + left.mergeSortRecursive() + right.mergeSortRecursive() + + var i = 0; var j = 0; var k = 0 + + val leftSize = left.size + val rightSize = right.size + + while (i < leftSize && j < rightSize) { + if (left[i] <= right[j]) { + list[k++] = left[i++] + } else { + list[k++] = right[j++] + } + } + + while (i < leftSize) { + list[k++] = left[i++] + } + + while (j < rightSize) { + list[k++] = right[j++] + } +} diff --git a/src/main/kotlin/sorting/QuickSort.kt b/src/main/kotlin/sorting/QuickSort.kt index 4a6fe629..f285b324 100644 --- a/src/main/kotlin/sorting/QuickSort.kt +++ b/src/main/kotlin/sorting/QuickSort.kt @@ -3,51 +3,76 @@ package sorting import kotlin.random.Random /** - * - * QuickSort is a sorting algorithm based on the Divide and Conquer algorithm - * - * that picks an element as a pivot and partitions the given array around the picked pivot - * - * by placing the pivot in its correct position in the sorted array. - * + * quicksort algorithm * * worst time: n² - * best time: n * log(n) + * the best time: n * log(n) * average time: n * log(n) * * amount of memory: n - * */ -class QuickSort { - fun > sort(array: Array, start: Int = 0, end: Int = array.size - 1) { - if (array.isEmpty()) return - if (start >= end) return +fun > Array.quickSort(start: Int = 0, end: Int = size - 1) { + val array = this - val pivotIndex = Random.nextInt(start, end + 1) - val pivot = array[pivotIndex] + if (array.isEmpty()) return + if (start >= end) return - var i = start - var j = end - while (i <= j) { - while (array[i] < pivot) { - i++ - } - while (array[j] > pivot) { - j-- - } - if (i <= j) { - val tmp = array[i] - array[i] = array[j] - array[j] = tmp - i++ - j-- + val pivotIndex = Random.nextInt(start, end + 1) + val pivot = array[pivotIndex] + + var i = start + var j = end + + while (i <= j) { + while (array[i] < pivot) { + i++ + } + while (array[j] > pivot) { + j-- + } + if (i <= j) { + array[i] = array[j].apply { + array[j] = array[i] } + i++ + j-- } + } + + if (i < end) quickSort(i, end) + if (0 < j) quickSort(start, j) +} + +fun > MutableList.quickSort(start: Int = 0, end: Int = size - 1) { + val list = this + + if (list.isEmpty()) return + if (start >= end) return + + val pivotIndex = Random.nextInt(start, end + 1) + val pivot = list[pivotIndex] - if (i < end) sort(array, i, end) - if (0 < j) sort(array, start, j) + var i = start + var j = end + + while (i <= j) { + while (list[i] < pivot) { + i++ + } + while (list[j] > pivot) { + j-- + } + if (i <= j) { + list[i] = list[j].apply { + list[j] = list[i] + } + i++ + j-- + } } + if (i < end) quickSort(i, end) + if (0 < j) quickSort(start, j) } \ No newline at end of file diff --git a/src/main/kotlin/sorting/RadixSort.kt b/src/main/kotlin/sorting/RadixSort.kt index c1d28a1a..dcab1666 100644 --- a/src/main/kotlin/sorting/RadixSort.kt +++ b/src/main/kotlin/sorting/RadixSort.kt @@ -1,44 +1,66 @@ package sorting /** - * - * Radix Sort is a linear sorting algorithm that sorts elements by processing them digit by digit. - * - * It is an efficient sorting algorithm for integers or strings with fixed-size keys. + * radix sort algorithm applies only to integers * * worst time: * n * * amount of memory: 2 * n */ -class RadixSort { - fun sort(array: Array) { - val arraySize = array.size - val arrayOfZeroBits = Array(arraySize) { 0 } - val arrayOfOneBits = Array(arraySize) { 0 } +fun Array.radixSort() { + val array = this + val array1 = Array(size) { 0 } + val array2 = Array(size) { 0 } - val size = Int.SIZE_BITS + val size = Int.SIZE_BITS - for (radix in 0 until size) { - var size1 = 0 - var size2 = 0 - for (index in array.indices) { - if (array[index].and(1 shl radix) == 0) { - arrayOfZeroBits[size1++] = array[index] - } else { - arrayOfOneBits[size2++] = array[index] - } + for (radix in 0 until size) { + var size1 = 0 + var size2 = 0 + for (index in array.indices) { + if (array[index].and(1.shl(radix)) == 0) { + array1[size1++] = array[index] + } else { + array2[size2++] = array[index] } + } - for (index in 0 until size1) { - array[index] = arrayOfZeroBits[index] - } + for (index in 0 until size1) { + array[index] = array1[index] + } - for (index in 0 until size2) { - array[size1 + index] = arrayOfOneBits[index] - } + for (index in 0 until size2) { + array[size1 + index] = array2[index] } } +} + +fun MutableList.radixSort() { + val list = this + val array1 = MutableList(size) { 0 } + val array2 = MutableList(size) { 0 } + + val size = Int.SIZE_BITS + for (radix in 0 until size) { + var size1 = 0 + var size2 = 0 + for (index in list.indices) { + if (list[index].and(1.shl(radix)) == 0) { + array1[size1++] = list[index] + } else { + array2[size2++] = list[index] + } + } + + for (index in 0 until size1) { + list[index] = array1[index] + } + + for (index in 0 until size2) { + list[size1 + index] = array2[index] + } + } } \ No newline at end of file diff --git a/src/main/kotlin/sorting/SelectionSort.kt b/src/main/kotlin/sorting/SelectionSort.kt index 1d7ea4d0..661688e0 100644 --- a/src/main/kotlin/sorting/SelectionSort.kt +++ b/src/main/kotlin/sorting/SelectionSort.kt @@ -1,38 +1,45 @@ package sorting /** - * - * Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting - * - * the smallest (or largest) element from the unsorted portion of the list and - * - * moving it to the sorted portion of the list. + * selection sort algorithm * * worst time: n² - * best time: n² + * the best time: n² * average time: n² * * amount of memory: 1 - * */ -class SelectionSort { - - fun > sort(array: Array) { - val arraySize = array.size - for (i in 0 until arraySize - 1) { - var min = i - for (j in i + 1 until arraySize) { - if (array[min] > array[j]) { - min = j - } +fun > Array.selectionSort() { + val array = this + for (i in 0 until size - 1) { + var min = i + for (j in i + 1 until size) { + if (array[min] > array[j]) { + min = j } - if (min != i) { - val tmp = array[i] + } + if (min != i) { + array[min] = array[i].apply { array[i] = array[min] - array[min] = tmp } } } +} +fun > MutableList.selectionSort() { + val list = this + for (i in 0 until size - 1) { + var min = i + for (j in i + 1 until size) { + if (list[min] > list[j]) { + min = j + } + } + if (min != i) { + list[min] = list[i].apply { + list[i] = list[min] + } + } + } } diff --git a/src/main/kotlin/sorting/TimSort.kt b/src/main/kotlin/sorting/TimSort.kt index 34db046b..c5fdf65c 100644 --- a/src/main/kotlin/sorting/TimSort.kt +++ b/src/main/kotlin/sorting/TimSort.kt @@ -1,126 +1,110 @@ package sorting -import kotlin.math.min +import java.lang.Integer.min /** + * Tim sort algorithm * - * Tim Sort is a hybrid sorting algorithm derived from merge sort and insertion sort - * - * used by Python’s sorted() and list.sort() functions, which was designed to perform well on - * - * many kinds of real-world data. - * - * worst time: n * log(n) - * best time: n + * the best time: n * average time: n * log(n) + * worst time: n * log(n) * * amount of memory: n * */ -class TimSort { - - fun sort(array: Array) { - val arraySize = array.size - val minRunSize = minRunSize(arraySize) +fun Array.timSort() { + val size = size + val minrun = minrun(size) + var index = 0 + while (index < size) { + insertionSort(this, index, min(index + minrun - 1, size - 1)) + index += minrun + } - var i = 0 - while (i < arraySize) { - insertionSort(array, i, min(i + minRunSize - 1, arraySize - 1)) - i += minRunSize - } + var mergingSize = minrun + while (mergingSize < size) { - var mergingSize = minRunSize - while (mergingSize < arraySize) { - var start = 0 - while (start < arraySize) { - val middle = start + mergingSize - 1 - val end = min(start + 2 * mergingSize - 1, arraySize - 1) - if (middle < end) { - merge(array, start, middle, end) - } - start += mergingSize * 2 + var left = 0 + while (left < size) { + val middle = left + mergingSize - 1 + val right = min(left + 2 * mergingSize - 1, size - 1) + if (middle < right) { + merge(this, left, middle, right) } - mergingSize *= 2 - } - } - - /** - * Minrun is chosen from the range 32 to 64 inclusive, such that the size of the data, divided by minrun, is equal to, - * or slightly less than, a power of two. The final algorithm takes the six most significant bits of the size of the array, - * adds one if any of the remaining bits are set, and uses that result as the minrun. - * This algorithm works for all arrays, including those smaller than 64; for arrays of size 63 or less, - * this sets minrun equal to the array size and Timsort reduces to an insertion sort - */ - private fun minRunSize(arraySize: Int) : Int { - var result = 0 - var size = arraySize - while (size >= 64) { - result = result or (size and 1) - // shift one bit to the right until 6 significant bits remain - size = size shr 1 + left += mergingSize * 2 } - return size + result + mergingSize *= 2 } - - private fun insertionSort(array: Array, start: Int, end: Int) { - var i = start + 1 - while (i <= end) { - val current = array[i] - var j = i - 1 - while (j >= start && array[j] > current) { - array[j + 1] = array[j] - j-- - } - array[j + 1] = current - i++ +} + +private fun minrun(n: Int) : Int { + var addedValue = 0 + var size = n + if (size >= 64) { + addedValue = addedValue or (size and 1) + size = size.shr(1) + } + return size + addedValue +} + +private fun insertionSort(array: Array, left: Int, right: Int) { + var outerIndex = left + 1 + while (outerIndex <= right) { + val temporaryValue = array[outerIndex] + var innerIndex = outerIndex - 1 + while (innerIndex >= left && array[innerIndex] > temporaryValue) { + array[innerIndex + 1] = array[innerIndex] + innerIndex-- } + array[innerIndex + 1] = temporaryValue + outerIndex++ } +} - private fun merge(array: Array, start: Int, middle: Int, end: Int) { - val leftSize = middle - start + 1 - val rightSize = end - middle - - var i = 0 - val leftArray = Array(leftSize) { 0 } - while (i < leftSize) { - leftArray[i] = array[start + i] - i++ - } +private fun merge(array: Array, left: Int, middle: Int, right: Int) { + val leftLengthArray = middle - left + 1 + val rightLengthArray = right - middle - i = 0 - val rightArray = Array(rightSize) { 0 } - while (i < rightSize) { - rightArray[i] = array[middle + i + 1] - i++ - } + var index = 0 + var leftArray = Array(leftLengthArray) { 0 } + while (index < leftLengthArray) { + leftArray[index] = array[left + index] + index++ + } - i = 0 - var j = 0 - var k = start - while (i < leftSize && j < rightSize) { - if (leftArray[i] <= rightArray[j]) { - array[k] = leftArray[i] - i++ - } else { - array[k] = rightArray[j] - j++ - } - k++ - } + index = 0 + var rightArray = Array(rightLengthArray) { 0 } + while (index < rightLengthArray) { + rightArray[index] = array[middle + 1 + index] + index++ + } - while (i < leftSize) { - array[k] = leftArray[i] - i++ - k++ + var leftArrayIndex = 0 + var rightArrayIndex = 0 + index = 0 + + while (leftArrayIndex < leftLengthArray && rightArrayIndex < rightLengthArray) { + if (leftArray[leftArrayIndex] <= rightArray[rightArrayIndex]) { + array[index] = leftArray[leftArrayIndex] + leftArrayIndex++ + } else { + array[index] = rightArray[rightArrayIndex] + rightArrayIndex++ } + index++ + } - while (j < rightSize) { - array[k] = rightArray[j] - j++ - k++ - } + while (leftArrayIndex < leftLengthArray) { + array[index] = leftArray[leftArrayIndex] + leftArrayIndex++ + index++ } + while (rightArrayIndex < rightLengthArray) { + array[index] = rightArray[rightArrayIndex] + rightArrayIndex++ + index++ + } } \ No newline at end of file diff --git a/src/main/kotlin/structures/BinaryTree.kt b/src/main/kotlin/structures/BinaryTree.kt index 58fb4355..7f774c58 100644 --- a/src/main/kotlin/structures/BinaryTree.kt +++ b/src/main/kotlin/structures/BinaryTree.kt @@ -1,19 +1,16 @@ package structures -import java.util.LinkedList - /** + * data structure: binary tree * - * Binary tree consists of nodes each of which has a maximum of two children. - * - * Child nodes satisfy the following requirements: - * - * - the left child is less than the parent - * - right child is larger than parent - * - * Hint: the worst time may be O(n) because the situation is possible when the elements follow each other 1,2,3,4... - * and the tree takes the following form: + * description: consists of nodes, each of which has a maximum of two children, + * child nodes satisfy the following requirements: + * - the left child is less than the parent; + * - right child is larger than parent; * + * average search time: log(n) + * worst search time: n + * because the situation is possible when the elements follow each other 1,2,3,4... and the tree takes the following form: * 1 * \ * 2 @@ -21,52 +18,56 @@ import java.util.LinkedList * 3 * \ * 4 + * the same complexity is true for adding and removing nodes * */ -class BinaryTree> { - - private var root: Node? = null +class BinaryTree { - val isEmpty: Boolean - get() = root == null + /** + * binary tree root + */ + private var root: Node? = null /** - * Complexity: - * worst time: O(n), read the hint in the description - * best time: O(log(n)) - * average time: O(log(n)) + * adding a new element to the tree + * + * @param value - element value */ - fun add(value: T) { - fun addRecursive(current: Node?, value: T): Node { + fun add(value: Int) { + fun addRec(current: Node?, value: Int) : Node { if (current == null) { return Node(value) } if (value < current.value()) { - current.changeLeft(addRecursive(current.leftNode(), value)) + current.changeLeft(addRec(current.leftNode(), value)) } else if (value > current.value()) { - current.changeRight(addRecursive(current.rightNode(), value)) + current.changeRight(addRec(current.rightNode(), value)) } return current } - root = addRecursive(root, value) + root = addRec(root, value) } /** - * Complexity: - * worst time: O(n), read the hint in the description - * best time: O(1) - * average time: O(log(n)) + * checks the tree for emptiness + * + * @return returns true if the tree does not contain any nodes + */ + fun isEmpty() = root == null + + /** + * removing an element from the tree + * + * @param value - the value of the element to be removed */ - fun remove(value: T) { - fun smallestValue(root: Node): T { - val leftNode = root.leftNode() - if (leftNode === null) return root.value() - return smallestValue(leftNode) + fun remove(value: Int) { + fun smallestValue(root: Node) : Int { + return if (root.leftNode() == null) root.value() else smallestValue(root.leftNode()!!) } - fun removeRecursive(current: Node?, value: T): Node? { + fun removeRec(current: Node?, value: Int) : Node? { if (current == null) { return null } @@ -84,30 +85,31 @@ class BinaryTree> { val smallestValue = smallestValue(current.rightNode()!!) current.changeValue(smallestValue) - current.changeRight(removeRecursive(current.rightNode(), smallestValue)) + current.changeRight(removeRec(current.rightNode(), smallestValue)) return current } if (value < current.value()) { - current.changeLeft(removeRecursive(current.leftNode(), value)) + current.changeLeft(removeRec(current.leftNode(), value)) } else { - current.changeRight(removeRecursive(current.rightNode(), value)) + current.changeRight(removeRec(current.rightNode(), value)) } return current } - root = removeRecursive(root, value) + root = removeRec(root, value) } /** - * Complexity: - * worst time: O(n), read the hint in the description - * best time: O(1) - * average time: O(log(n)) + * checking for the existence of an element in the tree + * + * @param value - element value + * + * @return - returns true if the element exists */ - fun contains(value: T): Boolean { - fun containsRecursive(current: Node?, value: T): Boolean { + fun contains(value: Int) : Boolean { + fun containsRec(current: Node?, value: Int) : Boolean { if (current == null) { return false } @@ -115,66 +117,66 @@ class BinaryTree> { return true } return if (value < current.value()) { - containsRecursive(current.leftNode(), value) + containsRec(current.leftNode(), value) } else { - containsRecursive(current.rightNode(), value) + containsRec(current.rightNode(), value) } } - return containsRecursive(root, value) + return containsRec(root, value) } /** + * traversal of the binary tree in depth * - * Traversal of the binary tree in depth - * - * order: the left child, the parent, the right child + * first the left child, then the parent, then the right child * + * @return returns the elements of the tree */ - fun traverseInOrder(): List { - fun traverseInOrderRecursive(node: Node?, nodes: MutableList) { + fun traverseInOrder() : List { + fun traverseInOrderRec(node: Node?, nodes: MutableList) { if (node != null) { - traverseInOrderRecursive(node.leftNode(), nodes) + traverseInOrderRec(node.leftNode(), nodes) nodes.add(node.value()) - traverseInOrderRecursive(node.rightNode(), nodes) + traverseInOrderRec(node.rightNode(), nodes) } } - val nodes = mutableListOf() - traverseInOrderRecursive(root, nodes) - return nodes + return mutableListOf().apply { + traverseInOrderRec(root, this) + } } /** + * traversal of the binary tree in depth * - * Traversal of the binary tree in depth - * - * order: the parent, the left child, the right child + * parent first, then left and right children * + * @return returns the elements of the tree */ - fun traversePreOrder(): List { - fun traversePreOrderRecursive(node: Node?, nodes: MutableList) { + fun traversePreOrder() : List { + fun traversePreOrderRec(node: Node?, nodes: MutableList) { if (node != null) { nodes.add(node.value()) - traversePreOrderRecursive(node.leftNode(), nodes) - traversePreOrderRecursive(node.rightNode(), nodes) + traversePreOrderRec(node.leftNode(), nodes) + traversePreOrderRec(node.rightNode(), nodes) } } - val nodes = mutableListOf() - traversePreOrderRecursive(root, nodes) - return nodes + return mutableListOf().apply { + traversePreOrderRec(root, this) + } } /** + * traversal of the binary tree in depth * - * Traversal of the binary tree in depth - * - * order: the left child, the right child, the parent + * first the left and right children, then the parent * + * @return returns the elements of the tree */ - fun traversePostOrder(): List { - fun traversePostOrderRec(node: Node?, nodes: MutableList) { + fun traversePostOrder() : List { + fun traversePostOrderRec(node: Node?, nodes: MutableList) { if (node != null) { traversePostOrderRec(node.leftNode(), nodes) traversePostOrderRec(node.rightNode(), nodes) @@ -182,66 +184,87 @@ class BinaryTree> { } } - val nodes = mutableListOf() - traversePostOrderRec(root, nodes) - return nodes + return mutableListOf().apply { + traversePostOrderRec(root, this) + } } /** + * traversal of the binary tree in breadth * - * Traversal of the binary tree in breadth uses an additional data structure - a queue into which new tree - * + * uses an additional data structure - a queue into which new tree * nodes are added until the last node is added * + * @return returns the elements of the tree */ - fun traverseLevelOrder(): List { - val current = root ?: return emptyList() + fun traverseLevelOrder() : List { + val root = this.root ?: return listOf() - val queue = LinkedList>() - queue.add(current) + val queue = java.util.LinkedList() + queue.add(root) - val nodeValues = mutableListOf() + val items = mutableListOf() while (queue.isNotEmpty()) { - val node = queue.removeFirst() - - nodeValues.add(node.value()) - - val leftNode = node.leftNode() - if (leftNode != null) { - queue.add(leftNode) - } + val node = queue.remove() + items.add(node.value()) - val rightNode = node.rightNode() - if (rightNode != null) { - queue.add(rightNode) - } + node.leftNode()?.let(queue::add) + node.rightNode()?.let(queue::add) } - return nodeValues + return items } - class Node( - private var value: T, - private var left: Node? = null, - private var right: Node? = null - ) { +} - fun value() = value - fun changeValue(newValue: T) { - value = newValue - } +/** + * represents a tree node + * + * @constructor + * @property value - node value + * @property left - left child node + * @property right - right child node + * + */ +class Node( + private var value: Int, + private var left: Node? = null, + private var right: Node? = null +) { + /** + * returns the value of the node + */ + fun value() = value - fun leftNode() = left - fun changeLeft(node: Node?) { - left = node - } + /** + * changes the value of a node + */ + fun changeValue(value: Int) { + this.value = value + } - fun rightNode() = right - fun changeRight(node: Node?) { - right = node - } + /** + * changes the left child node + */ + fun changeLeft(left: Node?) { + this.left = left + } + /** + * changes the right child node + */ + fun changeRight(right: Node?) { + this.right = right } + /** + * returns the left child node + */ + fun leftNode() = left + + /** + * returns the right child node + */ + fun rightNode() = right } \ No newline at end of file diff --git a/src/main/kotlin/structures/CircularLinkedList.kt b/src/main/kotlin/structures/CircularLinkedList.kt index e628e05d..8b82c8f0 100644 --- a/src/main/kotlin/structures/CircularLinkedList.kt +++ b/src/main/kotlin/structures/CircularLinkedList.kt @@ -1,263 +1,219 @@ package structures /** + * data structure: singly linked list with circular reference (last refers to first) * - * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node. + * description: each element stores a link to the next element, the last one refers to the first * - * In the single LinkedList with circular reference each node contains a link to the next element, - * the last one refers to the first + * time to insert an element at the beginning and end of the list: O(1) + * insertion time in the middle by index: O(n) + * delete: O(n) * */ -class CircularLinkedList { - - private var head: Node? = null - private var tail: Node? = null - - private var size: Int = 0 - - val isEmpty: Boolean - get() = head == null - +class CircularLinkedList( /** - * The simple method to test functionality of the LinkedList with circular reference + * stores a reference to the first element of the list * - * Complexity: O(n * cycleNumber) + * if the list is empty, then the reference is null */ - fun cyclingList(cycleNumber: Int = 1): List { - val nodeList = mutableListOf() - var currentCycle = 0 - - if (isEmpty) return nodeList - - while (currentCycle < cycleNumber) { - - var node = head - while (node != null) { - val nodeValue = node.value() - if (nodeValue != null) { - nodeList.add(nodeValue) - } - - if (node === tail) { - currentCycle++ - break - } - - node = node.next() - } - - } - - return nodeList - } - + private var first: Node? = null, /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * stores a reference to the last element of the list + * + * if the list is empty, then the reference is null */ - fun add(index: Int, value: T) : Boolean { - if (head == null) return false + private var last: Node? = null, +) { - var i = 0 - var node = head - var prevNode = head - while (prevNode != null && node != null) { - if (i == index) { - val newNode = Node(value) - newNode.changeNext(node) - prevNode.changeNext(newNode) - size++ - return true - } - i++ + /** + * stores the number of elements in the list + * + */ + private var count: Int = 0 - if (node === tail) { - break - } + /** + * singly linked list node + * + * @constructor + * @property value - node value + * @property next - link to the next element (assuming the element is not the last one) + * + */ + class Node( + private val value: T, + private var next: Node? = null + ) { - prevNode = node - node = node.next() + fun changeNext(next: Node? = null) { + this.next = next } - return false + fun next() = next + fun value() = value } - fun add(value: T) = addLast(value) + /** + * + * @return returns the number of elements in the list + */ + fun size() = count /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * + * @return returns true if the last element refers to the first */ - fun addFirst(value: T) { - val node = Node(value) - if (head == null) { - head = node - tail = node - } else { - node.changeNext(head) - head = node - } - tail?.changeNext(head) - size++ - } + fun isCircular() = last?.next()?.value() == first?.value() /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * a simple function that converts a list into a normal Kotlin list for visual representation + * + * @return returns Kotlin a list of elements */ - fun addLast(value: T) { - val node = Node(value) - if (head == null) { - head = node - tail = node - } else { - tail?.changeNext(node) - tail = node + fun toList() : List { + if (first == null) return listOf() + + val list = mutableListOf() + var node = first + for (i in 0 until count) { + if (node != null) { + list.add(node.value()) + } + node = node?.next() } - tail?.changeNext(head) - size++ + + return list } /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * checks if an element is in the list + * + * @param value - element value + * + * @return returns true if the value exists in the list */ fun contains(value: T) : Boolean { - if (head == null) return false + if (first == null) return false - var node = head - while (node != null) { - if (node.value() == value) { + var node = first + for (i in 0 until count) { + if (node?.value() == value) { return true } - - if (node === tail) { - break - } - - node = node.next() + node = node?.next() } return false } - // Complexity: O(n) - fun clear() { - var node = head - while (node != null) { - val currentNode = node - - node = node.next() - - currentNode.changeNext(null) - currentNode.changeValue(null) - - if (currentNode === tail) { - break - } - } - - head = null - tail = null - size = 0 - } + /** + * checking if the list is empty + * + * @return returns true if the list is empty + */ + fun isEmpty() = first == null /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * removes an element from the list + * + * @param value - element value + * + * @return returns true if the element was successfully removed */ fun remove(value: T) : Boolean { - if (head == null) return false - - var previous: Node? = null - var node = head - - while (node != null) { - if (node.value() == value) { - var nextNode = node.next() - if (nextNode === head) { - nextNode = null - } - previous?.changeNext(nextNode) + if (first == null) { + return false + } - if (head === node) { - head = nextNode - } + var prev = first + var node = first - if (tail === node) { - tail = previous + for (i in 0 until count) { + if (node?.value() == value) { + if (prev?.value() == node?.value()) { + this.first = null + this.last = null + } else { + prev?.changeNext(node?.next()) } - - node.changeNext(null) - node.changeValue(null) - - tail?.changeNext(head) - - size-- - + this.last?.changeNext(this.first) + count-- return true } - - if (node === tail) { - break - } - - previous = node - node = node.next() + prev = node + node = node?.next() } - return false } - override fun toString(): String { - val builder = StringBuilder() - builder.append("size: $size\n") - builder.append("elements: ") + /** + * add element by index + * + * @param index - the index where the new element should be added + * @param value - the value of the new element + * + * @return returns true if the element was successfully added at the specified index + */ + fun add(index: Int, value: T) : Boolean { - var node = head - while (node != null) { - builder.append(node.value()) + if (first == null) return false - // it's necessary to see the correct node connections - if (node.next() != null) { - builder.append(" - ") - } + var node = first - if (node === tail) { - break + for (i in 0 until count - 1) { + if (i == index) { + val newNode = Node(value) + node?.changeNext(newNode) + this.last?.changeNext(this.first) + count++ + return true } - - node = node.next() + node = node?.next() } - return builder.toString() + return false } - class Node( - private var value: T? = null, - private var next: Node? = null - ) { + /** + * similar addLast method + * + */ + fun add(value: T) = addLast(value) - fun next() = next - fun changeNext(node: Node? = null) { - next = node + /** + * adds an element to the beginning of the list + * + * @param value - element value + */ + fun addFirst(value: T) { + val node = Node(value) + if (first == null) { + this.first = node + this.last = node + } else { + node.changeNext(first) + this.first = node } + this.last?.changeNext(this.first) + count++ + } - fun value() = value - fun changeValue(newValue: T?) { - value = newValue + /** + * adds an element to the end of the list + * + * @param value - element value + */ + fun addLast(value: T) { + val newNode = Node(value) + if (first == null) { + this.first = newNode + this.last = newNode + } else { + this.last?.changeNext(newNode) + this.last = newNode } + this.last?.changeNext(this.first) + count++ } } \ No newline at end of file diff --git a/src/main/kotlin/structures/DoubleLinkedList.kt b/src/main/kotlin/structures/DoubleLinkedList.kt index 792fc7b9..b329c057 100644 --- a/src/main/kotlin/structures/DoubleLinkedList.kt +++ b/src/main/kotlin/structures/DoubleLinkedList.kt @@ -1,136 +1,102 @@ package structures /** + * data structure: doubly linked list * - * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node. - * - * In the double LinkedList each node contains a link to the previous and next elements + * description: in a doubly linked list, each element stores a link to the previous and next elements * + * time to insert an element at the beginning and end of the list: O(1) + * insertion time in the middle by index: O(n) + * delete: O(n) */ -class DoubleLinkedList { - - private var head: Node? = null - private var tail: Node? = null +class DoubleLinkedList( + /** + * stores a reference to the first element of the list + * + * if the list is empty, then the reference is null + */ + private var first: Node? = null, + /** + * stores a reference to the last element of the list + * + * if the list is empty, then the reference is null + */ + private var last: Node? = null +) { - private var size: Int = 0 + /** + * stores the number of elements in the list + * + */ + private var count: Int = 0 - val isEmpty: Boolean - get() = head == null + /** + * doubly linked list node + * + * @constructor + * @property value - node value + * @property prev - link to the previous element (assuming the element is not the first one) + * @property next - link to the next element (assuming the element is not the last one) + * + */ + class Node( + private val value: T, + private var prev: Node? = null, + private var next: Node? = null + ) { - // Complexity: O(n) - val list: List - get() { - val nodes = mutableListOf() - var node = head - while (node != null) { - val nodeValue = node.value() - if (nodeValue != null) { - nodes.add(nodeValue) - } - node = node.next() - } - return nodes + fun changeNext(next: Node? = null) { + this.next = next } - // Complexity: O(n) - val reversedList: List - get() { - val nodes = mutableListOf() - var node = tail - while (node != null) { - val nodeValue = node.value() - if (nodeValue != null) { - nodes.add(nodeValue) - } - node = node.previous() - } - return nodes + fun changePrev(prev: Node? = null) { + this.prev = prev } - /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) - */ - fun add(index: Int, value: T) : Boolean { - if (head == null) return false - - var i = 0 - var node = head - var prevNode = head - while (prevNode != null && node != null) { - if (i == index) { - val newNode = Node(value) - newNode.changeNext(node) - newNode.changePrevious(prevNode) - prevNode.changeNext(newNode) - size++ - return true - } - i++ - prevNode = node - node = node.next() - } + fun next() = next + fun prev() = prev + fun value() = value - return false + fun isOne() = prev == null && next == null + fun isFirst() = prev == null + fun isLast() = next == null } - fun add(value: T) = addLast(value) - /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * + * @return returns the number of elements in the list */ - fun addFirst(value: T) { - val headNode = head - head = if (headNode == null) { - Node(value) - } else { - val newNode = Node(value = value, next = headNode) - headNode.changePrevious(newNode) - newNode - } - if (tail == null) { - tail = head - } - size++ - } + fun size() = count /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * a simple function that converts a list into a normal Kotlin list for visual representation + * + * @return returns Kotlin a list of elements */ - fun addLast(value: T) { - val tailNode = tail - tail = if (tailNode == null) { - Node(value) - } else { - val newNode = Node(value = value, previous = tailNode) - tailNode.changeNext(newNode) - newNode - } - if (head == null) { - head = tail + fun toList() : List { + if (first == null) return listOf() + + val list = mutableListOf() + var node = first + while (node != null) { + list.add(node.value()) + node = node.next() } - size++ + return list } /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * checks if an element is in the list + * + * @param value - element value + * + * @return returns true if the value exists in the list */ fun contains(value: T) : Boolean { - if (head == null) return false + if (first == null) return false - var node = head + var node = first while (node != null) { if (node.value() == value) { return true @@ -141,110 +107,129 @@ class DoubleLinkedList { } /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * checking if the list is empty + * + * @return returns true if the list is empty + */ + fun isEmpty() = first == null + + /** + * removes an element from the list + * + * @param value - element value + * + * @return returns true if the element was successfully removed */ fun remove(value: T) : Boolean { - if (head == null) return false + if (first == null) return false - var previous: Node? = null - var node = head + var node = first while (node != null) { if (node.value() == value) { - val nextNode = node.next() - previous?.changeNext(nextNode) - nextNode?.changePrevious(previous) - - if (node === head) { - head = nextNode + if (node.isOne()) { + first = null + last = null + } else if (node.isFirst()) { + val next = node.next() + next?.changePrev(null) + first = next + } else if (node.isLast()) { + val prev = node.prev() + prev?.changeNext(null) + last = prev + } else { + node.prev()?.changeNext(node.next()) + node.next()?.changePrev(node.prev()) } - - if (node === tail) { - tail = previous - } - - node.changePrevious(null) - node.changeNext(null) - node.changeValue(null) - - size-- + count-- return true } - previous = node node = node.next() } - return false } - // Complexity: O(n) - fun clear() { - var node = head - while (node != null) { - val currentNode = node - - node = node.next() - - currentNode.changeNext(null) - currentNode.changePrevious(null) - currentNode.changeValue(null) - } - - head = null - tail = null - size = 0 - } + /** + * add element by index + * + * @param index - the index where the new element should be added + * @param value - the value of the new element + * + * @return returns true if the element was successfully added at the specified index + */ + fun add(index: Int, value: T) : Boolean { - override fun toString(): String { - val builder = StringBuilder() - builder.append("size: $size\n") - builder.append("elements: ") + if (first == null) return false - var node = head + var i = 0 + var node = first while (node != null) { + if (i == index) { + val newNode = Node(value) - // it's necessary to see the correct node connections - if (node.previous() != null) { - builder.append("- ") - } + newNode.changePrev(node.prev()) + newNode.changeNext(node) - builder.append(node.value()) + node.prev()?.changeNext(newNode) + node.changePrev(newNode) - // it's necessary to see the correct node connections - if (node.next() != null) { - builder.append(" -") + count++ + return true } - + i++ node = node.next() } - return builder.toString() + return false } - class Node( - private var value: T? = null, - private var previous: Node? = null, - private var next: Node? = null - ) { + /** + * similar addLast method + * + */ + fun add(value: T) = addLast(value) - fun next() = next - fun changeNext(node: Node? = null) { - next = node + /** + * adds an element to the beginning of the list + * + * @param value - element value + */ + fun addFirst(value: T) { + val firstNode = first + first = if (firstNode == null) { + Node(value) + } else { + val newNode = Node(value) + newNode.changeNext(firstNode) + firstNode.changePrev(newNode) + newNode } - - fun previous() = previous - fun changePrevious(node: Node? = null) { - previous = node + if (last == null) { + last = first } + count++ + } - fun value() = value - fun changeValue(newValue: T?) { - value = newValue + /** + * adds an element to the end of the list + * + * @param value - element value + */ + fun addLast(value: T) { + val lastNode = last + last = if (lastNode == null) { + Node(value) + } else { + val newNode = Node(value) + lastNode.changeNext(newNode) + newNode.changePrev(lastNode) + newNode } - + if (first == null) { + first = last + } + count++ } } \ No newline at end of file diff --git a/src/main/kotlin/structures/DynamicArray.kt b/src/main/kotlin/structures/DynamicArray.kt deleted file mode 100644 index 8cbf12a6..00000000 --- a/src/main/kotlin/structures/DynamicArray.kt +++ /dev/null @@ -1,140 +0,0 @@ -package structures - -import java.lang.IllegalStateException - -/** - * - * Dynamic array or array list is a random access, variable-size list data structure - * - * that allows elements to be added or removed, in Java this is java.util.ArrayList - * - * P.S. Kotlin lists use under the hood java.util.ArrayList on the JVM - * - * Example: - * - * 1) val numbers = listOf(1, 2, 3) // java.util.ArrayList - * - * 2) val symbols = mutableListOf('a', 'b', 'c') // also java.util.ArrayList - * - */ - -class DynamicArray(private var capacity: Int = 10) { - - private var data = arrayOfNulls(capacity) - private var size = 0 - - /** - * Complexity: - * worst time - O(n) because increaseSize() is called - * best time - O(1) - * average time - O(1) - */ - fun add(value: T) { - if (size <= data.size - 1) { - data[size] = value - } else { - increaseSize() - data[size] = value - } - size += 1 - } - - /** - * Complexity: - * worst time: O(n) - * best time: O(n) - * average time: O(n) - */ - fun remove(value: T) : Boolean { - var foundedIndex = -1 - - for (i in data.indices) { - if (data[i] == value) { - foundedIndex = i - break - } - } - - if (foundedIndex == -1) return false - - for (i in foundedIndex until data.size - 1) { - data[i] = data[i + 1] - } - - size -= 1 - - return true - } - - /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) - */ - fun contains(value: T): Boolean { - for (i in data.indices) { - if (data[i] == value) { - return true - } - } - - return false - } - - /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) - */ - fun set(index: Int, value: T): T? { - if (index !in 0 until size) throw IllegalStateException("The index $index is out of bounds!") - - val oldValue = data[index] - - data[index] = value - - return oldValue as? T - } - - /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) - */ - fun get(index: Int) : T { - if (index !in data.indices) throw IllegalStateException("The index $index is out of bounds!") - - return data[index] as T - } - - override fun toString(): String { - val builder = StringBuilder() - builder.append("capacity: $capacity\n") - builder.append("size: $size\n") - - builder.append("elements: ") - for (i in 0 until size - 1) { - builder.append("${data[i]}, ") - } - builder.append(data[size - 1]) - - return builder.toString() - } - - private fun increaseSize() { - capacity = (capacity * INCREASE_SIZE_COEFFICIENT).toInt() - val newArray = arrayOfNulls(capacity) - for (i in data.indices) { - newArray[i] = data[i] - } - data = newArray - } - - companion object { - private const val INCREASE_SIZE_COEFFICIENT = 1.5f - } - -} \ No newline at end of file diff --git a/src/main/kotlin/structures/Graph.kt b/src/main/kotlin/structures/Graph.kt index 0b41618a..81bf0867 100644 --- a/src/main/kotlin/structures/Graph.kt +++ b/src/main/kotlin/structures/Graph.kt @@ -1,30 +1,30 @@ package structures import java.util.LinkedList -import kotlin.collections.LinkedHashSet /** + * data structure: graph * - * Graph is a non-linear data structure consisting of vertices and edges. - * - * The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph. - * - * More formally a Graph is composed of a set of vertices V and a set of edges E. The graph is denoted by G(E, V). - * - * Undirected graph is a type of graph where the edges have no specified direction assigned to the them. + * description: a graph is made up of vertices connected by edges * */ class Graph { - private val data = linkedMapOf, MutableList>>() + private val data = mutableMapOf, MutableList>>() - // Complexity: O(1) - fun addVertex(value: T) { - data.putIfAbsent(Vertex(value), mutableListOf()) - } + /** + * adds a new vertex + * + * @param value - the value of the new vertex + */ + fun addVertex(value: T) = data.putIfAbsent(Vertex(value), mutableListOf()) - // Complexity: O(n) + /** + * removes a vertex from a graph + * + * @param value - vertex value + */ fun removeVertex(value: T) { val removingVertex = Vertex(value) data.values.forEach { list -> @@ -33,7 +33,12 @@ class Graph { data.remove(removingVertex) } - // Complexity: O(1) + /** + * adds an edge between two vertices + * + * @param value1 - first vertex value + * @param value2 - second vertex value + */ fun addEdge(value1: T, value2: T) { val vertex1 = Vertex(value1) val vertex2 = Vertex(value2) @@ -41,7 +46,12 @@ class Graph { data[vertex2]?.add(vertex1) } - // Complexity: O(1) + /** + * removes an edge between two vertices + * + * @param value1 - first vertex value + * @param value2 - second vertex value + */ fun removeEdge(value1: T, value2: T) { val vertex1 = Vertex(value1) val vertex2 = Vertex(value2) @@ -49,58 +59,55 @@ class Graph { data[vertex2]?.remove(vertex1) } - // returns the associated vertices with the given vertex value - fun connectedVertexes(value: T) = data[Vertex(value)]?.map { it.value } ?: emptyList() - /** + * returns the associated vertices with the given vertex * - * Traversal of the graph in depth, - * - * returns all vertices of the graph - * + * @param value - vertex value */ - fun depthFirstTraversal() : List { - val firstVertex = data.keys.firstOrNull() ?: return emptyList() + fun connectedVertexes(value: T) = data[Vertex(value)] ?: listOf() - val visited = LinkedHashSet() + /** + * traversal of the graph in depth + * + * @return returns all vertices of the graph + */ + fun depthFirstTraversal() : List> { + val visited = LinkedHashSet>() val queue = LinkedList>() - queue.push(firstVertex) + queue.push(data.keys.first()) while (queue.isNotEmpty()) { - val vertex = queue.pollFirst() - if (!visited.contains(vertex.value)) { - visited.add(vertex.value) - queue.addAll(data[vertex] ?: emptyList()) + val vertex = queue.pop() + if (!visited.contains(vertex)) { + visited.add(vertex) + queue.addAll(data[vertex] ?: listOf()) } } return visited.toList() } /** + * traversal of the graph in breadth * - * Traversal of the graph in breadth, - * - * returns all vertices of the graph - * + * @return returns all vertices of the graph */ - fun breadthFirstTraversal() : List { - val firstVertex = data.keys.firstOrNull() ?: return emptyList() - - val visited = LinkedHashSet() + fun breadthFirstTraversal() : List> { + val visited = LinkedHashSet>() val queue = LinkedList>() + val firstVertex = data.keys.firstOrNull() ?: return listOf() queue.add(firstVertex) - visited.add(firstVertex.value) + visited.add(firstVertex) while (queue.isNotEmpty()) { - val vertex = queue.pollFirst() - data[vertex]?.forEach { connectedVertex -> - if (!visited.contains(connectedVertex.value)) { - visited.add(connectedVertex.value) - queue.add(connectedVertex) + val vertex = queue.poll() + data[vertex]?.forEach { v -> + if (!visited.contains(v)) { + visited.add(v) + queue.add(v) } } } return visited.toList() } - private data class Vertex(val value: T) - } + +data class Vertex(val value: T) \ No newline at end of file diff --git a/src/main/kotlin/structures/GraphWithWeights.kt b/src/main/kotlin/structures/GraphWithWeights.kt deleted file mode 100644 index d51df238..00000000 --- a/src/main/kotlin/structures/GraphWithWeights.kt +++ /dev/null @@ -1,102 +0,0 @@ -package structures - - -/** - * - * Graph is a non-linear data structure consisting of vertices and edges. - * - * The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph. - * - * More formally a Graph is composed of a set of vertices V and a set of edges E. The graph is denoted by G(E, V). - * - * Directed graph with weights is a type of graph where the edges have specified direction and weights assigned to the them. - * - */ - -class GraphWithWeights { - - private val data = linkedMapOf, MutableList>>() - - // Complexity: O(1) - fun addVertex(value: T) { - data.putIfAbsent(Vertex(value), mutableListOf()) - } - - // Complexity: O(n) - fun removeVertex(value: T) { - val removingVertex = Vertex(value) - data.values.forEach { connections -> - connections.removeIf { it.vertex == removingVertex } - } - data.remove(removingVertex) - } - - // Complexity: O(1) - fun addEdge(value1: T, value2: T, cost: Int) { - val vertex1 = Vertex(value1) - val vertex2 = Vertex(value2) - data[vertex1]?.add(VertexConnection(vertex2, cost)) - } - - // Complexity: O(n) - fun removeEdge(value1: T, value2: T) { - val vertex1 = Vertex(value1) - val vertex2 = Vertex(value2) - data[vertex1]?.removeIf { it.vertex == vertex2 } - } - - // returns the associated vertices and their weights with the given vertex value - fun connectedVertexesWithWeights(value: T) = data[Vertex(value)]?.map { it.toString() } ?: emptyList() - - /** - * - * Dijkstra's algorithm, - * - * returns pairs of a vertex and the minimum weight needed to get to that vertex, - * - * the starting vertex is the first added - * - */ - fun dijkstraAlgorithm(): Map { - if (data.isEmpty()) return emptyMap() - - val unvisitedVertexes = linkedMapOf, Int>() - data.keys.forEach { vertex -> - unvisitedVertexes[vertex] = Int.MAX_VALUE - } - - val visitedVertexes = linkedMapOf() - var minimumCost = 0 - - var currentVertex = unvisitedVertexes.keys.first() - while(unvisitedVertexes.isNotEmpty()) { - val neighbourVertexConnections = data[currentVertex] ?: emptyList() - for (neighbourVertexConnection in neighbourVertexConnections) { - val neighbourVertex = neighbourVertexConnection.vertex - if (!unvisitedVertexes.contains(neighbourVertex)) continue - - val newCost = minimumCost + neighbourVertexConnection.cost - val neighbourVertexCost = unvisitedVertexes[neighbourVertex] ?: Int.MAX_VALUE - if (neighbourVertexCost > newCost) { - unvisitedVertexes[neighbourVertex] = newCost - } - } - visitedVertexes[currentVertex.value] = minimumCost - unvisitedVertexes.remove(currentVertex) - val nextUnvisitedEntry = unvisitedVertexes.entries - .filter { it.value != Int.MAX_VALUE } - .minByOrNull { it.value } ?: return visitedVertexes - currentVertex = nextUnvisitedEntry.key - minimumCost = nextUnvisitedEntry.value - } - return visitedVertexes - } - - private data class Vertex(val value: T) - - // helper class for defining graph weights - private data class VertexConnection(val vertex: Vertex, val cost: Int) { - override fun toString(): String = "vertex -> ${vertex.value}, cost -> $cost" - } - -} \ No newline at end of file diff --git a/src/main/kotlin/structures/Matrix.kt b/src/main/kotlin/structures/Matrix.kt deleted file mode 100644 index 56a18153..00000000 --- a/src/main/kotlin/structures/Matrix.kt +++ /dev/null @@ -1,131 +0,0 @@ -package structures - -import java.lang.IllegalArgumentException - -fun matrix(apply: Matrix.() -> Unit): Matrix { - val matrix = Matrix() - matrix.apply() - return matrix -} - -/** - * Matrix is a rectangular table filled with numbers. - * - * For example: - * 1, 2, 3 - * 4, 5, 6 - * 7, 8, 9 - */ -class Matrix() { - - private val elements = mutableListOf() - private var columnCount = 0 - private var rowCount = 0 - - private constructor(elements: List, columnCount: Int, rowCount: Int) : this() { - this.elements.addAll(elements) - this.columnCount = columnCount - this.rowCount = rowCount - } - - fun row(vararg rowElements: Int) { - if (rowElements.isEmpty()) { - return - } - - if (rowCount == 0) { - columnCount = rowElements.size - } - - if (columnCount != rowElements.size) { - throw IllegalArgumentException("The number of elements in each row must be the same") - } - - elements.addAll(rowElements.toTypedArray()) - - rowCount++ - } - - operator fun plus(value: Int): Matrix { - return Matrix(elements.map { it + value }, columnCount, rowCount) - } - - operator fun plus(value: Matrix): Matrix { - if (rowCount != value.rowCount) throw IllegalArgumentException("The number of rows doesn't match") - if (columnCount != value.columnCount) throw IllegalArgumentException("The number of columns doesn't match") - - return Matrix(elements.zip(value.elements) { element1, element2 -> element1 + element2 }, columnCount, rowCount) - } - - operator fun minus(value: Int): Matrix { - return Matrix(elements.map { it - value }, columnCount, rowCount) - } - - operator fun minus(value: Matrix): Matrix { - if (rowCount != value.rowCount) throw IllegalArgumentException("The number of rows doesn't match") - if (columnCount != value.columnCount) throw IllegalArgumentException("The number of columns doesn't match") - - return Matrix(elements.zip(value.elements) { element1, element2 -> element1 - element2 }, columnCount, rowCount) - } - - operator fun times(value: Int): Matrix { - return Matrix(elements.map { it * value }, columnCount, rowCount) - } - - operator fun times(matrix: Matrix): Matrix { - val columnCountMatrix1 = columnCount - val rowCountMatrix1 = rowCount - val columnCountMatrix2 = matrix.columnCount - val rowCountMatrix2 = matrix.rowCount - - if (columnCountMatrix1 != rowCountMatrix2) throw IllegalArgumentException("The number of columns of the first matrix doesn't match the number of rows of the second matrix") - - val newElements = mutableListOf() - for (rowIndexMatrix1 in 0 until rowCountMatrix1) { - for (columnIndexMatrix2 in 0 until columnCountMatrix2) { - var sum = 0 - for (sameSizeIndex in 0 until columnCountMatrix1) { - sum += elements[rowIndexMatrix1 * columnCountMatrix1 + sameSizeIndex] * matrix.elements[sameSizeIndex * columnCountMatrix2 + columnIndexMatrix2] - } - newElements.add(sum) - } - } - - return Matrix(newElements, columnCountMatrix2, rowCountMatrix1) - } - - operator fun div(value: Int): Matrix { - return Matrix(elements.map { it / value }, columnCount, rowCount) - } - - override fun equals(other: Any?): Boolean { - if (other == null) return false - if (other !is Matrix) return false - if (this === other) return true - - return columnCount == other.columnCount && rowCount == other.rowCount && elements == other.elements - } - - override fun hashCode(): Int { - var result = elements.hashCode() - result = 31 * result + columnCount - result = 31 * result + rowCount - return result - } - - override fun toString(): String { - val stringBuilder = StringBuilder("\n") - - elements.forEachIndexed { index, value -> - val floating = if ((index + 1) % columnCount == 0) "" else ", " - stringBuilder.append("$value$floating") - - if ((index + 1) % columnCount == 0) { - stringBuilder.append("\n") - } - } - - return stringBuilder.toString() - } - -} \ No newline at end of file diff --git a/src/main/kotlin/structures/MaxHeap.kt b/src/main/kotlin/structures/MaxHeap.kt index e8fd626f..6d08b190 100644 --- a/src/main/kotlin/structures/MaxHeap.kt +++ b/src/main/kotlin/structures/MaxHeap.kt @@ -1,117 +1,78 @@ package structures -import java.lang.IllegalArgumentException - /** + * data structure: max-heap + * + * | operation | time + * ---------------------------------------------- + * | getting the maximum element | O(1) + * | -------------------------------------------- + * | inserting a new element | O(logn) + * | -------------------------------------------- + * | deleting an element | O(logn) * - * Max-heap is a binary tree in which each parent is greater than its children + * description: max-heap is a binary tree in which each parent is greater than its children * */ class MaxHeap(private val maxSize: Int) { - - private val data = IntArray(maxSize + 1) { Int.MIN_VALUE } + private val heap = Array(maxSize + 1) { 0 }.apply { + this[0] = Int.MAX_VALUE + } private val root = 1 private var size = 0 - val isEmpty: Boolean - get() = size == 0 - - private val Int.parent - get() = this / 2 + private fun parent(pos: Int) = pos / 2 + private fun leftChild(pos: Int) = 2 * pos + private fun rightChild(pos: Int) = 2 * pos + 1 - private val Int.leftChild - get() = this * 2 - - private val Int.rightChild - get() = this * 2 + 1 - - init { - if (maxSize <= 0) throw IllegalArgumentException("The heap must have maxSize larger than zero") - - data[0] = Int.MAX_VALUE + private fun swap(old: Int, new: Int) { + heap[old] = heap[new].apply { heap[new] = heap[old] } } - // Complexity: O(logn) - fun add(element: Int) { - if (size >= maxSize) throw IllegalStateException("The heap is full!") + fun isEmpty() = size == 0 - data[++size] = Int.MIN_VALUE - set(size, element) - } - - // Complexity: O(logn) - fun set(index: Int, newValue: Int) { - if (index < root || index > maxSize) throw IllegalArgumentException("The heap doesn't have the such index: $index!") - if (newValue < data[index]) throw IllegalArgumentException("The new value $newValue is less than the previous: ${data[index]}") - - data[index] = newValue - - var current = index - while (current > root && data[current.parent] < data[current]) { - swap(current, current.parent) - current = current.parent + fun add(element: Int) { + fun heapifyUp(pos: Int) { + var current = pos + val temp = heap[pos] + while (current > 0 && temp > heap[parent(current)]) { + heap[current] = heap[parent(current)] + current = parent(current) + } + heap[current] = temp } - } - - // Complexity: O(1) - fun peekMax() = data[root] - // Complexity: O(logn) - fun popMax(): Int { - if (size < 1) throw IllegalStateException("The heap is empty!") - - val max = data[root] - data[root] = data[size--] - heapify(root) - return max + heap[++size] = element + heapifyUp(size) } - private tailrec fun heapify(pos: Int) { - val leftChild = pos.leftChild - val rightChild = pos.rightChild - var largest = pos - - if (leftChild <= size && data[leftChild] > data[largest]) { - largest = leftChild - } + fun peekMax() = heap[root] - if (rightChild <= size && data[rightChild] > data[largest]) { - largest = rightChild + fun popMax(): Int { + fun downHeapify(pos: Int) { + if (pos >= size / 2 && pos <= size) return + if (pos == maxSize - 1) return + + if (heap[pos] < heap[leftChild(pos)] || + heap[pos] < heap[rightChild(pos)] + ) { + if (heap[leftChild(pos)] > heap[rightChild(pos)]) { + swap(pos, leftChild(pos)) + downHeapify(leftChild(pos)) + } else { + swap(pos, rightChild(pos)) + downHeapify(rightChild(pos)) + } + } } - if (largest != pos) { - swap(pos, largest) - heapify(largest) - } - } - - private fun swap(index1: Int, index2: Int) { - val tmp = data[index1] - data[index1] = data[index2] - data[index2] = tmp + val max = heap[root] + heap[root] = heap[size--] + downHeapify(root) + return max } - companion object { - fun create(intArray: IntArray): MaxHeap { - val arraySize = intArray.size - val heap = MaxHeap(arraySize) - heap.size = intArray.size - - var index = 0 - while (index < arraySize) { - heap.data[index + 1] = intArray[index] - index++ - } - - var pos = arraySize / 2 - while (pos >= 0) { - heap.heapify(pos) - pos-- - } - return heap - } - } } \ No newline at end of file diff --git a/src/main/kotlin/structures/MinHeap.kt b/src/main/kotlin/structures/MinHeap.kt index 9fac6827..46cbed23 100644 --- a/src/main/kotlin/structures/MinHeap.kt +++ b/src/main/kotlin/structures/MinHeap.kt @@ -1,117 +1,86 @@ package structures -import java.lang.IllegalArgumentException - /** + * data structure: min-heap + * + * | operation | time + * ---------------------------------------------- + * | getting the minimum element | O(1) + * | -------------------------------------------- + * | inserting a new element | O(logn) + * | -------------------------------------------- + * | deleting an element | O(logn) * - * Min-heap is a binary tree in which each parent is smaller than its children + * description: min-heap is a binary tree in which each parent is smaller than its children * */ -class MinHeap(private val maxSize: Int) { +class MinHeap(maxSize: Int) { - private val data = IntArray(maxSize + 1) { Int.MAX_VALUE } + private val heap = Array(maxSize) { 0 } - private val root = 1 private var size = 0 + private val front = 0 - val isEmpty: Boolean - get() = size == 0 - - private val Int.parent - get() = this / 2 - - private val Int.leftChild - get() = this * 2 - - private val Int.rightChild - get() = this * 2 + 1 + fun add(item: Int) { + heap[size++] = item - init { - if (maxSize <= 0) throw IllegalArgumentException("The heap must have maxSize larger than zero") + var current = size - 1 + var parent = parent(current) - data[0] = Int.MIN_VALUE + while (parent != current && heap[current] < heap[parent]) { + swap(current, parent) + current = parent + parent = parent(current) + } } - // Complexity: O(logn) - fun add(element: Int) { - if (size >= maxSize) throw IllegalStateException("The heap is full!") - - data[++size] = Int.MAX_VALUE - set(size, element) - } + fun minHeapify(pos: Int) { + val left = left(pos) + val right = right(pos) - // Complexity: O(logn) - fun set(index: Int, newValue: Int) { - if (index < root || index > maxSize) throw IllegalArgumentException("The heap doesn't have the such index: $index!") - if (newValue > data[index]) throw IllegalArgumentException("The new value $newValue is more than the previous: ${data[index]}") + var smallest = if (left <= size && heap[left] < heap[pos]) { + left + } else { + pos + } - data[index] = newValue + if (right <= size && heap[right] < heap[smallest]) { + smallest = right + } - var current = index - while (current > root && data[current.parent] > data[current]) { - swap(current, current.parent) - current = current.parent + if (smallest != pos) { + swap(pos, smallest) + minHeapify(smallest) } } - // Complexity: O(1) - fun peekMin() = data[root] + fun popMin() : Int { + if (size == 1) { + return heap[--size] + } - // Complexity: O(logn) - fun popMin(): Int { - if (size < 1) throw IllegalStateException("The heap is empty!") + val min = heap[front] + heap[front] = heap[size - 1] - val max = data[root] - data[root] = data[size--] - heapify(root) - return max - } + size-- - private tailrec fun heapify(pos: Int) { - val leftChild = pos.leftChild - val rightChild = pos.rightChild - var minimum = pos + minHeapify(front) - if (leftChild <= size && data[leftChild] < data[minimum]) { - minimum = leftChild - } - - if (rightChild <= size && data[rightChild] < data[minimum]) { - minimum = rightChild - } - - if (minimum != pos) { - swap(pos, minimum) - heapify(minimum) - } + return min } - private fun swap(index1: Int, index2: Int) { - val tmp = data[index1] - data[index1] = data[index2] - data[index2] = tmp - } + fun peekMin() = heap[front] + + fun isEmpty() = size == 0 - companion object { - fun create(intArray: IntArray): MinHeap { - val arraySize = intArray.size - val heap = MinHeap(arraySize) - heap.size = intArray.size - - var index = 0 - while (index < arraySize) { - heap.data[index + 1] = intArray[index] - index++ - } - - var pos = arraySize / 2 - while (pos >= 0) { - heap.heapify(pos) - pos-- - } - return heap + private fun left(pos: Int) = 2 * pos + 1 + private fun right(pos: Int) = 2 * pos + 2 + private fun parent(pos: Int) = if (pos % 2 == 1) pos / 2 else (pos - 1) / 2 + private fun swap(old: Int, new: Int) { + heap[new] = heap[old].apply { + heap[old] = heap[new] } } diff --git a/src/main/kotlin/structures/MyArrayList.kt b/src/main/kotlin/structures/MyArrayList.kt new file mode 100644 index 00000000..64c3e639 --- /dev/null +++ b/src/main/kotlin/structures/MyArrayList.kt @@ -0,0 +1,125 @@ +package structures + +import java.lang.IllegalStateException + +/** + * data structure: simple java.util.ArrayList implementation + * + * description: wrapper over a regular array, in which indexes are checked and + * when the array overflows, its size increases dynamically + * + * @constructor + * @property capacity initial array size + * + * P.S. Kotlin lists use under the hood java.util.ArrayList + * for example: + * val numbers = listOf(1, 2, 3) // java.util.ArrayList + * val symbols = mutableListOf('a', 'b', 'c') // also java.util.ArrayList + */ + +class MyArrayList(private var capacity: Int = 10) { + private var data = Array(capacity) { 0 } + private var index = 0 + + /** + * add a new element in array + * + * if the array cannot accommodate the new element, then its size is dynamically increased + * + * @param value - element + */ + fun add(value: Int) { + if (index < data.size - 1) { + data[index++] = value + } else { + increaseSize() + data[index++] = value + } + } + + /** + * removes an element from the array and shifts subsequent elements in its place + * + * @param value - element + */ + fun remove(value: Int) : Boolean { + val foundedIndex = data.indexOf(value) + if (foundedIndex == -1) { + return false + } + for (i in foundedIndex until data.size - 1) { + data[i] = data[i + 1] + } + return true + } + + /** + * checks for the existence of an element in an array + * + * @param value - element + * + * @return returns true if the element is present in the array + */ + fun contains(value: Int) = data.contains(value) + + /** + * sets the new element value at the specified index + * + * @param index - element index + * @param value - the new value of the element + * + * @return returns true if the element was successfully modified + */ + fun set(index: Int, value: Int) : Boolean { + if (isBound(index)) { + data[index] = value + return true + } + return false + } + + + /** + * returns the value of the element by index, or throws an exception if the index is invalid + * + * @param index - element index + * + * @return returns the value of an element by index + */ + fun get(index: Int) : Int { + if (isBound(index)) { + return data[index] + } else { + throw IllegalStateException("index is out of bounds!") + } + } + + /** + * + * @return returns the size of the array + */ + fun capacity() = capacity + + /** + * check for correct index + * + * @return returns true if the index is within the range of available indexes + */ + private fun isBound(i: Int) = i in 0 until index + + override fun toString() = data.joinToString(", ") + + /** + * increases the size of an array when there is not enough to add new elements + * + */ + private fun increaseSize() { + capacity *= 2 + val newArray = Array(capacity) { 0 } + for ((index, element) in data.withIndex()) { + newArray[index] = element + } + data = newArray + } + +} \ No newline at end of file diff --git a/src/main/kotlin/structures/Queue.kt b/src/main/kotlin/structures/Queue.kt index a3599495..d932b54d 100644 --- a/src/main/kotlin/structures/Queue.kt +++ b/src/main/kotlin/structures/Queue.kt @@ -1,51 +1,134 @@ package structures -import java.util.LinkedList +import kotlin.collections.ArrayList /** + * data structure: queue * - * Queue is a data structure that follows the FIFO (first in, first out) principle - * - * LIFO implies that the element that is inserted first, comes out first - * - * The main operations: - * - * 1) enqueue - inserts an element at the end of the queue - * 2) dequeue - removes an element from the beginning of the queue - * - * All these operations performed in O(1) time. + * description: the queue is organized on a FIFO basis (first in, first out), all operations are performed in O(1), + * except for the operation of deleting from the middle of the queue, which in the worst case takes O(n) time * */ -class Queue { - private val data = LinkedList() +interface Queue { - val isEmpty: Boolean - get() = data.isEmpty() + /** + * adding to the front of the queue + * + * @param item - added element + */ + fun offer(item: T) - val size: Int - get() = data.size + /** + * returns the element from the front of the queue + * + * if the queue is empty, throws an IllegalStateException + */ + fun element() : T - fun enqueue(item: T) { - data.add(item) - } + /** + * returns the element from the front of the queue + * + * if the queue is empty it will return null + */ + fun peek() : T? - fun dequeue(): T { - if (isEmpty) throw IllegalStateException("The queue is empty") + /** + * removes and returns an element from the front of the queue + * + * if the queue is empty, throws an IllegalStateException + */ + fun remove() : T - // LinkedList under the hood stores a link to the first element - // this operation will be completed in time O(1) - return data.removeFirst() - } + /** + * removes and returns an element from the front of the queue + * + * if the queue is empty it will return null + */ + fun poll() : T? + + /** + * + * @return returns true if the queue is empty + */ + fun isEmpty() : Boolean + + /** + * clears the queue + * + */ + fun clear() + + /** + * removes an element from the middle of the queue + * + * @return returns true if the element was successfully removed + */ + fun remove(item: T) : Boolean + + /** + * implementation using dynamic ArrayList + * + */ + class ArrayListQueue : Queue { + private val data = ArrayList() + + override fun offer(item: T) = data.add(0, item) - fun peek(): T { - if (isEmpty) throw IllegalStateException("The queue is empty") + override fun isEmpty() = data.isEmpty() + override fun clear() = data.clear() - return data.first + override fun element() = if (isEmpty()) thr("queue is empty!") else data.first() + override fun peek() = if (isEmpty()) null else data.first() + + override fun remove() = if (isEmpty()) thr("queue is empty!") else data.removeFirst() + override fun poll() = if (isEmpty()) null else data.removeFirst() + + override fun remove(item: T) : Boolean { + return if (data.contains(item)) { + data.remove(item) + true + } else { + false + } + } + + private fun thr(msg: String) : Nothing { + throw IllegalStateException(msg) + } } - fun clear() { - data.clear() + /** + * implementation using linked list LinkedList + * + */ + class LinkedListQueue : Queue { + private val data = java.util.LinkedList() + + override fun offer(item: T) = data.add(0, item) + + override fun isEmpty() = data.isEmpty() + override fun clear() = data.clear() + + override fun element() : T = if (isEmpty()) thr("queue is empty!") else data.peekFirst() + override fun peek() = if (isEmpty()) null else data.peekFirst() + + override fun remove(): T = if (isEmpty()) thr("queue is empty!") else data.removeFirst() + override fun poll() = if (isEmpty()) null else data.removeFirst() + + override fun remove(item: T) : Boolean { + return if (data.contains(item)) { + data.remove(item) + true + } else { + false + } + } + + private fun thr(msg: String) : Nothing { + throw IllegalStateException(msg) + } } + } \ No newline at end of file diff --git a/src/main/kotlin/structures/SingleLinkedList.kt b/src/main/kotlin/structures/SingleLinkedList.kt index 49c958de..006bcd38 100644 --- a/src/main/kotlin/structures/SingleLinkedList.kt +++ b/src/main/kotlin/structures/SingleLinkedList.kt @@ -1,199 +1,206 @@ package structures /** + * data structure: singly linked list * - * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node. + * description: in a singly linked list, each element stores a link only to the next element * - * In the single LinkedList each node contains a link only to the next element + * time to insert an element at the beginning and end of the list: O(1) + * insertion time in the middle by index: O(n) + * delete: O(n) * */ -class SingleLinkedList() { - - private var head: Node? = null - private var tail: Node? = null - - private var size: Int = 0 +class SingleLinkedList( + /** + * stores a reference to the first element of the list + * + * if the list is empty, then the reference is null + */ + private var first: Node? = null, + /** + * stores a reference to the last element of the list + * + * if the list is empty, then the reference is null + */ + private var last: Node? = null, +) { - val isEmpty: Boolean - get() = head == null + /** + * stores the number of elements in the list + * + */ + private var count: Int = 0 /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * singly linked list node + * + * @constructor + * @property value - node value + * @property next - link to the next element (assuming the element is not the last one) + * */ - fun add(index: Int, value: T) : Boolean { - if (head == null) return false + class Node( + private val value: T, + private var next: Node? = null + ) { - var i = 0 - var node = head - var prevNode = head - while (prevNode != null && node != null) { - if (i == index) { - val newNode = Node(value) - newNode.changeNext(node) - prevNode.changeNext(newNode) - size++ - return true - } - i++ - prevNode = node - node = node.next() + fun changeNext(next: Node? = null) { + this.next = next } - return false + fun next() = next + fun value() = value } - fun add(value: T) = addLast(value) - /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * + * @return returns the number of elements in the list */ - fun addFirst(value: T) { - val node = Node(value) - if (head == null) { - head = node - tail = node - } else { - node.changeNext(head) - head = node - } - size++ - } + fun size() = count /** - * Complexity: - * worst time: O(1) - * best time: O(1) - * average time: O(1) + * a simple function that converts a list into a normal Kotlin list for visual representation + * + * @return returns Kotlin a list of elements */ - fun addLast(value: T) { - val node = Node(value) - if (head == null) { - head = node - tail = node - } else { - tail?.changeNext(node) - tail = node + fun toList() : List { + if (first == null) return listOf() + + val list = mutableListOf() + var node = first + while (node != null) { + list.add(node.value()) + node = node.next() } - size++ + return list } /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * checks if an element is in the list + * + * @param value - element value + * + * @return returns true if the value exists in the list */ fun contains(value: T) : Boolean { - if (head == null) return false + if (first == null) return false - var node = head + var node = first while (node != null) { if (node.value() == value) { return true } node = node.next() } - return false } /** - * Complexity: - * worst time: O(n) - * best time: O(1) - * average time: O(n) + * checking if the list is empty + * + * @return returns true if the list is empty + */ + fun isEmpty() = first == null + + /** + * removes an element from the list + * + * @param value - element value + * + * @return returns true if the element was successfully removed */ fun remove(value: T) : Boolean { - if (head == null) return false + if (first == null) { + return false + } - var previous: Node? = null - var node = head + var prev = first + var node = first while (node != null) { if (node.value() == value) { - val nextNode = node.next() - previous?.changeNext(nextNode) - - if (head === node) { - head = nextNode + if (prev?.value() == node.value()) { + this.first = null + this.last = null + } else { + prev?.changeNext(node.next()) } - - if (tail === node) { - tail = previous - } - - node.changeNext(null) - node.changeValue(null) - - size-- + count-- return true } - previous = node + prev = node node = node.next() } - return false } - // Complexity: O(n) - fun clear() { - var node = head - while (node != null) { - val currentNode = node - - node = node.next() - - currentNode.changeNext(null) - currentNode.changeValue(null) - } - - head = null - tail = null - size = 0 - } + /** + * add element by index + * + * @param index - the index where the new element should be added + * @param value - the value of the new element + * + * @return returns true if the element was successfully added at the specified index + */ + fun add(index: Int, value: T) : Boolean { - override fun toString(): String { - val builder = StringBuilder() - builder.append("size: $size\n") - builder.append("elements: ") + if (first == null) return false - var node = head + var i = 0 + var node = first while (node != null) { - builder.append(node.value()) - - // it's necessary to see the correct node connections - if (node.next() != null) { - builder.append(" - ") + if (i == index) { + val newNode = Node(value) + node.changeNext(newNode) + count++ + return true } - + i++ node = node.next() } - return builder.toString() + return false } - class Node( - private var value: T? = null, - private var next: Node? = null - ) { + /** + * similar addLast method + * + */ + fun add(value: T) = addLast(value) - fun next() = next - fun changeNext(node: Node? = null) { - next = node + /** + * adds an element to the beginning of the list + * + * @param value - element value + */ + fun addFirst(value: T) { + val node = Node(value) + if (first == null) { + this.first = node + this.last = node + } else { + node.changeNext(first) + this.first = node } + count++ + } - fun value() = value - fun changeValue(newValue: T?) { - value = newValue + /** + * adds an element to the end of the list + * + * @param value - element value + */ + fun addLast(value: T) { + val newNode = Node(value) + if (first == null) { + this.first = newNode + this.last = newNode + } else { + this.last?.changeNext(newNode) + this.last = newNode } - + count++ } } \ No newline at end of file diff --git a/src/main/kotlin/structures/Stack.kt b/src/main/kotlin/structures/Stack.kt new file mode 100644 index 00000000..5f1c3514 --- /dev/null +++ b/src/main/kotlin/structures/Stack.kt @@ -0,0 +1,112 @@ +package structures + +import java.lang.IllegalArgumentException +import kotlin.collections.ArrayList + +/** + * data structure: stack + * + * description: the stack uses the LIFO principle (last in, first out), all operations are performed in O(1) time + * + */ + +interface Stack { + + /** + * adds an element to the top of the stack + * + * @param item - element + */ + fun push(item: T) + + /** + * removes the element at the top of the stack and returns it + * + */ + fun pop() : T + + /** + * returns the element at the top of the stack without removing + * + */ + fun peek() : T + + /** + * returns true if the stack is empty + * + */ + fun isEmpty() : Boolean + + /** + * clears the stack + * + */ + fun clear() + + /** + * implementation using ArrayList + * + * @param T - stack element type + */ + class ArrayListStack : Stack { + private val data = ArrayList() + + override fun push(item: T) { + data.add(item) + } + + override fun pop() : T { + if (isEmpty()) { + throw IllegalArgumentException("Stack is empty!") + } + return data.removeLast() + } + + override fun peek() : T { + if (isEmpty()) { + throw IllegalArgumentException("Stack is empty!") + } + return data.last() + } + + override fun isEmpty() = data.isEmpty() + + override fun clear() { + data.clear() + } + } + + /** + * linked list implementation + * + * @param T - тип элементов стэка + */ + class LinkedListStack : Stack { + private val data = java.util.LinkedList() + + override fun push(item: T) { + data.add(item) + } + + override fun pop(): T { + if (isEmpty()) { + throw IllegalArgumentException("Stack is empty!") + } + return data.removeLast() + } + + override fun peek(): T { + if (isEmpty()) { + throw IllegalArgumentException("Stack is empty!") + } + return data.peekLast() + } + + override fun isEmpty() = data.isEmpty() + + override fun clear() { + data.clear() + } + + } +} diff --git a/src/main/kotlin/structures/Stack1.kt b/src/main/kotlin/structures/Stack1.kt deleted file mode 100644 index c882462e..00000000 --- a/src/main/kotlin/structures/Stack1.kt +++ /dev/null @@ -1,53 +0,0 @@ -package structures - -import java.lang.IllegalArgumentException -import java.util.ArrayList - -/** - * - * Stack is a linear data structure that follows the LIFO (last in first out) principle - * - * LIFO implies that the element that is inserted last, comes out first. - * - * The main operations: - * - * 1) push() - when we insert an element in a stack then the operation is known as a push - * 2) pop() - when we delete an element from the stack, the operation is known as a pop - * - * All these operations performed in O(1) time. - * - */ - -class Stack1 { - // this implementation uses ArrayList - private val data = ArrayList() - - val isEmpty: Boolean - get() = data.size == 0 - - val size: Int - get() = data.size - - fun push(item: T) { - data.add(item) - } - - fun pop() : T { - if (isEmpty) { - throw IllegalArgumentException("Stack is empty!") - } - return data.removeLast() - } - - fun peek() : T { - if (isEmpty) { - throw IllegalArgumentException("Stack is empty!") - } - return data.last() - } - - fun clear() { - data.clear() - } - -} \ No newline at end of file diff --git a/src/main/kotlin/structures/Stack2.kt b/src/main/kotlin/structures/Stack2.kt deleted file mode 100644 index 594ed295..00000000 --- a/src/main/kotlin/structures/Stack2.kt +++ /dev/null @@ -1,53 +0,0 @@ -package structures - -import java.util.LinkedList - -/** - * - * Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle - * - * LIFO implies that the element that is inserted last, comes out first. - * - * The main operations: - * - * push() - when we insert an element in a stack then the operation is known as a push. - * pop() - when we delete an element from the stack, the operation is known as a pop. - * If the stack is empty means that no element exists in the stack. - * - * All these operations performed in O(1) time. - * - */ - -class Stack2 { - // this implementation uses LinkedList - private val data = LinkedList() - - val isEmpty: Boolean - get() = data.size == 0 - - val size: Int - get() = data.size - - fun push(item: T) { - data.add(item) - } - - fun pop(): T { - if (isEmpty) { - throw IllegalArgumentException("Stack is empty!") - } - return data.removeLast() - } - - fun peek(): T { - if (isEmpty) { - throw IllegalArgumentException("Stack is empty!") - } - return data.peekLast() - } - - fun clear() { - data.clear() - } - -} \ No newline at end of file diff --git a/src/test/kotlin/TestUtils.kt b/src/test/kotlin/TestUtils.kt index 91373b44..430555f3 100644 --- a/src/test/kotlin/TestUtils.kt +++ b/src/test/kotlin/TestUtils.kt @@ -1,8 +1,12 @@ - +import org.junit.jupiter.api.Assertions import kotlin.random.Random object TestUtils { + fun assertArrays(expected: Array, actual: Array) { + Assertions.assertEquals(expected.toList(), actual.toList()) + } + fun randomArray(size: Int) = List(size) { Random.nextInt(100) }.toTypedArray() fun sortedArray(size: Int) = List(size) { it }.toTypedArray() diff --git a/src/test/kotlin/design_patterns/AbstractFactoryTest.kt b/src/test/kotlin/design_patterns/AbstractFactoryTest.kt index 0156ce76..de06f318 100644 --- a/src/test/kotlin/design_patterns/AbstractFactoryTest.kt +++ b/src/test/kotlin/design_patterns/AbstractFactoryTest.kt @@ -23,10 +23,6 @@ internal class AbstractFactoryTest { assertThat(androidButton, instanceOf(AndroidButton::class.java)) assertThat(androidText, instanceOf(AndroidText::class.java)) - - // we can draw iOS and Android components regardless of their implementation - listOf(iosButton, androidButton).forEach { it.draw() } - listOf(iosText, androidText).forEach { it.draw() } } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/AdapterTest.kt b/src/test/kotlin/design_patterns/AdapterTest.kt index 6fcd79ec..1b51e24e 100644 --- a/src/test/kotlin/design_patterns/AdapterTest.kt +++ b/src/test/kotlin/design_patterns/AdapterTest.kt @@ -1,21 +1,20 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class AdapterTest { @Test fun test() { - // we don't understand EnglishSpeaker interface - val englishSpeaker = EnglishSpeakerImpl() - // but we know about SpainSpeaker interface - val speakerAdapter = SpainSpeakerAdapter(englishSpeaker) - - // EnglishSpeaker interface was changed to SpainSpeaker interface - val actual = speakerAdapter.speakSpanish() - - assertEquals("Hola, amigo!", actual) + val list = RecyclerView() + val items = listOf(1, 2, 3) + list.changeAdapter(object: Adapter { + override fun getItem(position: Int) = items[position] + override fun getItemCount() = items.size + }) + val drawItems = list.draw() + assertEquals(items, drawItems) } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/BridgeTest.kt b/src/test/kotlin/design_patterns/BridgeTest.kt deleted file mode 100644 index 8c9f45f8..00000000 --- a/src/test/kotlin/design_patterns/BridgeTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class BridgeTest { - - @Test - fun test() { - val windowsSystem = WindowsSystem() - val macOSSystem = MacOSSystem() - - // the line doesn't know how graphics are implemented in different operating systems - val line = GraphicLinePrimitive(0, 0, 100, 100) - line.draw(windowsSystem) - line.draw(macOSSystem) - - // the circle doesn't know how graphics are implemented in different operating systems - val circle = GraphicCirclePrimitive(10, 10, 6) - circle.draw(windowsSystem) - circle.draw(macOSSystem) - - assertEquals(""" - Windows 10 - Lines: - Windows graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100 - Circles: - Windows graphic subsystem -> centerX: 10, centerY: 10, radius: 6 - """.trimIndent(), windowsSystem.toString()) - - assertEquals(""" - MacOS 14 - Lines: - MacOS graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100 - Circles: - MacOS graphic subsystem -> centerX: 10, centerY: 10, radius: 6 - """.trimIndent(), macOSSystem.toString()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/BuilderTest.kt b/src/test/kotlin/design_patterns/BuilderTest.kt index daca987a..fa4224a0 100644 --- a/src/test/kotlin/design_patterns/BuilderTest.kt +++ b/src/test/kotlin/design_patterns/BuilderTest.kt @@ -1,89 +1,54 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class BuilderTest { @Test fun test_first_variant() { - val dnsServerAddress = "8.8.8.8" - val callTimeout = 500 - val connectTimeout = 3_000 - val writeTimeout = 3_000 - val readTimeout = 3_000 - val httpClient = HttpConnectionClient1.Builder() - .dnsServerAddress(dnsServerAddress) - .callTimeout(callTimeout) - .connectTimeout(connectTimeout) - .writeTimeout(writeTimeout) - .readTimeout(readTimeout) - .build() + val name = "Twillight Sparkle" + val cutieMark = "The magic star" + val city = "Canterlot" + val family = "Alicorn" - val expected = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() + val pony = Pony1.Builder().changeName(name) + .changeCutieMark(cutieMark) + .changeCity(city) + .changeFamily(family) + .build() - assertEquals(expected, httpClient.toString()) + assertEquals("$name, $family, $cutieMark, $city", pony.toString()) } @Test fun test_the_second_variant() { - val dnsServerAddress = "8.8.8.8" - val callTimeout = 500 - val connectTimeout = 3_000 - val writeTimeout = 3_000 - val readTimeout = 3_000 - val httpClient = HttpConnectionClient2.newBuilder() - .dnsServerAddress(dnsServerAddress) - .callTimeout(callTimeout) - .connectTimeout(connectTimeout) - .writeTimeout(writeTimeout) - .readTimeout(readTimeout) - .build() + val name = "Twillight Sparkle" + val cutieMark = "The magic star" + val city = "Canterlot" + val family = "Alicorn" - val expected = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() + val pony = Pony2.newBuilder().changeName(name) + .changeCutieMark(cutieMark) + .changeCity(city) + .changeFamily(family) + .build() - assertEquals(expected, httpClient.toString()) + assertEquals("$name, $family, $cutieMark, $city", pony.toString()) } @Test fun test_third_variant() { - val dnsServerAddress = "8.8.8.8" - val callTimeout = 500 - val connectTimeout = 3_000 - val writeTimeout = 3_000 - val readTimeout = 3_000 - val httpClient = HttpConnectionClient3( - dnsServerAddress = dnsServerAddress, - callTimeout = callTimeout, - connectTimeout = connectTimeout, - readTimeout = readTimeout, - writeTimeout = writeTimeout - ) + val name = "Twillight Sparkle" + val city = "Canterlot" + val family = "Alicorn" - val expected = """ - dns -> $dnsServerAddress - call timeout -> $callTimeout - connect timeout -> $connectTimeout - read timeout -> $readTimeout - write timeout -> $writeTimeout - """.trimIndent() + val pony = Pony3(name, family, city = city) - assertEquals(expected, httpClient.toString()) + assertEquals("$name, $family, , $city", pony.toString()) } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt b/src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt index 6c45b69f..6c55b7ed 100644 --- a/src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt +++ b/src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt @@ -1,7 +1,7 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions class ChainOfResponsibilitiesTest { @@ -9,9 +9,9 @@ class ChainOfResponsibilitiesTest { fun test_when_we_have_only_stone_pickaxe() { val pickaxe = StonePickaxe() - assertEquals(true, pickaxe.mine(StoneBlock())) - assertEquals(false, pickaxe.mine(DiamondBlock())) - assertEquals(false, pickaxe.mine(ObsidianBlock())) + Assertions.assertEquals(true, pickaxe.mine(StoneBlock())) + Assertions.assertEquals(false, pickaxe.mine(DiamondBlock())) + Assertions.assertEquals(false, pickaxe.mine(ObsidianBlock())) } @Test @@ -19,22 +19,23 @@ class ChainOfResponsibilitiesTest { val pickaxe = StonePickaxe() pickaxe.changeNextPickaxe(IronPickaxe()) - assertEquals(true, pickaxe.mine(StoneBlock())) - assertEquals(true, pickaxe.mine(DiamondBlock())) - assertEquals(false, pickaxe.mine(ObsidianBlock())) + Assertions.assertEquals(true, pickaxe.mine(StoneBlock())) + Assertions.assertEquals(true, pickaxe.mine(DiamondBlock())) + Assertions.assertEquals(false, pickaxe.mine(ObsidianBlock())) } @Test fun test_when_we_have_all_three_pickaxes() { - val ironPickaxe = IronPickaxe() - ironPickaxe.changeNextPickaxe(DiamondPickaxe()) - - val stonePickaxe = StonePickaxe() - stonePickaxe.changeNextPickaxe(ironPickaxe) - - assertEquals(true, stonePickaxe.mine(StoneBlock())) - assertEquals(true, stonePickaxe.mine(DiamondBlock())) - assertEquals(true, stonePickaxe.mine(ObsidianBlock())) + val pickaxe = StonePickaxe() + val ironPickaxe = IronPickaxe().apply { + changeNextPickaxe(DiamondPickaxe()) + } + pickaxe.changeNextPickaxe(ironPickaxe) + + Assertions.assertEquals(true, pickaxe.mine(StoneBlock())) + Assertions.assertEquals(true, pickaxe.mine(DiamondBlock())) + Assertions.assertEquals(true, pickaxe.mine(ObsidianBlock())) } + } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/CommandTest.kt b/src/test/kotlin/design_patterns/CommandTest.kt index 71f0dd58..6d37a2d1 100644 --- a/src/test/kotlin/design_patterns/CommandTest.kt +++ b/src/test/kotlin/design_patterns/CommandTest.kt @@ -1,74 +1,76 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions internal class CommandTest { @Test - fun `test usual commands`() { - val stereoSystem = StereoSystem() - val remoteControl = StereoSystemRemoteControl(mapOf( - "turnOn" to TurnOnCommand(stereoSystem), - "turnOff" to TurnOffCommand(stereoSystem), - "volume+" to IncreaseVolumeCommand(stereoSystem), - "volume-" to DecreaseVolumeCommand(stereoSystem) - )) + fun test_1() { + val commands = listOf( + AddCommand(10), + AddCommand(20), + MultiCommand(2), + MinusCommand(10) + ) - remoteControl.pressButton("turnOn") + var actual = 0 + commands.forEach { command -> + actual = command.execute(actual) + } - assertEquals(""" - running status: true - volume value: 50 - """.trimIndent(), stereoSystem.currentState) - - remoteControl.pressButton("volume+") - remoteControl.pressButton("volume+") - remoteControl.pressButton("volume+") + Assertions.assertEquals(50, actual) + } - assertEquals(""" - running status: true - volume value: 80 - """.trimIndent(), stereoSystem.currentState) + @Test + fun test_2() { + val commands = listOf( + MultiCommand(2), + MultiCommand(2), + MultiCommand(2), + MultiCommand(2), + MinusCommand(100), + MultiCommand(-1) + ) - remoteControl.pressUndoButton() - remoteControl.pressUndoButton() - remoteControl.pressUndoButton() - remoteControl.pressUndoButton() + var actual = 1 + commands.forEach { command -> + actual = command.execute(actual) + } - assertEquals(""" - running status: false - volume value: 50 - """.trimIndent(), stereoSystem.currentState) + Assertions.assertEquals(84, actual) } @Test - fun `test macro command`() { - val stereoSystem = StereoSystem() - val remoteControl = StereoSystemRemoteControl(mapOf( - "party" to MacroCommand( - TurnOnCommand(stereoSystem), - IncreaseVolumeCommand(stereoSystem), - IncreaseVolumeCommand(stereoSystem), - IncreaseVolumeCommand(stereoSystem), - IncreaseVolumeCommand(stereoSystem), - IncreaseVolumeCommand(stereoSystem) - ) - )) + fun test_3() { + val commands = listOf( + AddCommand(-1), + MinusCommand(1000), + MultiCommand(-2) + ) - remoteControl.pressButton("party") + var actual = 1 + commands.forEach { command -> + actual = command.execute(actual) + } - assertEquals(""" - running status: true - volume value: 100 - """.trimIndent(), stereoSystem.currentState) + Assertions.assertEquals(2000, actual) + } + + @Test + fun test_kotlin_variant() { + val commands: List<(Int) -> Int> = listOf( + { actual: Int -> actual + 49 }, + { actual: Int -> actual - 20 }, + { actual: Int -> actual * 6 } + ) - remoteControl.pressUndoButton() + var actual = 1 + commands.forEach { command -> + actual = command.invoke(actual) + } - assertEquals(""" - running status: false - volume value: 50 - """.trimIndent(), stereoSystem.currentState) + Assertions.assertEquals(180, actual) } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/CompositeTest.kt b/src/test/kotlin/design_patterns/CompositeTest.kt deleted file mode 100644 index 3e043f0c..00000000 --- a/src/test/kotlin/design_patterns/CompositeTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class CompositeTest { - - @Test - fun test() { - val menu = Menu("Delicious Restaurant") - - val pizzasMenu = Menu("Pizzas") - pizzasMenu.addComponent(MenuItem("Cheese pizza", 10)) - pizzasMenu.addComponent(MenuItem("Pepperoni pizza", 11)) - menu.addComponent(pizzasMenu) - - val cakesMenu = Menu("Cakes") - cakesMenu.addComponent(MenuItem("Chocolate cake", 13)) - cakesMenu.addComponent(MenuItem("Cheese cake", 13)) - menu.addComponent(cakesMenu) - - assertEquals(""" - Menu: Delicious Restaurant - Menu: Pizzas - title: Cheese pizza - price: 10 - ------------- - title: Pepperoni pizza - price: 11 - ------------- - Menu: Cakes - title: Chocolate cake - price: 13 - ------------- - title: Cheese cake - price: 13 - ------------- - """.trimIndent(), menu.fetchMenuInformation()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/DecoratorTest.kt b/src/test/kotlin/design_patterns/DecoratorTest.kt index 967b4fd9..d806e25f 100644 --- a/src/test/kotlin/design_patterns/DecoratorTest.kt +++ b/src/test/kotlin/design_patterns/DecoratorTest.kt @@ -1,10 +1,9 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions class DecoratorTest { - @Test fun test() { val printer = ExclamationPrinter( @@ -16,7 +15,6 @@ class DecoratorTest { ) ) ) - assertEquals("Hello, World!", printer.printedText()) + Assertions.assertEquals("Hello, World!", printer.printedText()) } - } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/DependencyInjectionTest.kt b/src/test/kotlin/design_patterns/DependencyInjectionTest.kt new file mode 100644 index 00000000..4955a9d8 --- /dev/null +++ b/src/test/kotlin/design_patterns/DependencyInjectionTest.kt @@ -0,0 +1,14 @@ +package design_patterns + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class DependencyInjectionTest { + @Test + fun test() { + val service = NewsApiService() + val repo = NewsRepository(service) + val viewModel = NewsViewModel(repo) + assertEquals(listOf("event 1", "event 2", "event 3"), viewModel.news) + } +} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/FacadeTest.kt b/src/test/kotlin/design_patterns/FacadeTest.kt index afbcfc4d..591a1bca 100644 --- a/src/test/kotlin/design_patterns/FacadeTest.kt +++ b/src/test/kotlin/design_patterns/FacadeTest.kt @@ -1,36 +1,14 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class FacadeTest { @Test fun test() { - val goodsRepository = GoodsRepository( - GoodsDatabase(), - GoodsNetworkService(), - CategoryDatabase(), - CategoryNetworkService() - ) - - val actual = goodsRepository.goodsAndCategories() - - assertEquals( - GoodsResult( - goods = listOf(GoodsEntity( - id = 1, - name = "Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition", - description = "You know you don't want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who've faced the same software design problems.", - price = 41.94 - )), - categories = listOf(CategoryEntity( - id = 1, - name = "Books" - )) - ), - actual - ) + val facade = Repository(LocalDataSource(), NetworkDataSource()) + val data = facade.fetch() + assertEquals(listOf("Harry Potter", "Ronald Weasley", "Hermione Granger"), data) } - } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/FactoryMethodTest.kt b/src/test/kotlin/design_patterns/FactoryMethodTest.kt index e8c15931..dca22af0 100644 --- a/src/test/kotlin/design_patterns/FactoryMethodTest.kt +++ b/src/test/kotlin/design_patterns/FactoryMethodTest.kt @@ -2,61 +2,32 @@ package design_patterns import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.core.IsInstanceOf.instanceOf -import org.junit.Assert.assertEquals import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals class FactoryMethodTest { @Test - fun `test WoodenHouseCompany`() { - val woodenHouseCompany = WoodenHouseCompany() - - val house1 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.CHEAP) - assertThat(house1, instanceOf(WoodenCheapHouse::class.java)) - - val house2 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.AVERAGE) - assertThat(house2, instanceOf(WoodenAverageHouse::class.java)) - - val house3 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.EXPENSIVE) - assertThat(house3, instanceOf(WoodenExpensiveHouse::class.java)) - - val expected = """ - address = 77, Brook Ave - price = 50000 - - address = 77, Brook Ave - price = 250000 - - address = 77, Brook Ave - price = 1000000 - """.trimIndent() - assertEquals(expected, woodenHouseCompany.examplesAlreadyBuiltHouses) + fun test_match_objects() { + val ponyville = Ponyville() + val earthPony = ponyville.newPony() + + assertThat(earthPony, instanceOf(EarthPony4::class.java)) + + val canterlot = Canterlot() + val unicorn = canterlot.newPony() + + assertThat(unicorn, instanceOf(Unicorn4::class.java)) } @Test - fun `test StoneHouseCompany`() { - val stoneHouseCompany = StoneHouseCompany() - - val house1 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.CHEAP) - assertThat(house1, instanceOf(StoneCheapHouse::class.java)) - - val house2 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.AVERAGE) - assertThat(house2, instanceOf(StoneAverageHouse::class.java)) - - val house3 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.EXPENSIVE) - assertThat(house3, instanceOf(StoneExpensiveHouse::class.java)) - - val expected = """ - address = 55, Brook Ave - price = 45000 - - address = 55, Brook Ave - price = 230000 - - address = 55, Brook Ave - price = 900000 - """.trimIndent() - assertEquals(expected, stoneHouseCompany.examplesAlreadyBuiltHouses) - } + fun test_count() { + val cloudsDale = Cloudsdale() + + cloudsDale.newPony() + cloudsDale.newPony() + cloudsDale.newPony() + assertEquals(3, cloudsDale.count()) + } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/FluentInterfaceTest.kt b/src/test/kotlin/design_patterns/FluentInterfaceTest.kt new file mode 100644 index 00000000..d58a6e14 --- /dev/null +++ b/src/test/kotlin/design_patterns/FluentInterfaceTest.kt @@ -0,0 +1,20 @@ +package design_patterns + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class FluentInterfaceTest { + + @Test + fun test() { + + val view = View().bg(0xffffff).focusable().clickable() + + view.draw() + + assertEquals(0xffffff, view.bgColor()) + assertEquals(true, view.isClickable()) + assertEquals(true, view.hasFocus()) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/FlyweightTest.kt b/src/test/kotlin/design_patterns/FlyweightTest.kt deleted file mode 100644 index 2724b871..00000000 --- a/src/test/kotlin/design_patterns/FlyweightTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class FlyweightTest { - - @Test - fun test() { - val garden = BeautifulGarden() - - garden.placeTree("oak", "", 21, 10, 10) - garden.placeTree("birch", "", 15, 10, 20) - garden.placeTree("birch", "", 16, 10, 30) - garden.placeTree("birch", "", 17, 10, 40) - garden.placeTree("oak", "", 21, 20, 10) - garden.placeTree("oak", "", 21, 20, 20) - garden.placeTree("oak", "", 21, 20, 30) - garden.placeTree("birch", "", 15, 20, 40) - - assertEquals(""" - Beautiful Garden: - name: oak, height: 21, x: 10, y: 10 - name: birch, height: 15, x: 10, y: 20 - name: birch, height: 16, x: 10, y: 30 - name: birch, height: 17, x: 10, y: 40 - name: oak, height: 21, x: 20, y: 10 - name: oak, height: 21, x: 20, y: 20 - name: oak, height: 21, x: 20, y: 30 - name: birch, height: 15, x: 20, y: 40 - -|-|-|-|-|-|-|-|-|-|- - """.trimIndent(), garden.placedTreesAsString()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/InterpreterTest.kt b/src/test/kotlin/design_patterns/InterpreterTest.kt deleted file mode 100644 index e58010c2..00000000 --- a/src/test/kotlin/design_patterns/InterpreterTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class InterpreterTest { - - @Test - fun test() { - // x = 10, y = 20, d = 5 - // sum = x + y - // result = sum * d - val expression = PerformExpression( - SetIntVariableExpression("x", 10), - SetIntVariableExpression("y", 20), - AddVariablesExpression("x", "y", "sum"), - SetIntVariableExpression("d", 5), - MultipleVariablesExpression("sum", "d", "result") - ) - - val context = InterpreterContext() - - expression.interpret(context) - - assertEquals(150, context.fetchVariable("result")) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/IteratorTest.kt b/src/test/kotlin/design_patterns/IteratorTest.kt deleted file mode 100644 index 75651cf2..00000000 --- a/src/test/kotlin/design_patterns/IteratorTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class IteratorTest { - - @Test - fun test() { - val presents = arrayOf("chocolate cake", "snowboard", "snowman") - val giftBox = GiftBox(presents) - val giftBoxIterator = giftBox.iterator() - val actualPresents = mutableListOf() - while (giftBoxIterator.hasNext()) { - val present = giftBoxIterator.next() - actualPresents.add(present) - } - assertEquals(presents.toList(), actualPresents) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/MediatorTest.kt b/src/test/kotlin/design_patterns/MediatorTest.kt deleted file mode 100644 index 7abdd71e..00000000 --- a/src/test/kotlin/design_patterns/MediatorTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class MediatorTest { - - @Test - fun test() { - val manager = SoftwareDevelopmentManager() - - val customer = CustomerSoftwareDevelopmentMember(manager) - manager.changeCustomer(customer) - val designer = DesignerSoftwareDevelopmentMember(manager) - manager.changeDesigner(designer) - val programmer = ProgrammerSoftwareDevelopmentMember(manager) - manager.changeProgrammer(programmer) - val tester = TesterSoftwareDevelopmentMember(manager) - manager.changeTester(tester) - - customer.finishWork() - designer.finishWork() - programmer.finishWork() - tester.finishWork() - - assertEquals(""" - Designer accepted the work: design development - Programmer accepted the work: writing code - Tester accepted the work: application testing - Customer accepted the work: business valuation - """.trimIndent(), manager.stagesAsString) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/Memento.kt b/src/test/kotlin/design_patterns/Memento.kt new file mode 100644 index 00000000..027e7020 --- /dev/null +++ b/src/test/kotlin/design_patterns/Memento.kt @@ -0,0 +1,34 @@ +package design_patterns + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +class Memento { + + @Test + fun test() { + // start Android system + val android = AndroidSystem() + + val greetingText = TextView1() + greetingText.setText(greeting) + greetingText.draw() + + // rotating Android device (recreating Application components) + // saving state + android.saveBundle(greetingText.onSaveInstanceState()) + + // the state of the text was lost, but we saved it + greetingText.setText("") + + // Android device has already rotated + // restoring state + greetingText.onRestoreInstanceState(android.restoreBundle()) + + Assertions.assertEquals(greeting, greetingText.text()) + } + + companion object { + private const val greeting = "Hello, World!" + } +} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/MementoTest.kt b/src/test/kotlin/design_patterns/MementoTest.kt deleted file mode 100644 index bf727324..00000000 --- a/src/test/kotlin/design_patterns/MementoTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class MementoTest { - - @Test - fun test() { - // start Android system - val androidOS = AndroidSystem() - - val greetingText = "Hello, World!" - val greetingView = TextView() - greetingView.setText(greetingText) - greetingView.draw() - - // rotating Android device (recreating application components) - // Android system saves the states of running applications - androidOS.saveBundle(greetingView.onSaveInstanceState()) - - // the state of the text was lost, but we saved it - greetingView.setText("") - - // Android device has already rotated - // The system restores the states of running applications - greetingView.onRestoreInstanceState(androidOS.restoreBundle()) - - assertEquals(greetingText, greetingView.text()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/MonostateTest.kt b/src/test/kotlin/design_patterns/MonostateTest.kt new file mode 100644 index 00000000..7346ce75 --- /dev/null +++ b/src/test/kotlin/design_patterns/MonostateTest.kt @@ -0,0 +1,23 @@ +package design_patterns + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class MonostateTest { + + @Test + fun test() { + + val linearLayout = mutableListOf() + + for (i in 1..10) { + linearLayout.add(TextView()) + } + + assertEquals(10, linearLayout.first().textViewCount()) + + linearLayout.forEach { txtView -> txtView.onDetachView() } + + assertEquals(0, linearLayout.first().textViewCount()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/ObserverTest.kt b/src/test/kotlin/design_patterns/ObserverTest.kt index ce6b4a35..0de57c61 100644 --- a/src/test/kotlin/design_patterns/ObserverTest.kt +++ b/src/test/kotlin/design_patterns/ObserverTest.kt @@ -1,29 +1,15 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class ObserverTest { - @Test fun test() { val ponyList = PonyList() - - val observer1 = PonyObserver { items -> - assertEquals(listOf("Twillight Sparkle"), items) + ponyList.observe { items -> + assertEquals("Twillight Sparkle", items.first()) } - ponyList.addObserver(observer1) - // we add the first item, observer1 is triggered ponyList.add("Twillight Sparkle") - // we remove observer1 so that it is not called again - ponyList.removeObserver(observer1) - - val observer2 = PonyObserver { items -> - assertEquals(listOf("Twillight Sparkle", "Starlight Glimmer"), items) - } - ponyList.addObserver(observer2) - // we add the second item, observer2 is triggered - ponyList.add("Starlight Glimmer") } - } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/PrototypeTest.kt b/src/test/kotlin/design_patterns/PrototypeTest.kt deleted file mode 100644 index 8904cbb0..00000000 --- a/src/test/kotlin/design_patterns/PrototypeTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class PrototypeTest { - - @Test - fun test() { - // we have a list of sweets that need to be made at the confectionery factory - val recipesOfSweets = listOf( - OreoCookies("Original OREO", "Rich chocolate cookies with vanilla creme", 12), - OreoCookies("Golden OREO", "Sweet vanilla cookies with vanilla creme", 13), - OreoCookies("OREO Thins", "Sweet vanilla cookies with vanilla creme", 11), - `M&MsChocolate`("with puffed rice", 10), - `M&MsChocolate`("with peanuts", 11) - ) - - // we produce sweets according to existing recipes - val producedSweets = recipesOfSweets.flatMap { sweets -> List(10) { sweets.copy() } } - - assertEquals(producedSweets.size, 50) - assertEquals(producedSweets[9], recipesOfSweets[0]) - assertEquals(producedSweets[19], recipesOfSweets[1]) - assertEquals(producedSweets[29], recipesOfSweets[2]) - assertEquals(producedSweets[39], recipesOfSweets[3]) - assertEquals(producedSweets[49], recipesOfSweets[4]) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/ProxyTest.kt b/src/test/kotlin/design_patterns/ProxyTest.kt deleted file mode 100644 index 83152556..00000000 --- a/src/test/kotlin/design_patterns/ProxyTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class ProxyTest { - - @Test - fun test() { - // we use the proxy object instead of a real one - val mediaPlayer = AudioPlayerProxy() - - mediaPlayer.play("track_0.mp3") - assertEquals(""" - current audio: track_0.mp3 - current status: RUNNING - """.trimIndent(), mediaPlayer.currentState) - - mediaPlayer.pause() - assertEquals(""" - current audio: track_0.mp3 - current status: PAUSED - """.trimIndent(), mediaPlayer.currentState) - - mediaPlayer.resume() - assertEquals(""" - current audio: track_0.mp3 - current status: RUNNING - """.trimIndent(), mediaPlayer.currentState) - - mediaPlayer.stop() - assertEquals(""" - current audio: - current status: NOT_INITIALIZED - """.trimIndent(), mediaPlayer.currentState) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/SingletonTest.kt b/src/test/kotlin/design_patterns/SingletonTest.kt index ec28877a..d438d242 100644 --- a/src/test/kotlin/design_patterns/SingletonTest.kt +++ b/src/test/kotlin/design_patterns/SingletonTest.kt @@ -1,21 +1,16 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class SingletonTest { @Test fun test() { - // we have one instance of SQLiteDatabase class - SQLiteDatabase.openConnection() + LocalData.addName("Twillight Sparkle") + LocalData.addName("Starlight Glimmer") - val actual = SQLiteDatabase.execSQL("select * from names") - val expected = listOf("Rick", "Morty", "Jerry", "Beth") - - assertEquals(expected, actual) - - SQLiteDatabase.closeConnection() + assertEquals(listOf("Twillight Sparkle", "Starlight Glimmer"), LocalData.names()) } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/StateTest.kt b/src/test/kotlin/design_patterns/StateTest.kt deleted file mode 100644 index d5b13b67..00000000 --- a/src/test/kotlin/design_patterns/StateTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class StateTest { - - @Test - fun test() { - val machine = CocaColaMachine() - - assertEquals("NoDollarCocaColaState", machine.currentState) - machine.pressButton() - assertEquals("NoDollarCocaColaState", machine.currentState) - - machine.insertDollar() - assertEquals("HaveDollarCocaColaState", machine.currentState) - machine.takeBackDollar() - assertEquals("NoDollarCocaColaState", machine.currentState) - machine.takeBackDollar() - assertEquals("NoDollarCocaColaState", machine.currentState) - - machine.insertDollar() - assertEquals("HaveDollarCocaColaState", machine.currentState) - machine.pressButton() - assertEquals("NoDollarCocaColaState", machine.currentState) - - machine.insertDollar() - assertEquals("HaveDollarCocaColaState", machine.currentState) - machine.pressButton() - assertEquals("NoDollarCocaColaState", machine.currentState) - - machine.insertDollar() - assertEquals("HaveDollarCocaColaState", machine.currentState) - machine.pressButton() - assertEquals("EmptyCocaColaState", machine.currentState) - - machine.insertDollar() - assertEquals("EmptyCocaColaState", machine.currentState) - - machine.loadDrinks(1) - machine.insertDollar() - assertEquals("HaveDollarCocaColaState", machine.currentState) - machine.pressButton() - assertEquals("EmptyCocaColaState", machine.currentState) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/StrategyTest.kt b/src/test/kotlin/design_patterns/StrategyTest.kt index d7ec59a7..ec2b12d8 100644 --- a/src/test/kotlin/design_patterns/StrategyTest.kt +++ b/src/test/kotlin/design_patterns/StrategyTest.kt @@ -1,72 +1,19 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class StrategyTest { @Test fun test() { - val strategy = OnlyChipsFilterStrategy() - val foodStore = FoodStore(strategy) - assertEquals(listOf( - FoodEntity( - "Lays Potato Chips Fried Crab Flavor", - 2, - "chips" - ), - FoodEntity( - "Lay's Potato Chips, Classic", - 3, - "chips" - ) - ), foodStore.foodItems()) + val exchange = RubleExchangeRate() + assertEquals(1.0, exchange.exchange(70.0)) - foodStore.changeStrategy(OnlyChocolateFilterStrategy()) + exchange.changeStrategy(ExchangeStrategy.Tenge()) + assertEquals(60.0, exchange.exchange(10.0)) - assertEquals(listOf( - FoodEntity( - "Dove Chocolate", - 3, - "chocolate" - ), - FoodEntity( - "Ritter Sport Chocolate", - 4, - "chocolate" - ) - ), foodStore.foodItems()) - - foodStore.changeStrategy(PriceFilterStrategy(3)) - - assertEquals(listOf( - FoodEntity( - "Lay's Potato Chips, Classic", - 3, - "chips" - ), - FoodEntity( - "Dove Chocolate", - 3, - "chocolate" - ), - FoodEntity( - "Ritter Sport Chocolate", - 4, - "chocolate" - ) - ), foodStore.foodItems()) - - foodStore.changeStrategy(SearchWordFilterStrategy("Ritter Sport")) - - assertEquals(listOf( - FoodEntity( - "Ritter Sport Chocolate", - 4, - "chocolate" - ) - ), foodStore.foodItems()) } } \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/TemplateMethodTest.kt b/src/test/kotlin/design_patterns/TemplateMethodTest.kt deleted file mode 100644 index 9dc2a38d..00000000 --- a/src/test/kotlin/design_patterns/TemplateMethodTest.kt +++ /dev/null @@ -1,44 +0,0 @@ -package design_patterns - -import org.junit.Test -import org.junit.Assert.assertEquals - -class TemplateMethodTest { - - @Test - fun `test ChocolateCakeBaker`() { - val baker = ChocolateCakeBaker() - - val actual = baker.makeCake(3) - val expected = Cake( - layers = listOf( - "chocolate cake layer", - "chocolate cake layer", - "chocolate cake layer" - ), - cream = "chocolate cream", - sprinkles = "chocolate chips" - ) - - assertEquals(expected, actual) - } - - @Test - fun `test WaffleCakeBaker`() { - val baker = WaffleCakeBaker() - - val actual = baker.makeCake(3) - val expected = Cake( - layers = listOf( - "waffle cake layer", - "waffle cake layer", - "waffle cake layer" - ), - cream = "custard cream", - sprinkles = "coconut flakes" - ) - - assertEquals(expected, actual) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/design_patterns/VisitorTest.kt b/src/test/kotlin/design_patterns/VisitorTest.kt index 389c5e6f..621897a0 100644 --- a/src/test/kotlin/design_patterns/VisitorTest.kt +++ b/src/test/kotlin/design_patterns/VisitorTest.kt @@ -1,7 +1,7 @@ package design_patterns import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class VisitorTest { diff --git a/src/test/kotlin/other/BinaryDigitsCounterTest.kt b/src/test/kotlin/other/BinaryDigitsCounterTest.kt index 54f244e3..a2b97680 100644 --- a/src/test/kotlin/other/BinaryDigitsCounterTest.kt +++ b/src/test/kotlin/other/BinaryDigitsCounterTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions internal class BinaryDigitsCounterTest { @@ -11,35 +11,35 @@ internal class BinaryDigitsCounterTest { fun test_empty_string() { val result = counter.compute("") - assertEquals(BinaryDigitsCounter.Result(), result) + Assertions.assertEquals(BinaryDigitsCounter.Result(), result) } @Test fun test_binary_string_1() { val result = counter.compute("10101111000") - assertEquals(BinaryDigitsCounter.Result(6, 5), result) + Assertions.assertEquals(BinaryDigitsCounter.Result(6, 5), result) } @Test fun test_binary_string_2() { val result = counter.compute("0100000111110010101010") - assertEquals(BinaryDigitsCounter.Result(10, 12), result) + Assertions.assertEquals(BinaryDigitsCounter.Result(10, 12), result) } @Test fun test_binary_string_3() { val result = counter.compute("1111111111") - assertEquals(BinaryDigitsCounter.Result(10, 0), result) + Assertions.assertEquals(BinaryDigitsCounter.Result(10, 0), result) } @Test fun test_binary_string_4() { val result = counter.compute("0000000000") - assertEquals(BinaryDigitsCounter.Result(0, 10), result) + Assertions.assertEquals(BinaryDigitsCounter.Result(0, 10), result) } } \ No newline at end of file diff --git a/src/test/kotlin/other/EuclidAlgorithmTest.kt b/src/test/kotlin/other/EuclidAlgorithmTest.kt deleted file mode 100644 index 603d871c..00000000 --- a/src/test/kotlin/other/EuclidAlgorithmTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class EuclidAlgorithmTest { - - private val euclidAlgorithm = EuclidAlgorithm() - - @Test - fun `test computeByDivisionWithRemainder`() { - assertEquals(5, euclidAlgorithm.computeByDivisionWithRemainder(10, 5)) - assertEquals(10, euclidAlgorithm.computeByDivisionWithRemainder(10, 100)) - assertEquals(9, euclidAlgorithm.computeByDivisionWithRemainder(9, 27)) - assertEquals(13, euclidAlgorithm.computeByDivisionWithRemainder(26, 39)) - assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(135, 13)) - assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(27, 19)) - assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(2, 17)) - assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(4, 9)) - } - - @Test - fun `test computeBySubtraction`() { - assertEquals(5, euclidAlgorithm.computeBySubtraction(10, 5)) - assertEquals(10, euclidAlgorithm.computeBySubtraction(10, 100)) - assertEquals(9, euclidAlgorithm.computeBySubtraction(9, 27)) - assertEquals(13, euclidAlgorithm.computeBySubtraction(26, 39)) - assertEquals(1, euclidAlgorithm.computeBySubtraction(135, 13)) - assertEquals(1, euclidAlgorithm.computeBySubtraction(27, 19)) - assertEquals(1, euclidAlgorithm.computeBySubtraction(2, 17)) - assertEquals(1, euclidAlgorithm.computeBySubtraction(4, 9)) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/EuclidTest.kt b/src/test/kotlin/other/EuclidTest.kt new file mode 100644 index 00000000..ab053999 --- /dev/null +++ b/src/test/kotlin/other/EuclidTest.kt @@ -0,0 +1,26 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class EuclidTest { + + private val euclid = Euclid() + + @Test + fun test_one() { + assertEquals(5, euclid.compute(10, 5)) + assertEquals(10, euclid.compute(10, 100)) + assertEquals(9, euclid.compute(9, 27)) + assertEquals(13, euclid.compute(26, 39)) + } + + @Test + fun test_two() { + assertEquals(1, euclid.compute(135, 13)) + assertEquals(1, euclid.compute(27, 19)) + assertEquals(1, euclid.compute(2, 17)) + assertEquals(1, euclid.compute(4, 9)) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/FactorialAdvancedTest.kt b/src/test/kotlin/other/FactorialAdvancedTest.kt index dbb1a14f..b69117c1 100644 --- a/src/test/kotlin/other/FactorialAdvancedTest.kt +++ b/src/test/kotlin/other/FactorialAdvancedTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions internal class FactorialAdvancedTest { @@ -10,13 +10,13 @@ internal class FactorialAdvancedTest { @Test fun test_factorial_30() { val actual = factorial.compute(30) - assertEquals("265252859812191058636308480000000", actual.toString()) + Assertions.assertEquals("265252859812191058636308480000000", actual.toString()) } @Test fun test_factorial_60() { val actual = factorial.compute(60) - assertEquals("8320987112741390144276341183223364380754172606361245952449277696409600000000000000", actual.toString()) + Assertions.assertEquals("8320987112741390144276341183223364380754172606361245952449277696409600000000000000", actual.toString()) } @Test @@ -26,7 +26,7 @@ internal class FactorialAdvancedTest { "864000000000000000000000000" val actual = factorial.compute(100) - assertEquals(expected, actual.toString()) + Assertions.assertEquals(expected, actual.toString()) } @Test @@ -37,7 +37,7 @@ internal class FactorialAdvancedTest { "1904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000" val actual = factorial.compute(200) - assertEquals(expected, actual.toString()) + Assertions.assertEquals(expected, actual.toString()) } @Test @@ -77,7 +77,6 @@ internal class FactorialAdvancedTest { "000000000000000000000000000000000000000000000000" val actual = factorial.compute(1000) - assertEquals(expected, actual.toString()) + Assertions.assertEquals(expected, actual.toString()) } - } \ No newline at end of file diff --git a/src/test/kotlin/other/FactorialBigWithCacheTest.kt b/src/test/kotlin/other/FactorialBigWithCacheTest.kt index e297ec52..5667e17e 100644 --- a/src/test/kotlin/other/FactorialBigWithCacheTest.kt +++ b/src/test/kotlin/other/FactorialBigWithCacheTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class FactorialBigWithCacheTest { diff --git a/src/test/kotlin/other/FactorialTest.kt b/src/test/kotlin/other/FactorialTest.kt index 3853e3cb..631e86d1 100644 --- a/src/test/kotlin/other/FactorialTest.kt +++ b/src/test/kotlin/other/FactorialTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class FactorialTest { @@ -34,4 +34,5 @@ internal class FactorialTest { assertEquals(720, factorial.computeRecursiveWithKotlinOptimization(6)) } + } \ No newline at end of file diff --git a/src/test/kotlin/other/FactorialWithCacheTest.kt b/src/test/kotlin/other/FactorialWithCacheTest.kt index ea0e7071..bd4a8dc8 100644 --- a/src/test/kotlin/other/FactorialWithCacheTest.kt +++ b/src/test/kotlin/other/FactorialWithCacheTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class FactorialWithCacheTest { diff --git a/src/test/kotlin/other/FizzBuzzTest.kt b/src/test/kotlin/other/FizzBuzzTest.kt index 40bba05f..def1a13a 100644 --- a/src/test/kotlin/other/FizzBuzzTest.kt +++ b/src/test/kotlin/other/FizzBuzzTest.kt @@ -1,7 +1,7 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class FizzBuzzTest { @@ -34,5 +34,4 @@ internal class FizzBuzzTest { val expected = "1" assertEquals(expected, actual) } - } \ No newline at end of file diff --git a/src/test/kotlin/other/KnuthMorrisPrattAlgorithmTest.kt b/src/test/kotlin/other/KnuthMorrisPrattAlgorithmTest.kt deleted file mode 100644 index ea343beb..00000000 --- a/src/test/kotlin/other/KnuthMorrisPrattAlgorithmTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class KnuthMorrisPrattAlgorithmTest { - - @Test - fun test() { - val knuthMorrisPrattAlgorithm = KnuthMorrisPrattAlgorithm() - - val sentence1 = "Twillight Sparkle likes reading books!" - assertEquals(true, knuthMorrisPrattAlgorithm.contains("Twillight Sparkle", sentence1)) - assertEquals(true, knuthMorrisPrattAlgorithm.contains("likes", sentence1)) - assertEquals(true, knuthMorrisPrattAlgorithm.contains("reading", sentence1)) - assertEquals(true, knuthMorrisPrattAlgorithm.contains("books", sentence1)) - - assertEquals(false, knuthMorrisPrattAlgorithm.contains("Apple Jack", sentence1)) - assertEquals(false, knuthMorrisPrattAlgorithm.contains("loves", sentence1)) - assertEquals(false, knuthMorrisPrattAlgorithm.contains("learning", sentence1)) - assertEquals(false, knuthMorrisPrattAlgorithm.contains("articles", sentence1)) - - val sentence2 = """ - Watch the Keynote, livestream replay, and tech talks to hear about the latest updates - in Android development directly from the Android team. - """.trimIndent() - assertEquals(3, knuthMorrisPrattAlgorithm.count("the", sentence2)) - assertEquals(2, knuthMorrisPrattAlgorithm.count("Android", sentence2)) - assertEquals(1, knuthMorrisPrattAlgorithm.count("and", sentence2)) - assertEquals(1, knuthMorrisPrattAlgorithm.count("Keynote", sentence2)) - - assertEquals(0, knuthMorrisPrattAlgorithm.count("Kotlin", sentence2)) - assertEquals(0, knuthMorrisPrattAlgorithm.count("Jetpack Compose", sentence2)) - assertEquals(0, knuthMorrisPrattAlgorithm.count("Android Studio", sentence2)) - assertEquals(0, knuthMorrisPrattAlgorithm.count("developers", sentence2)) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/KnuthMorrisPrattTest.kt b/src/test/kotlin/other/KnuthMorrisPrattTest.kt new file mode 100644 index 00000000..d5f6560a --- /dev/null +++ b/src/test/kotlin/other/KnuthMorrisPrattTest.kt @@ -0,0 +1,19 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class KnuthMorrisPrattTest { + + @Test + fun test() { + val knuthMorrisPratt = KnuthMorrisPratt() + + assertEquals(true, knuthMorrisPratt.contains("twilly", "twilly likes reading books!")) + assertEquals(false, knuthMorrisPratt.contains("I", "you are so beautiful!")) + + assertEquals(3, knuthMorrisPratt.count("the", "Watch the Keynote, livestream replay, and tech talks to hear about the latest updates in Android development directly from the Android team.")) + assertEquals(0, knuthMorrisPratt.count("Kotlin", "Watch the Keynote, livestream replay, and tech talks to hear about the latest updates in Android development directly from the Android team.")) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/LevenshteinLengthAlgorithmTest.kt b/src/test/kotlin/other/LevenshteinLengthAlgorithmTest.kt deleted file mode 100644 index 3a139924..00000000 --- a/src/test/kotlin/other/LevenshteinLengthAlgorithmTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class LevenshteinLengthAlgorithmTest { - - @Test - fun test() { - val levenshteinLengthAlgorithm = LevenshteinLengthAlgorithm() - - val str1 = "hello" - val str2 = "hello," - assertEquals(1, levenshteinLengthAlgorithm.compute(str1, str2)) - - val str3 = "hello, world!" - val str4 = "hello, friend" - assertEquals(6, levenshteinLengthAlgorithm.compute(str3, str4)) - - assertEquals(0, levenshteinLengthAlgorithm.compute(str1, str1)) - assertEquals(0, levenshteinLengthAlgorithm.compute(str2, str2)) - assertEquals(0, levenshteinLengthAlgorithm.compute(str3, str3)) - assertEquals(0, levenshteinLengthAlgorithm.compute(str4, str4)) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/LevenshteinLengthTest.kt b/src/test/kotlin/other/LevenshteinLengthTest.kt new file mode 100644 index 00000000..fda9a613 --- /dev/null +++ b/src/test/kotlin/other/LevenshteinLengthTest.kt @@ -0,0 +1,27 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class LevenshteinLengthTest { + + private val levenshteinLength = LevenshteinLength() + + @Test + fun test_some_changes() { + val str1 = "hello" + val str2 = "hello," + assertEquals(1, levenshteinLength.compute(str1, str2)) + + val str3 = "hello, world!" + val str4 = "hello, friend" + assertEquals(6, levenshteinLength.compute(str3, str4)) + } + + @Test + fun test_no_changes() { + val str1 = "hello" + assertEquals(0, levenshteinLength.compute(str1, str1)) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/MaxAlgorithmTest.kt b/src/test/kotlin/other/MaxAlgorithmTest.kt deleted file mode 100644 index 7e12e910..00000000 --- a/src/test/kotlin/other/MaxAlgorithmTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class MaxAlgorithmTest { - - private val maxAlgorithm = MaxAlgorithm() - - @Test - fun `test iterative algorithm`() { - val actual1 = maxAlgorithm.compute(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) - assertEquals(10, actual1) - - val actual2 = maxAlgorithm.compute(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) - assertEquals(10, actual2) - - val actual3 = maxAlgorithm.compute(listOf(-50, 10, 6, -100, -9, 110)) - assertEquals(110, actual3) - } - - @Test - fun `test recursive algorithm`() { - val actual1 = maxAlgorithm.computeRecursive(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) - assertEquals(10, actual1) - - val actual2 = maxAlgorithm.computeRecursive(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) - assertEquals(10, actual2) - - val actual3 = maxAlgorithm.computeRecursive(listOf(-50, 10, 6, -100, -9, 110)) - assertEquals(110, actual3) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/MaxTest.kt b/src/test/kotlin/other/MaxTest.kt new file mode 100644 index 00000000..db00fc9d --- /dev/null +++ b/src/test/kotlin/other/MaxTest.kt @@ -0,0 +1,34 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class MaxTest { + + private val max = Max() + + @Test + fun test_sorted() { + val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + assertEquals(10, max.compute(items)) + } + + @Test + fun test_reversed() { + val items = listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1) + assertEquals(10, max.compute(items)) + } + + @Test + fun test_sorted_recursive() { + val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + assertEquals(10, max.computeRecursive(items)) + } + + @Test + fun test_reversed_recursive() { + val items = listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1) + assertEquals(10, max.computeRecursive(items)) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/MinAlgorithmTest.kt b/src/test/kotlin/other/MinAlgorithmTest.kt deleted file mode 100644 index 398cfc44..00000000 --- a/src/test/kotlin/other/MinAlgorithmTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class MinAlgorithmTest { - - private val minAlgorithm = MinAlgorithm() - - @Test - fun `test iterative algorithm`() { - val actual1 = minAlgorithm.compute(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) - assertEquals(1, actual1) - - val actual2 = minAlgorithm.compute(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) - assertEquals(1, actual2) - - val actual3 = minAlgorithm.compute(listOf(-50, 10, 6, -100, -9, 110)) - assertEquals(-100, actual3) - } - - @Test - fun `test recursive algorithm`() { - val actual1 = minAlgorithm.computeRecursive(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) - assertEquals(1, actual1) - - val actual2 = minAlgorithm.computeRecursive(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) - assertEquals(1, actual2) - - val actual3 = minAlgorithm.computeRecursive(listOf(-50, 10, 6, -100, -9, 110)) - assertEquals(-100, actual3) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/MinTest.kt b/src/test/kotlin/other/MinTest.kt new file mode 100644 index 00000000..7ce8eb4f --- /dev/null +++ b/src/test/kotlin/other/MinTest.kt @@ -0,0 +1,33 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class MinTest { + + private val min = Min() + + @Test + fun test_sorted() { + val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + assertEquals(1, min.compute(items)) + } + + @Test + fun test_reversed() { + val items = listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1) + assertEquals(1, min.compute(items)) + } + + @Test + fun test_sorted_recursive() { + val items = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + assertEquals(1, min.computeRecursive(items)) + } + + @Test + fun test_reversed_recursive() { + val items = listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1) + assertEquals(1, min.computeRecursive(items)) + } +} \ No newline at end of file diff --git a/src/test/kotlin/other/PalindromeAdvancedTest.kt b/src/test/kotlin/other/PalindromeAdvancedTest.kt new file mode 100644 index 00000000..5181be1a --- /dev/null +++ b/src/test/kotlin/other/PalindromeAdvancedTest.kt @@ -0,0 +1,40 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +class PalindromeAdvancedTest { + + @Test + fun test_empty_string() { + val text1 = "" + assertEquals(PalindromeAdvanced(text1).isYes(), true) + } + + @Test + fun test_one_length() { + val text1 = "a" + assertEquals(PalindromeAdvanced(text1).isYes(), true) + } + + @Test + fun test_is_palindrome() { + val text1 = "tenet" + assertEquals(PalindromeAdvanced(text1).isYes(), true) + + val text2 = "friend" + assertEquals(PalindromeAdvanced(text2).isYes(), false) + } + + @Test + fun test_is_not_palindrome() { + val text1 = "white" + assertEquals(PalindromeAdvanced(text1).isNot(), true) + + val text2 = "tenet" + assertEquals(PalindromeAdvanced(text2).isNot(), false) + } + +} + + diff --git a/src/test/kotlin/other/PalindromeAlgorithmTest.kt b/src/test/kotlin/other/PalindromeAlgorithmTest.kt deleted file mode 100644 index 37baee9e..00000000 --- a/src/test/kotlin/other/PalindromeAlgorithmTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -class PalindromeAlgorithmTest { - - private val palindromeAlgorithm = PalindromeAlgorithm() - - @Test - fun `test empty string`() { - assertEquals(true, palindromeAlgorithm.isPalindrome("")) - - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("")) - } - - @Test - fun `test string with one symbol`() { - assertEquals(true, palindromeAlgorithm.isPalindrome("a")) - assertEquals(true, palindromeAlgorithm.isPalindrome("b")) - assertEquals(true, palindromeAlgorithm.isPalindrome("c")) - assertEquals(true, palindromeAlgorithm.isPalindrome("d")) - assertEquals(true, palindromeAlgorithm.isPalindrome("e")) - assertEquals(true, palindromeAlgorithm.isPalindrome("f")) - - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("a")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("b")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("c")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("d")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("e")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("f")) - - } - - @Test - fun `test string is palindrome`() { - assertEquals(true, palindromeAlgorithm.isPalindrome("tenet")) - assertEquals(true, palindromeAlgorithm.isPalindrome("madam")) - assertEquals(true, palindromeAlgorithm.isPalindrome("racecar")) - assertEquals(true, palindromeAlgorithm.isPalindrome("dad")) - - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("tenet")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("madam")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("racecar")) - assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion("dad")) - } - - @Test - fun `test string is not palindrome`() { - assertEquals(false, palindromeAlgorithm.isPalindrome("friend")) - assertEquals(false, palindromeAlgorithm.isPalindrome("success")) - assertEquals(false, palindromeAlgorithm.isPalindrome("mistake")) - assertEquals(false, palindromeAlgorithm.isPalindrome("language")) - - assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion("friend")) - assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion("success")) - assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion("mistake")) - assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion("language")) - } - -} - - diff --git a/src/test/kotlin/other/PalindromeTest.kt b/src/test/kotlin/other/PalindromeTest.kt new file mode 100644 index 00000000..e89c85c4 --- /dev/null +++ b/src/test/kotlin/other/PalindromeTest.kt @@ -0,0 +1,39 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.* + +internal class PalindromeTest { + + @Test + fun test_empty_string() { + val text1 = "" + assertEquals(Palindrome(text1).isYes(), true) + } + + @Test + fun test_one_length() { + val text1 = "a" + assertEquals(Palindrome(text1).isYes(), true) + } + + @Test + fun test_is_palindrome() { + val text1 = "tenet" + assertEquals(Palindrome(text1).isYes(), true) + + val text2 = "friend" + assertEquals(Palindrome(text2).isYes(), false) + } + + @Test + fun test_is_not_palindrome() { + val text1 = "white" + assertEquals(Palindrome(text1).isNot(), true) + + val text2 = "tenet" + assertEquals(Palindrome(text2).isNot(), false) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/ParenthesisCheckAlgorithmTest.kt b/src/test/kotlin/other/ParenthesisCheckAlgorithmTest.kt deleted file mode 100644 index 2dd502c8..00000000 --- a/src/test/kotlin/other/ParenthesisCheckAlgorithmTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class ParenthesisCheckAlgorithmTest { - - private val parenthesisCheckAlgorithm = ParenthesisCheckAlgorithm() - - @Test - fun `test success`() { - // the correct C program - assertEquals(true, parenthesisCheckAlgorithm.check(""" - void main() { - printf("Hello, World!"); - } - """)) - assertEquals(true, parenthesisCheckAlgorithm.check("")) - assertEquals(true, parenthesisCheckAlgorithm.check("()")) - assertEquals(true, parenthesisCheckAlgorithm.check("{}")) - assertEquals(true, parenthesisCheckAlgorithm.check("[]")) - assertEquals(true, parenthesisCheckAlgorithm.check("(([[]]))[[]]")) - assertEquals(true, parenthesisCheckAlgorithm.check("[[[[((()))]]]]{}{}{}")) - assertEquals(true, parenthesisCheckAlgorithm.check("(())()()[][]{{()}}{}")) - } - - @Test - fun `test failed`() { - // the failed C program - assertEquals(false, parenthesisCheckAlgorithm.check(""" - void main({ - printf("Hello, World!"; - } - """)) - assertEquals(false, parenthesisCheckAlgorithm.check("(")) - assertEquals(false, parenthesisCheckAlgorithm.check(")")) - assertEquals(false, parenthesisCheckAlgorithm.check("{")) - assertEquals(false, parenthesisCheckAlgorithm.check("}")) - assertEquals(false, parenthesisCheckAlgorithm.check("[")) - assertEquals(false, parenthesisCheckAlgorithm.check("]")) - assertEquals(false, parenthesisCheckAlgorithm.check("[](){{}")) - assertEquals(false, parenthesisCheckAlgorithm.check("[[[]]]{}{})")) - assertEquals(false, parenthesisCheckAlgorithm.check("{{{}}}({[}]))[]")) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/ParenthesisCheckTest.kt b/src/test/kotlin/other/ParenthesisCheckTest.kt new file mode 100644 index 00000000..26158875 --- /dev/null +++ b/src/test/kotlin/other/ParenthesisCheckTest.kt @@ -0,0 +1,44 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +internal class ParenthesisCheckTest { + + private val parenthesisCheck = ParenthesisCheck() + + @Test + fun test_default_c_program() { + Assertions.assertEquals(true, parenthesisCheck.check()) + } + + @Test + fun test_failed_c_program() { + val failCode = """ + void main({ + printf("Hello, World!"; + } + """.trimIndent() + Assertions.assertEquals(false, parenthesisCheck.check(failCode)) + } + + @Test + fun test_statement_1() { + val statement = "(([[]])}".trimIndent() + Assertions.assertEquals(false, parenthesisCheck.check(statement)) + } + + @Test + fun test_statement_2() { + val statement = "(([[()]])){}{}()".trimIndent() + Assertions.assertEquals(true, parenthesisCheck.check(statement)) + } + + @Test + fun test_statement_3() { + val statement = "(([[()]])){}{}([)".trimIndent() + Assertions.assertEquals(false, parenthesisCheck.check(statement)) + } + + +} \ No newline at end of file diff --git a/src/test/kotlin/other/ReverseArrayAlgorithmTest.kt b/src/test/kotlin/other/ReverseArrayAlgorithmTest.kt deleted file mode 100644 index 5e8b3c2c..00000000 --- a/src/test/kotlin/other/ReverseArrayAlgorithmTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package other - -import org.junit.Test -import junit.framework.TestCase.assertEquals - -internal class ReverseArrayAlgorithmTest { - - private val reverseArrayAlgorithm = ReverseArrayAlgorithm() - - @Test - fun `test numbers`() { - val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - - reverseArrayAlgorithm.compute(array) - - assertEquals(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1), array.toList()) - } - - @Test - fun `test strings`() { - val array = arrayOf("Twillight Sparkle", "Pinky Pie", "Apple Jack", "Rainbow Dash", "Fluttershy", "Rarity") - - reverseArrayAlgorithm.compute(array) - - assertEquals(listOf("Rarity", "Fluttershy", "Rainbow Dash", "Apple Jack", "Pinky Pie", "Twillight Sparkle"), array.toList()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/ReverseArrayTest.kt b/src/test/kotlin/other/ReverseArrayTest.kt new file mode 100644 index 00000000..edb526a6 --- /dev/null +++ b/src/test/kotlin/other/ReverseArrayTest.kt @@ -0,0 +1,23 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class ReverseArrayTest { + + @Test + fun test_numbers() { + val reverseArray = ReverseArray() + val actual = reverseArray.compute(arrayOf(1, 2, 3)).toList() + val expected = arrayOf(3, 2, 1).toList() + assertEquals(expected, actual) + } + + @Test + fun test_strings() { + val reverseArray = ReverseArray() + val actual = reverseArray.compute(arrayOf("Twillight Sparkle", "Pinky Pie", "Apple Jack")).toList() + val expected = arrayOf("Apple Jack", "Pinky Pie", "Twillight Sparkle").toList() + assertEquals(expected, actual) + } +} \ No newline at end of file diff --git a/src/test/kotlin/other/SieveOfEratosthenesAlgorithmTest.kt b/src/test/kotlin/other/SieveOfEratosthenesAlgorithmTest.kt deleted file mode 100644 index 7adc51d4..00000000 --- a/src/test/kotlin/other/SieveOfEratosthenesAlgorithmTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class SieveOfEratosthenesAlgorithmTest { - - private val eratosthenesAlgorithm = SieveOfEratosthenesAlgorithm() - - @Test - fun tes() { - assertEquals(emptyList(), eratosthenesAlgorithm.compute(1)) - assertEquals(listOf(2, 3, 5, 7), eratosthenesAlgorithm.compute(10)) - assertEquals(listOf(2, 3, 5, 7, 11, 13, 17, 19), eratosthenesAlgorithm.compute(20)) - assertEquals(listOf(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37), eratosthenesAlgorithm.compute(40)) - assertEquals( - listOf(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101), - eratosthenesAlgorithm.compute(102) - ) - assertEquals( - listOf( - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, - 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293 - ), - eratosthenesAlgorithm.compute(300) - ) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/SieveOfEratosthenesTest.kt b/src/test/kotlin/other/SieveOfEratosthenesTest.kt new file mode 100644 index 00000000..1bf0c620 --- /dev/null +++ b/src/test/kotlin/other/SieveOfEratosthenesTest.kt @@ -0,0 +1,24 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +internal class SieveOfEratosthenesTest { + + @Test + fun test_success() { + val eratosthenes = SieveOfEratosthenes() + val actual = eratosthenes.compute(10) + val expected = listOf(2, 3, 5, 7) + Assertions.assertEquals(expected, actual) + } + + @Test + fun test_fail() { + val eratosthenes = SieveOfEratosthenes() + val actual = eratosthenes.compute(5) + val expected = listOf(4) + Assertions.assertNotEquals(expected, actual) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/other/SqrtTest.kt b/src/test/kotlin/other/SqrtTest.kt index 99ad71b1..499bbe66 100644 --- a/src/test/kotlin/other/SqrtTest.kt +++ b/src/test/kotlin/other/SqrtTest.kt @@ -1,16 +1,16 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class SqrtTest { @Test fun test() { val sqrt = Sqrt() - assertEquals(3.0, sqrt.compute(9.0), 0.0) - assertEquals(2.0, sqrt.compute(4.0), 0.0) - assertEquals(6.0, sqrt.compute(36.0), 0.0) + assertEquals(3.0, sqrt.compute(9.0)) + assertEquals(2.0, sqrt.compute(4.0)) + assertEquals(6.0, sqrt.compute(36.0)) } } \ No newline at end of file diff --git a/src/test/kotlin/other/StringEqualsHashAlgorithmTest.kt b/src/test/kotlin/other/StringEqualsHashTest.kt similarity index 50% rename from src/test/kotlin/other/StringEqualsHashAlgorithmTest.kt rename to src/test/kotlin/other/StringEqualsHashTest.kt index d10f42b2..39d6ede8 100644 --- a/src/test/kotlin/other/StringEqualsHashAlgorithmTest.kt +++ b/src/test/kotlin/other/StringEqualsHashTest.kt @@ -1,18 +1,18 @@ package other import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions -internal class StringEqualsHashAlgorithmTest { +internal class StringEqualsHashTest { - private val stringEqualsHashAlgorithm = StringEqualsHashAlgorithm() + private val stringEqualsHash = StringEqualsHash() @Test fun test_two_the_same_strings() { val str1 = "Twilight Sparkle" val str2 = "Twilight Sparkle" - assertEquals(true, stringEqualsHashAlgorithm.equals(str1, str2)) + Assertions.assertEquals(true, stringEqualsHash.equals(str1, str2)) } @Test @@ -20,7 +20,7 @@ internal class StringEqualsHashAlgorithmTest { val greeting = "How are you?" val pattern = "Happy birthday to me!" - assertEquals(false, stringEqualsHashAlgorithm.equals(greeting, pattern)) + Assertions.assertEquals(false, stringEqualsHash.equals(greeting, pattern)) } } \ No newline at end of file diff --git a/src/test/kotlin/other/SwapAlgorithmTest.kt b/src/test/kotlin/other/SwapAlgorithmTest.kt deleted file mode 100644 index d410c58a..00000000 --- a/src/test/kotlin/other/SwapAlgorithmTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -package other - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class SwapAlgorithmTest { - - private val swapAlgorithm = SwapAlgorithm() - - @Test - fun test_list() { - val list = mutableListOf(1, 2, 3, 4, 5, 6) - - swapAlgorithm.swap(list, 0, 5) - swapAlgorithm.swap(list, 1, 4) - swapAlgorithm.swap(list, 2, 3) - - assertEquals(listOf(6, 5, 4, 3, 2, 1), list) - } - - @Test - fun test_array() { - val array = arrayOf(1, 2, 3, 4, 5, 6) - - swapAlgorithm.swap(array, 0, 5) - swapAlgorithm.swap(array, 1, 4) - swapAlgorithm.swap(array, 2, 3) - - assertEquals(listOf(6, 5, 4, 3, 2, 1), array.toList()) - } - - @Test - fun test_list_kotlin() { - val list = mutableListOf(1, 2, 3, 4, 5, 6) - - swapAlgorithm.swapKotlin(list, 0, 5) - swapAlgorithm.swapKotlin(list, 1, 4) - swapAlgorithm.swapKotlin(list, 2, 3) - - assertEquals(listOf(6, 5, 4, 3, 2, 1), list) - } - - @Test - fun test_array_kotlin() { - val array = arrayOf(1, 2, 3, 4, 5, 6) - - swapAlgorithm.swapKotlin(array, 0, 5) - swapAlgorithm.swapKotlin(array, 1, 4) - swapAlgorithm.swapKotlin(array, 2, 3) - - assertEquals(listOf(6, 5, 4, 3, 2, 1), array.toList()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/other/SwapTest.kt b/src/test/kotlin/other/SwapTest.kt new file mode 100644 index 00000000..df76b66c --- /dev/null +++ b/src/test/kotlin/other/SwapTest.kt @@ -0,0 +1,49 @@ +package other + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class SwapTest { + + private val swap = Swap() + + @Test + fun test_list() { + val list = mutableListOf(1, 2) + val expected1 = listOf(1, 2) + assertEquals(expected1, list) + swap.swap(list, 0, 1) + val expected2 = listOf(2, 1) + assertEquals(expected2, list) + } + + @Test + fun test_array() { + val array = arrayOf(1, 2) + val expected1 = listOf(1, 2) + assertEquals(expected1, array.toList()) + swap.swap(array, 0, 1) + val expected2 = listOf(2, 1) + assertEquals(expected2, array.toList()) + } + + @Test + fun test_list_kotlin() { + val list = mutableListOf(1, 2) + val expected1 = listOf(1, 2) + assertEquals(expected1, list) + swap.swapKotlin(list, 0, 1) + val expected2 = listOf(2, 1) + assertEquals(expected2, list) + } + + @Test + fun test_array_kotlin() { + val array = arrayOf(1, 2) + val expected1 = listOf(1, 2) + assertEquals(expected1, array.toList()) + swap.swapKotlin(array, 0, 1) + val expected2 = listOf(2, 1) + assertEquals(expected2, array.toList()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/search/BinarySearchRecursiveTest.kt b/src/test/kotlin/search/BinarySearchRecursiveTest.kt new file mode 100644 index 00000000..d227b20a --- /dev/null +++ b/src/test/kotlin/search/BinarySearchRecursiveTest.kt @@ -0,0 +1,34 @@ +package search + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +internal class BinarySearchRecursiveTest { + + private val searchAlgo = BinarySearchRecursive() + + @Test + fun test_existed_element() { + val array = arrayOf(1, 2, 3, 4, 5) + Assertions.assertEquals(true, searchAlgo.exists(array, 4)) + } + + @Test + fun test_start_element() { + val array = arrayOf(1, 11, 111, 1111, 11111) + Assertions.assertEquals(true, searchAlgo.exists(array, 1)) + } + + @Test + fun test_last_element() { + val array = arrayOf(0, 5, 10) + Assertions.assertEquals(true, searchAlgo.exists(array, 10)) + } + + @Test + fun test_none_existed_element() { + val array = arrayOf(0, 5, 10, 15, 20, 25) + Assertions.assertEquals(false, searchAlgo.exists(array, 100)) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/search/BinarySearchTest.kt b/src/test/kotlin/search/BinarySearchTest.kt index 994676f6..c9e72abe 100644 --- a/src/test/kotlin/search/BinarySearchTest.kt +++ b/src/test/kotlin/search/BinarySearchTest.kt @@ -1,55 +1,50 @@ package search import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class BinarySearchTest { - private val searchAlgo = BinarySearch() + private val searchAlgo = BinarySearch() @Test - fun `test search`() { - val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - - assertEquals(-1, searchAlgo.search(emptyArray(), 0)) - assertEquals(-1, searchAlgo.search(array, 0)) - assertEquals(-1, searchAlgo.search(array, 11)) - assertEquals(0, searchAlgo.search(array, 1)) - assertEquals(2, searchAlgo.search(array, 3)) - assertEquals(4, searchAlgo.search(array, 5)) - assertEquals(6, searchAlgo.search(array, 7)) - assertEquals(8, searchAlgo.search(array, 9)) - assertEquals(9, searchAlgo.search(array, 10)) - - assertEquals(-1, searchAlgo.searchRecursive(emptyArray(), 0)) - assertEquals(-1, searchAlgo.searchRecursive(array, 0)) - assertEquals(-1, searchAlgo.searchRecursive(array, 11)) - assertEquals(0, searchAlgo.searchRecursive(array, 1)) - assertEquals(2, searchAlgo.searchRecursive(array, 3)) - assertEquals(4, searchAlgo.searchRecursive(array, 5)) - assertEquals(6, searchAlgo.searchRecursive(array, 7)) - assertEquals(8, searchAlgo.searchRecursive(array, 9)) - assertEquals(9, searchAlgo.searchRecursive(array, 10)) + fun test_existed_element() { + val array = arrayOf(1, 2, 3, 4, 5) + assertEquals(true, searchAlgo.exists(array, 4)) } @Test - fun `test bounds`() { - val array = arrayOf(1, 2, 3, 4, 6, 7, 8, 10) - assertEquals(-1, searchAlgo.leftBound(array, 0)) - assertEquals(-1, searchAlgo.leftBound(array, 1)) + fun test_start_element() { + val array = arrayOf(1, 11, 111, 1111, 11111) + assertEquals(true, searchAlgo.exists(array, 1)) + } + + @Test + fun test_last_element() { + val array = arrayOf(0, 5, 10) + assertEquals(true, searchAlgo.exists(array, 10)) + } + + @Test + fun test_none_existed_element() { + val array = arrayOf(0, 5, 10, 15, 20, 25) + assertEquals(false, searchAlgo.exists(array, 100)) + } + + @Test + fun test_left_bound() { + val array = arrayOf(1, 2, 4, 5) assertEquals(1, searchAlgo.leftBound(array, 3)) - assertEquals(3, searchAlgo.leftBound(array, 5)) - assertEquals(6, searchAlgo.leftBound(array, 10)) - assertEquals(7, searchAlgo.leftBound(array, 11)) - assertEquals(7, searchAlgo.leftBound(array, 100)) - - assertEquals(0, searchAlgo.rightBound(array, 0)) - assertEquals(0, searchAlgo.rightBound(array, 1)) - assertEquals(2, searchAlgo.rightBound(array, 3)) - assertEquals(4, searchAlgo.rightBound(array, 5)) - assertEquals(7, searchAlgo.rightBound(array, 10)) - assertEquals(8, searchAlgo.rightBound(array, 11)) - assertEquals(8, searchAlgo.rightBound(array, 100)) + assertEquals(1, searchAlgo.leftBound(array, 4)) + assertEquals(2, searchAlgo.leftBound(array, 5)) + } + + @Test + fun test_right_bound() { + val array = arrayOf(10, 20, 21, 22, 23) + assertEquals(0, searchAlgo.rightBound(array, 3)) + assertEquals(1, searchAlgo.rightBound(array, 15)) + assertEquals(2, searchAlgo.rightBound(array, 21)) } } \ No newline at end of file diff --git a/src/test/kotlin/search/LinearSearchTest.kt b/src/test/kotlin/search/LinearSearchTest.kt index 3d3e16ea..8c56d125 100644 --- a/src/test/kotlin/search/LinearSearchTest.kt +++ b/src/test/kotlin/search/LinearSearchTest.kt @@ -1,26 +1,27 @@ package search import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions internal class LinearSearchTest { - @Test - fun test() { - val searchAlgo = LinearSearch() - - val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + private val searchAlgo = LinearSearch() - assertEquals(-1, searchAlgo.search(emptyArray(), 0)) - assertEquals(-1, searchAlgo.search(array, 0)) - assertEquals(-1, searchAlgo.search(array, 11)) - assertEquals(0, searchAlgo.search(array, 1)) - assertEquals(2, searchAlgo.search(array, 3)) - assertEquals(4, searchAlgo.search(array, 5)) - assertEquals(6, searchAlgo.search(array, 7)) - assertEquals(8, searchAlgo.search(array, 9)) - assertEquals(9, searchAlgo.search(array, 10)) + @Test + fun test_existed_element() { + val array = arrayOf(1, 2, 3, 4, 5) + Assertions.assertEquals(true, searchAlgo.exists(array, 4)) } + @Test + fun test_start_element() { + val array = arrayOf(1, 11, 111, 1111, 11111) + Assertions.assertEquals(true, searchAlgo.exists(array, 1)) + } + @Test + fun test_last_element() { + val array = arrayOf(0, 5, 10) + Assertions.assertEquals(true, searchAlgo.exists(array, 10)) + } } \ No newline at end of file diff --git a/src/test/kotlin/sorting/BubbleSortImprovedTest.kt b/src/test/kotlin/sorting/BubbleSortImprovedTest.kt new file mode 100644 index 00000000..ec87fe67 --- /dev/null +++ b/src/test/kotlin/sorting/BubbleSortImprovedTest.kt @@ -0,0 +1,63 @@ +package sorting + +import org.junit.Test +import org.junit.jupiter.api.Assertions +import kotlin.random.Random + +class BubbleSortImprovedTest { + + @Test + fun test_reversed_array() { + val expected = TestUtils.list(1000) + + val actual = expected.reversed().toTypedArray() + actual.bubbleSortImproved() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(500) + + val expected = actual.sorted() + + actual.bubbleSortImproved() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1000) + + val actual = expected.copyOf() + actual.shuffle() + actual.bubbleSortImproved() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1000) + + val expected = actual.toList() + + actual.bubbleSortImproved() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(5000) + + val expected = actual.sorted() + + actual.bubbleSortImproved() + + Assertions.assertEquals(expected, actual) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/sorting/BubbleSortTest.kt b/src/test/kotlin/sorting/BubbleSortTest.kt index 35a3fc26..660fb9a7 100644 --- a/src/test/kotlin/sorting/BubbleSortTest.kt +++ b/src/test/kotlin/sorting/BubbleSortTest.kt @@ -1,59 +1,63 @@ package sorting import org.junit.Test -import org.junit.Assert.assertArrayEquals -import kotlin.random.Random +import org.junit.jupiter.api.Assertions internal class BubbleSortTest { - private val bubbleSort = BubbleSort() + @Test + fun test_reversed_array() { + val expected = TestUtils.list(1000) + + val actual = expected.reversed().toTypedArray() + actual.bubbleSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(500) + + val expected = actual.sorted() + + actual.bubbleSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1000) + + val actual = expected.copyOf() + actual.shuffle() + actual.bubbleSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } @Test - fun `test sort`() { - val expected1 = Array(1000) { it } - val actual1 = expected1.reversedArray() - bubbleSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1000) { Random.nextInt(1000) } - val expected2 = actual2.sortedArray() - bubbleSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - bubbleSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1000) { it } - val actual4 = expected3.copyOf() - bubbleSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1000) + + val expected = actual.toList() + + actual.bubbleSort() + + Assertions.assertEquals(expected, actual.toList()) } @Test - fun `test sort improved`() { - val expected1 = Array(1000) { it } - val actual1 = expected1.reversedArray() - bubbleSort.sortImproved(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1000) { Random.nextInt(1000) } - val expected2 = actual2.sortedArray() - bubbleSort.sortImproved(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - bubbleSort.sortImproved(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1000) { it } - val actual4 = expected3.copyOf() - bubbleSort.sortImproved(actual3) - assertArrayEquals(expected4, actual4) + fun test_random_list() { + val actual = TestUtils.mutableRandomList(5000) + + val expected = actual.sorted() + + actual.bubbleSort() + + Assertions.assertEquals(expected, actual) } + } \ No newline at end of file diff --git a/src/test/kotlin/sorting/CountSortTest.kt b/src/test/kotlin/sorting/CountSortTest.kt new file mode 100644 index 00000000..5ce4c1b1 --- /dev/null +++ b/src/test/kotlin/sorting/CountSortTest.kt @@ -0,0 +1,38 @@ +package sorting + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +class CountSortTest { + + @Test + fun test_numbers_from_zero_to_five() { + val numbers = arrayOf(5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 4, 3, 4, 3, 3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 5, 3, 2, 2, 1, 1, 0) + val expected = numbers.sorted() + + numbers.countSort(0, 5) + + Assertions.assertEquals(expected, numbers.toList()) + } + + @Test + fun test_numbers_from_one_to_ten() { + val numbers = arrayOf(9, 9, 9, 10, 10, 5, 4, 4, 4, 1, 1, 1, 3, 3, 3) + val expected = numbers.sorted() + + numbers.countSort(1, 10) + + Assertions.assertEquals(expected, numbers.toList()) + } + + @Test + fun test_numbers_from_one_to_thousand() { + val numbers = arrayOf(1000, 1000, 555, 555, 555, 333, 222, 222, 1, 1, 1, 222, 222, 555, 587, 587, 1, 587, 1000, 1000, 1000, 6, 7, 6, 7, 7, 7, 6, 1, 1, 222, 555, 587, 3, 3, 3, 1, 3, 3, 6, 6, 49, 587, 587, 49, 49, 49, 100, 100, 1000, 100, 1000, 555, 222) + val expected = numbers.sorted() + + numbers.countSort(1, 1000) + + Assertions.assertEquals(expected, numbers.toList()) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/sorting/CountingSortTest.kt b/src/test/kotlin/sorting/CountingSortTest.kt deleted file mode 100644 index 7ec1997d..00000000 --- a/src/test/kotlin/sorting/CountingSortTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package sorting - -import org.junit.Test -import org.junit.Assert.assertArrayEquals - -class CountingSortTest { - - @Test - fun test() { - val countingSort = CountingSort() - - val actual1 = arrayOf( - 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 4, 3, 4, 3, 3, 0, - 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 5, 3, 2, 2, 1, 1, 0 - ) - val expected1 = actual1.sortedArray() - countingSort.sort(actual1,0, 5) - assertArrayEquals(expected1, actual1) - - val actual2 = arrayOf(9, 9, 9, 10, 10, 5, 4, 4, 4, 1, 1, 1, 3, 3, 3) - val expected2 = actual2.sortedArray() - countingSort.sort(actual2, 1, 10) - assertArrayEquals(expected2, actual2) - - val actual3 = arrayOf( - 1000, 1000, 555, 555, 555, 333, 222, 222, 1, 1, 1, 222, 222, 555, 587, 587, 1, 587, - 1000, 1000, 1000, 6, 7, 6, 7, 7, 7, 6, 1, 1, 222, 555, 587, 3, 3, 3, 1, 3, 3, 6, 6, - 49, 587, 587, 49, 49, 49, 100, 100, 1000, 100, 1000, 555, 222 - ) - val expected3 = actual3.sortedArray() - countingSort.sort(actual3, 1, 1000) - assertArrayEquals(expected3, actual3) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/sorting/InsertionSortTest.kt b/src/test/kotlin/sorting/InsertionSortTest.kt index 09bd315a..121d85ae 100644 --- a/src/test/kotlin/sorting/InsertionSortTest.kt +++ b/src/test/kotlin/sorting/InsertionSortTest.kt @@ -1,35 +1,63 @@ package sorting import org.junit.Test -import org.junit.Assert.assertArrayEquals +import org.junit.jupiter.api.Assertions import kotlin.random.Random internal class InsertionSortTest { @Test - fun `test sort`() { - val insertionSort = InsertionSort() - - val expected1 = Array(1000) { it } - val actual1 = expected1.reversedArray() - insertionSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1000) { Random.nextInt(1000) } - val expected2 = actual2.sortedArray() - insertionSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - insertionSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1000) { it } - val actual4 = expected3.copyOf() - insertionSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_reversed_array() { + val expected = TestUtils.list(1000) + + val actual = expected.reversed().toTypedArray() + actual.insertionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(500) + + val expected = actual.sorted() + + actual.insertionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1000) + + val actual = expected.copyOf() + actual.shuffle() + actual.insertionSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1000) + + val expected = actual.toList() + + actual.insertionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(5000) + + val expected = actual.sorted() + + actual.insertionSort() + + Assertions.assertEquals(expected, actual) } } \ No newline at end of file diff --git a/src/test/kotlin/sorting/MergeSortRecursiveTest.kt b/src/test/kotlin/sorting/MergeSortRecursiveTest.kt new file mode 100644 index 00000000..9829c7bf --- /dev/null +++ b/src/test/kotlin/sorting/MergeSortRecursiveTest.kt @@ -0,0 +1,62 @@ +package sorting + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +class MergeSortRecursiveTest { + + @Test + fun test_reversed_array() { + val expected = TestUtils.list(100000) + + val actual = expected.reversed().toTypedArray() + actual.mergeSortRecursive() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(50000) + + val expected = actual.sorted() + + actual.mergeSortRecursive() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(100000) + + val actual = expected.copyOf() + actual.shuffle() + actual.mergeSortRecursive() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(100000) + + val expected = actual.toList() + + actual.mergeSortRecursive() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(500000) + + val expected = actual.sorted() + + actual.mergeSortRecursive() + + Assertions.assertEquals(expected, actual) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/sorting/MergeSortTest.kt b/src/test/kotlin/sorting/MergeSortTest.kt index da4ac84c..b1d624c9 100644 --- a/src/test/kotlin/sorting/MergeSortTest.kt +++ b/src/test/kotlin/sorting/MergeSortTest.kt @@ -1,59 +1,62 @@ package sorting import org.junit.Test -import kotlin.random.Random -import org.junit.Assert.assertArrayEquals +import org.junit.jupiter.api.Assertions class MergeSortTest { - private val mergeSort = MergeSort() + @Test + fun test_reversed_array() { + val expected = TestUtils.list(100000) + + val actual = expected.reversed().toTypedArray() + actual.mergeSort() + + Assertions.assertEquals(expected, actual.toList()) + } @Test - fun `test sort`() { - val expected1 = Array(1_000_000) { it } - val actual1 = expected1.reversedArray() - mergeSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) } - val expected2 = actual2.sortedArray() - mergeSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1_000_000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - mergeSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1_000_000) { it } - val actual4 = expected3.copyOf() - mergeSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_random_array() { + val actual = TestUtils.randomArray(50000) + + val expected = actual.sorted() + + actual.mergeSort() + + Assertions.assertEquals(expected, actual.toList()) } @Test - fun `test sort recursive`() { - val expected1 = Array(1_000_000) { it } - val actual1 = expected1.reversedArray() - mergeSort.sortRecursive(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) } - val expected2 = actual2.sortedArray() - mergeSort.sortRecursive(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1_000_000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - mergeSort.sortRecursive(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1_000_000) { it } - val actual4 = expected3.copyOf() - mergeSort.sortRecursive(actual3) - assertArrayEquals(expected4, actual4) + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(100000) + + val actual = expected.copyOf() + actual.shuffle() + actual.mergeSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(100000) + + val expected = actual.toList() + + actual.mergeSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(500000) + + val expected = actual.sorted() + + actual.mergeSort() + + Assertions.assertEquals(expected, actual) } } \ No newline at end of file diff --git a/src/test/kotlin/sorting/QuickSortTest.kt b/src/test/kotlin/sorting/QuickSortTest.kt index 166c02c8..5f84eb36 100644 --- a/src/test/kotlin/sorting/QuickSortTest.kt +++ b/src/test/kotlin/sorting/QuickSortTest.kt @@ -1,35 +1,62 @@ package sorting import org.junit.Test +import org.junit.jupiter.api.Assertions import kotlin.random.Random -import org.junit.Assert.assertArrayEquals class QuickSortTest { @Test - fun `test sort`() { - val quickSort = QuickSort() - - val expected1 = Array(1_000_000) { it } - val actual1 = expected1.reversedArray() - quickSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) } - val expected2 = actual2.sortedArray() - quickSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1_000_000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - quickSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1_000_000) { it } - val actual4 = expected3.copyOf() - quickSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_reversed_array() { + val expected = TestUtils.list(1_000_000) + + val actual = expected.reversed().toTypedArray() + actual.quickSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(5_000_000) + + val expected = actual.sorted() + + actual.quickSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1_000_000) + + val actual = expected.copyOf() + actual.shuffle() + actual.quickSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1_000_000) + + val expected = actual.toList() + + actual.quickSort() + + Assertions.assertEquals(expected, actual.toList()) } + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(1_000_000) + + val expected = actual.sorted() + + actual.quickSort() + + Assertions.assertEquals(expected, actual) + } } \ No newline at end of file diff --git a/src/test/kotlin/sorting/RadixSort.kt b/src/test/kotlin/sorting/RadixSort.kt new file mode 100644 index 00000000..d3289626 --- /dev/null +++ b/src/test/kotlin/sorting/RadixSort.kt @@ -0,0 +1,63 @@ +package sorting + +import org.junit.Test +import org.junit.jupiter.api.Assertions +import kotlin.random.Random + +class RadixSortTest { + + @Test + fun test_reversed_array() { + val expected = TestUtils.list(1_000_000) + + val actual = expected.reversed().toTypedArray() + actual.radixSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(1_000_000) + + val expected = actual.sorted() + + actual.radixSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1_000_000) + + val actual = expected.copyOf() + actual.shuffle() + actual.radixSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1_000_000) + + val expected = actual.toList() + + actual.radixSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(1_000_000) + + val expected = actual.sorted() + + actual.radixSort() + + Assertions.assertEquals(expected, actual) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/sorting/RadixSortTest.kt b/src/test/kotlin/sorting/RadixSortTest.kt deleted file mode 100644 index 0c7fef49..00000000 --- a/src/test/kotlin/sorting/RadixSortTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package sorting - -import org.junit.Test -import org.junit.Assert.assertArrayEquals -import kotlin.random.Random - -class RadixSortTest { - - @Test - fun test() { - val radixSort = RadixSort() - - val expected1 = Array(1_000_000) { it } - val actual1 = expected1.reversedArray() - radixSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) } - val expected2 = actual2.sortedArray() - radixSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1_000_000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - radixSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1_000_000) { it } - val actual4 = expected3.copyOf() - radixSort.sort(actual3) - assertArrayEquals(expected4, actual4) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/sorting/SelectionSortTest.kt b/src/test/kotlin/sorting/SelectionSortTest.kt index 0bc36d33..1bbdba1c 100644 --- a/src/test/kotlin/sorting/SelectionSortTest.kt +++ b/src/test/kotlin/sorting/SelectionSortTest.kt @@ -1,35 +1,63 @@ package sorting import org.junit.Test -import org.junit.Assert.assertArrayEquals +import org.junit.jupiter.api.Assertions import kotlin.random.Random class SelectionSortTest { @Test - fun test() { - val selectionSort = SelectionSort() - - val expected1 = Array(1000) { it } - val actual1 = expected1.reversedArray() - selectionSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1000) { Random.nextInt(1000) } - val expected2 = actual2.sortedArray() - selectionSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - selectionSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1000) { it } - val actual4 = expected3.copyOf() - selectionSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_reversed_array() { + val expected = TestUtils.list(1000) + + val actual = expected.reversed().toTypedArray() + actual.selectionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(500) + + val expected = actual.sorted() + + actual.selectionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(1000) + + val actual = expected.copyOf() + actual.shuffle() + actual.selectionSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(1000) + + val expected = actual.toList() + + actual.selectionSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_list() { + val actual = TestUtils.mutableRandomList(5000) + + val expected = actual.sorted() + + actual.selectionSort() + + Assertions.assertEquals(expected, actual) } } \ No newline at end of file diff --git a/src/test/kotlin/sorting/TimSortTest.kt b/src/test/kotlin/sorting/TimSortTest.kt index 31d3ded3..f82bcdc2 100644 --- a/src/test/kotlin/sorting/TimSortTest.kt +++ b/src/test/kotlin/sorting/TimSortTest.kt @@ -1,35 +1,51 @@ package sorting import org.junit.Test -import kotlin.random.Random -import org.junit.Assert.assertArrayEquals +import org.junit.jupiter.api.Assertions class TimSortTest { @Test - fun `test sort`() { - val timSort = TimSort() - - val expected1 = Array(1_000_000) { it } - val actual1 = expected1.reversedArray() - timSort.sort(actual1) - assertArrayEquals(expected1, actual1) - - val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) } - val expected2 = actual2.sortedArray() - timSort.sort(actual2) - assertArrayEquals(expected2, actual2) - - val expected3 = Array(1_000_000) { it } - val actual3 = expected3.copyOf() - actual3.shuffle() - timSort.sort(actual3) - assertArrayEquals(expected3, actual3) - - val expected4 = Array(1_000_000) { it } - val actual4 = expected3.copyOf() - timSort.sort(actual3) - assertArrayEquals(expected4, actual4) + fun test_reversed_array() { + val expected = TestUtils.list(100000) + + val actual = expected.reversed().toTypedArray() + actual.timSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_random_array() { + val actual = TestUtils.randomArray(50000) + + val expected = actual.sorted() + + actual.timSort() + + Assertions.assertEquals(expected, actual.toList()) + } + + @Test + fun test_shuffled_array() { + val expected = TestUtils.sortedArray(100000) + + val actual = expected.copyOf() + actual.shuffle() + actual.timSort() + + Assertions.assertEquals(expected.toList(), actual.toList()) + } + + @Test + fun test_sorted_array() { + val actual = TestUtils.sortedArray(100000) + + val expected = actual.toList() + + actual.timSort() + + Assertions.assertEquals(expected, actual.toList()) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/ArrayListQueueTest.kt b/src/test/kotlin/structures/ArrayListQueueTest.kt new file mode 100644 index 00000000..eb4962c2 --- /dev/null +++ b/src/test/kotlin/structures/ArrayListQueueTest.kt @@ -0,0 +1,75 @@ +package structures + +import org.junit.Test +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import java.lang.IllegalStateException + +internal class ArrayListQueueTest { + + private val queue : Queue = Queue.ArrayListQueue() + + @BeforeEach + fun clear() = queue.clear() + + @Test + fun test_is_empty() { + Assertions.assertEquals(true, queue.isEmpty()) + + queue.offer(1) + queue.offer(2) + + Assertions.assertEquals(false, queue.isEmpty()) + + } + + @Test + fun test_poll() { + queue.offer(1) + Assertions.assertEquals(1, queue.poll()) + Assertions.assertEquals(null, queue.poll()) + } + + @Test + fun test_peek() { + queue.offer(5) + Assertions.assertEquals(5, queue.peek()) + queue.clear() + Assertions.assertEquals(null, queue.peek()) + } + + @Test + fun test_remove() { + queue.offer(100) + Assertions.assertEquals(100, queue.remove()) + + val exception = Assertions.assertThrows(IllegalStateException::class.java) { + queue.remove() + } + Assertions.assertEquals("queue is empty!", exception.message) + } + + @Test + fun test_element() { + queue.offer(100) + Assertions.assertEquals(100, queue.element()) + + queue.clear() + + val exception = Assertions.assertThrows(IllegalStateException::class.java) { + queue.element() + } + Assertions.assertEquals("queue is empty!", exception.message) + } + + @Test + fun test_remove_object() { + queue.offer(10) + queue.offer(20) + queue.offer(1000) + + Assertions.assertEquals(true, queue.remove(20)) + Assertions.assertEquals(false, queue.remove(34)) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/structures/ArrayListStackTest.kt b/src/test/kotlin/structures/ArrayListStackTest.kt new file mode 100644 index 00000000..5b435df8 --- /dev/null +++ b/src/test/kotlin/structures/ArrayListStackTest.kt @@ -0,0 +1,33 @@ +package structures + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +class ArrayListStackTest { + + private val arrayListStack = Stack.ArrayListStack() + + @Test + fun test_push() { + arrayListStack.push(10) + Assertions.assertEquals(10, arrayListStack.peek()) + } + + @Test + fun test_pop() { + arrayListStack.push(20) + Assertions.assertEquals(20, arrayListStack.pop()) + } + + @Test + fun test_is_empty() { + arrayListStack.clear() + Assertions.assertEquals(true, arrayListStack.isEmpty()) + } + + @Test + fun test_is_not_empty() { + arrayListStack.push(20) + Assertions.assertEquals(false, arrayListStack.isEmpty()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/structures/BinaryTreeTest.kt b/src/test/kotlin/structures/BinaryTreeTest.kt index c0656afd..b9a1c9eb 100644 --- a/src/test/kotlin/structures/BinaryTreeTest.kt +++ b/src/test/kotlin/structures/BinaryTreeTest.kt @@ -1,125 +1,73 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class BinaryTreeTest { @Test - fun `test add`() { - val tree = BinaryTree() + fun test_add() { + val tree = BinaryTree() tree.add(5) tree.add(10) tree.add(4) - assertEquals(listOf(5, 4, 10), tree.traverseLevelOrder()) - - tree.add(9) - - assertEquals(listOf(5, 4, 10, 9), tree.traverseLevelOrder()) - - tree.add(1) - - assertEquals(listOf(5, 4, 10, 1, 9), tree.traverseLevelOrder()) - - tree.add(11) - - assertEquals(listOf(5, 4, 10, 1, 9, 11), tree.traverseLevelOrder()) + assertEquals(listOf(4, 5, 10), tree.traverseInOrder().sorted()) } @Test - fun `test remove`() { - val tree = BinaryTree() + fun test_remove() { + val tree = BinaryTree() tree.add(10) tree.add(20) tree.add(30) - assertEquals(listOf(10, 20, 30), tree.traverseLevelOrder()) - assertEquals(false, tree.isEmpty) + assertEquals(listOf(10, 20, 30), tree.traverseInOrder().sorted()) tree.remove(20) - assertEquals(listOf(10, 30), tree.traverseLevelOrder()) - assertEquals(false, tree.isEmpty) + assertEquals(listOf(10, 30), tree.traverseInOrder().sorted()) tree.remove(10) - assertEquals(listOf(30), tree.traverseLevelOrder()) - assertEquals(false, tree.isEmpty) - - tree.remove(30) - - assertEquals(emptyList(), tree.traverseLevelOrder()) - assertEquals(true, tree.isEmpty) + assertEquals(listOf(30), tree.traverseInOrder().sorted()) } @Test - fun `test is empty`() { - val tree = BinaryTree() + fun test_is_empty() { + val tree = BinaryTree() - assertEquals(true, tree.isEmpty) + assertEquals(true, tree.isEmpty()) tree.add(10) - assertEquals(false, tree.isEmpty) - - tree.add(20) - - assertEquals(false, tree.isEmpty) + assertEquals(false, tree.isEmpty()) tree.remove(10) - assertEquals(false, tree.isEmpty) - - tree.remove(20) - - assertEquals(true, tree.isEmpty) + assertEquals(true, tree.isEmpty()) } @Test - fun `test contains`() { - val tree = BinaryTree() + fun test_contains() { + val tree = BinaryTree() - assertEquals(false, tree.contains(5)) - assertEquals(false, tree.contains(3)) - assertEquals(false, tree.contains(7)) + assertEquals(false, tree.contains(10)) tree.add(5) tree.add(3) tree.add(7) - - assertEquals(true, tree.contains(5)) - assertEquals(true, tree.contains(3)) - assertEquals(true, tree.contains(7)) - - assertEquals(false, tree.contains(2)) - assertEquals(false, tree.contains(10)) - tree.add(2) tree.add(10) - assertEquals(true, tree.contains(2)) - assertEquals(true, tree.contains(10)) - - tree.remove(5) - tree.remove(3) - tree.remove(7) - tree.remove(2) - - assertEquals(false, tree.contains(5)) - assertEquals(false, tree.contains(3)) - assertEquals(false, tree.contains(7)) - assertEquals(false, tree.contains(2)) assertEquals(true, tree.contains(10)) } @Test - fun `test traverseInOrder`() { - val tree = BinaryTree() - - assertEquals(emptyList(), tree.traverseInOrder()) + fun test_traverse_in_order() { + val tree = BinaryTree() tree.add(5) tree.add(3) @@ -128,23 +76,11 @@ internal class BinaryTreeTest { tree.add(9) assertEquals(listOf(2, 3, 5, 8, 9), tree.traverseInOrder()) - - tree.add(1) - tree.add(11) - - assertEquals(listOf(1, 2, 3, 5, 8, 9, 11), tree.traverseInOrder()) - - tree.add(20) - tree.add(30) - - assertEquals(listOf(1, 2, 3, 5, 8, 9, 11, 20, 30), tree.traverseInOrder()) } @Test - fun `test traversePreOrder`() { - val tree = BinaryTree() - - assertEquals(emptyList(), tree.traversePreOrder()) + fun test_traverse_pre_order() { + val tree = BinaryTree() tree.add(5) tree.add(3) @@ -153,23 +89,11 @@ internal class BinaryTreeTest { tree.add(9) assertEquals(listOf(5, 3, 2, 8, 9), tree.traversePreOrder()) - - tree.add(1) - tree.add(11) - - assertEquals(listOf(5, 3, 2, 1, 8, 9, 11), tree.traversePreOrder()) - - tree.add(0) - tree.add(20) - - assertEquals(listOf(5, 3, 2, 1, 0, 8, 9, 11, 20), tree.traversePreOrder()) } @Test - fun `test traversePostOrder`() { - val tree = BinaryTree() - - assertEquals(emptyList(), tree.traversePostOrder()) + fun test_traverse_post_order() { + val tree = BinaryTree() tree.add(5) tree.add(3) @@ -178,23 +102,11 @@ internal class BinaryTreeTest { tree.add(9) assertEquals(listOf(2, 3, 9, 8, 5), tree.traversePostOrder()) - - tree.add(1) - tree.add(11) - - assertEquals(listOf(1, 2, 3, 11, 9, 8, 5), tree.traversePostOrder()) - - tree.add(0) - tree.add(20) - - assertEquals(listOf(0, 1, 2, 3, 20, 11, 9, 8, 5), tree.traversePostOrder()) } @Test - fun `test traverseLevelOrder`() { - val tree = BinaryTree() - - assertEquals(emptyList(), tree.traverseLevelOrder()) + fun test_traverse_level_order() { + val tree = BinaryTree() tree.add(5) tree.add(3) @@ -203,17 +115,6 @@ internal class BinaryTreeTest { tree.add(9) assertEquals(listOf(5, 3, 8, 2, 9), tree.traverseLevelOrder()) - - tree.add(1) - tree.add(11) - - assertEquals(listOf(5, 3, 8, 2, 9, 1, 11), tree.traverseLevelOrder()) - - tree.add(0) - tree.add(20) - tree.add(30) - - assertEquals(listOf(5, 3, 8, 2, 9, 1, 11, 0, 20, 30), tree.traverseLevelOrder()) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/CircularLinkedListTest.kt b/src/test/kotlin/structures/CircularLinkedListTest.kt index 25a95227..3a404a89 100644 --- a/src/test/kotlin/structures/CircularLinkedListTest.kt +++ b/src/test/kotlin/structures/CircularLinkedListTest.kt @@ -1,242 +1,91 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class CircularLinkedListTest { @Test - fun `test cyclingList`() { + fun test_is_empty() { val list = CircularLinkedList() - - list.add(3) - list.add(6) - list.add(9) - list.add(12) - - assertEquals(emptyList(), list.cyclingList(0)) - assertEquals(listOf(3, 6, 9, 12), list.cyclingList(1)) - assertEquals(listOf( - 3, 6, 9, 12, - 3, 6, 9, 12 - ), list.cyclingList(2)) - assertEquals(listOf( - 3, 6, 9, 12, - 3, 6, 9, 12, - 3, 6, 9, 12 - ), list.cyclingList(3)) - - list.remove(6) - - assertEquals(listOf( - 3, 9, 12, 3, 9, 12, - 3, 9, 12, 3, 9, 12, - 3, 9, 12, 3, 9, 12 - ), list.cyclingList(6)) - - list.remove(9) - - assertEquals(listOf( - 3, 12, 3, 12, 3, 12, - 3, 12, 3, 12, 3, 12, - 3, 12, 3, 12, 3, 12, - 3, 12, 3, 12, 3, 12 - ), list.cyclingList(12)) - - list.remove(12) - - assertEquals(List(100) { 3 }, list.cyclingList(100)) - - list.remove(3) - - assertEquals(emptyList(), list.cyclingList(0)) - assertEquals(emptyList(), list.cyclingList(1)) - assertEquals(emptyList(), list.cyclingList(3)) - assertEquals(emptyList(), list.cyclingList(1000)) + assertEquals(true, list.isEmpty()) + list.add(10) + assertEquals(false, list.isEmpty()) } @Test - fun `test is empty`() { + fun test_circular() { val list = CircularLinkedList() - - assertEquals(true, list.isEmpty) - list.add(1) + assertEquals(true, list.isCircular()) list.add(2) list.add(3) - - assertEquals(false, list.isEmpty) - - list.remove(1) + assertEquals(true, list.isCircular()) list.remove(2) - list.remove(3) - - assertEquals(true, list.isEmpty) + list.remove(1) + assertEquals(true, list.isCircular()) } @Test - fun `test add by index`() { + fun test_size() { val list = CircularLinkedList() - + assertEquals(0, list.size()) list.add(1) + list.add(2) list.add(3) - list.add(5) - - assertEquals(""" - size: 3 - elements: 1 - 3 - 5 - - """.trimIndent(), list.toString()) - - list.add(1, 2) - list.add(3, 4) - - assertEquals(""" - size: 5 - elements: 1 - 2 - 3 - 4 - 5 - - """.trimIndent(), list.toString()) + assertEquals(3, list.size()) + list.remove(2) + assertEquals(2, list.size()) } @Test - fun `test addFirst`() { + fun test_add() { val list = CircularLinkedList() - - list.addFirst(100) - list.addFirst(80) - list.addFirst(60) - list.addFirst(40) - list.addFirst(20) - - assertEquals(""" - size: 5 - elements: 20 - 40 - 60 - 80 - 100 - - """.trimIndent(), list.toString()) - - list.remove(80) - list.remove(40) - - assertEquals(""" - size: 3 - elements: 20 - 60 - 100 - - """.trimIndent(), list.toString()) - - list.addFirst(0) - - assertEquals(""" - size: 4 - elements: 0 - 20 - 60 - 100 - - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.add(10) + list.add(20) + list.add(30) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test addLast`() { + fun test_add_first() { val list = CircularLinkedList() - - list.addLast(100) - list.addLast(200) - list.addLast(300) - list.addLast(400) - list.addLast(500) - list.addLast(600) - list.addLast(700) - - assertEquals(""" - size: 7 - elements: 100 - 200 - 300 - 400 - 500 - 600 - 700 - - """.trimIndent(), list.toString()) - - list.remove(200) - list.remove(400) - list.remove(600) - - assertEquals(""" - size: 4 - elements: 100 - 300 - 500 - 700 - - """.trimIndent(), list.toString()) - - list.addLast(900) - - assertEquals(""" - size: 5 - elements: 100 - 300 - 500 - 700 - 900 - - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.addFirst(30) + list.addFirst(20) + list.addFirst(10) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test contains`() { + fun test_remove() { val list = CircularLinkedList() - - list.add(1) - list.add(3) - list.add(5) - list.add(7) - list.add(9) - list.add(11) - - assertEquals(true, list.contains(1)) - assertEquals(true, list.contains(5)) - assertEquals(true, list.contains(9)) - assertEquals(true, list.contains(11)) - - assertEquals(false, list.contains(2)) - assertEquals(false, list.contains(4)) - assertEquals(false, list.contains(8)) - assertEquals(false, list.contains(10)) - - list.clear() - - assertEquals(false, list.contains(1)) - assertEquals(false, list.contains(5)) - assertEquals(false, list.contains(9)) - assertEquals(false, list.contains(11)) + assertEquals(listOf(), list.toList()) + list.addLast(10) + list.addLast(20) + list.addLast(30) + assertEquals(listOf(10, 20, 30), list.toList()) + list.remove(20) + assertEquals(listOf(10, 30), list.toList()) + list.remove(30) + assertEquals(listOf(10), list.toList()) + list.remove(10) + assertEquals(true, list.isEmpty()) } @Test - fun `test remove and clear`() { + fun test_contains() { val list = CircularLinkedList() - - list.add(1) - list.add(2) - list.add(3) - list.add(4) - list.add(5) - - assertEquals(""" - size: 5 - elements: 1 - 2 - 3 - 4 - 5 - - """.trimIndent(), list.toString()) - - assertEquals(true, list.remove(1)) - assertEquals(true, list.remove(3)) - assertEquals(true, list.remove(5)) - - assertEquals(""" - size: 2 - elements: 2 - 4 - - """.trimIndent(), list.toString()) - - println(list.toString()) - - assertEquals(true, list.remove(2)) - - println(list.toString()) - - assertEquals(true, list.remove(4)) - - assertEquals(true, list.isEmpty) - - list.add(6) - list.add(7) - list.add(11) - list.add(13) - - assertEquals(""" - size: 4 - elements: 6 - 7 - 11 - 13 - - """.trimIndent(), list.toString()) - - list.clear() - - assertEquals(true, list.isEmpty) + assertEquals(false, list.contains(10)) + list.add(10) + assertEquals(true, list.contains(10)) + list.addFirst(100) + list.addLast(300) + assertEquals(true, list.contains(300)) + assertEquals(false, list.contains(1000)) + list.remove(10) + assertEquals(false, list.contains(10)) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/DoubleLinkedListTest.kt b/src/test/kotlin/structures/DoubleLinkedListTest.kt index b830923c..e0ea58e9 100644 --- a/src/test/kotlin/structures/DoubleLinkedListTest.kt +++ b/src/test/kotlin/structures/DoubleLinkedListTest.kt @@ -1,222 +1,78 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class DoubleLinkedListTest { @Test - fun `test is empty`() { + fun test_is_empty() { val list = DoubleLinkedList() + assertEquals(true, list.isEmpty()) + list.add(10) + assertEquals(false, list.isEmpty()) + } - assertEquals(true, list.isEmpty) - + @Test + fun test_size() { + val list = DoubleLinkedList() + assertEquals(0, list.size()) list.add(1) list.add(2) list.add(3) - - assertEquals(false, list.isEmpty) - - list.remove(1) + assertEquals(3, list.size()) list.remove(2) - list.remove(3) - - assertEquals(true, list.isEmpty) + assertEquals(2, list.size()) } @Test - fun `test add by index`() { + fun test_add() { val list = DoubleLinkedList() - - list.add(1) - list.add(3) - list.add(5) - - assertEquals(""" - size: 3 - elements: 1 -- 3 -- 5 - """.trimIndent(), list.toString()) - - list.add(1, 2) - list.add(3, 4) - - assertEquals(""" - size: 5 - elements: 1 -- 2 -- 3 -- 4 -- 5 - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.add(10) + list.add(20) + list.add(30) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test addFirst`() { + fun test_add_first() { val list = DoubleLinkedList() - - list.addFirst(100) - list.addFirst(80) - list.addFirst(60) - list.addFirst(40) + assertEquals(listOf(), list.toList()) + list.addFirst(30) list.addFirst(20) - - assertEquals(""" - size: 5 - elements: 20 -- 40 -- 60 -- 80 -- 100 - """.trimIndent(), list.toString()) - - list.remove(80) - list.remove(40) - - assertEquals(""" - size: 3 - elements: 20 -- 60 -- 100 - """.trimIndent(), list.toString()) - - list.addFirst(0) - - assertEquals(""" - size: 4 - elements: 0 -- 20 -- 60 -- 100 - """.trimIndent(), list.toString()) + list.addFirst(10) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test addLast`() { + fun test_remove() { val list = DoubleLinkedList() - - list.addLast(100) - list.addLast(200) - list.addLast(300) - list.addLast(400) - list.addLast(500) - list.addLast(600) - list.addLast(700) - - assertEquals(""" - size: 7 - elements: 100 -- 200 -- 300 -- 400 -- 500 -- 600 -- 700 - """.trimIndent(), list.toString()) - - list.remove(200) - list.remove(400) - list.remove(600) - - assertEquals(""" - size: 4 - elements: 100 -- 300 -- 500 -- 700 - """.trimIndent(), list.toString()) - - list.addLast(900) - - assertEquals(""" - size: 5 - elements: 100 -- 300 -- 500 -- 700 -- 900 - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.addLast(10) + list.addLast(20) + list.addLast(30) + assertEquals(listOf(10, 20, 30), list.toList()) + list.remove(20) + assertEquals(listOf(10, 30), list.toList()) + list.remove(30) + assertEquals(listOf(10), list.toList()) + list.remove(10) + assertEquals(true, list.isEmpty()) } @Test - fun `test contains`() { + fun test_contains() { val list = DoubleLinkedList() - - list.add(1) - list.add(3) - list.add(5) - list.add(7) - list.add(9) - list.add(11) - - assertEquals(true, list.contains(1)) - assertEquals(true, list.contains(5)) - assertEquals(true, list.contains(9)) - assertEquals(true, list.contains(11)) - - assertEquals(false, list.contains(2)) - assertEquals(false, list.contains(4)) - assertEquals(false, list.contains(8)) assertEquals(false, list.contains(10)) - - list.clear() - - assertEquals(false, list.contains(1)) - assertEquals(false, list.contains(5)) - assertEquals(false, list.contains(9)) - assertEquals(false, list.contains(11)) - } - - @Test - fun `test remove and clear`() { - val list = DoubleLinkedList() - - list.add(1) - list.add(2) - list.add(3) - list.add(4) - list.add(5) - - assertEquals(""" - size: 5 - elements: 1 -- 2 -- 3 -- 4 -- 5 - """.trimIndent(), list.toString()) - - assertEquals(true, list.remove(1)) - assertEquals(true, list.remove(3)) - assertEquals(true, list.remove(5)) - - assertEquals(""" - size: 2 - elements: 2 -- 4 - """.trimIndent(), list.toString()) - - assertEquals(true, list.remove(2)) - assertEquals(true, list.remove(4)) - - assertEquals(true, list.isEmpty) - - list.add(6) - list.add(7) - list.add(11) - list.add(13) - - assertEquals(""" - size: 4 - elements: 6 -- 7 -- 11 -- 13 - """.trimIndent(), list.toString()) - - list.clear() - - assertEquals(true, list.isEmpty) - } - - @Test - fun `test list and reversedList`() { - val list = DoubleLinkedList() - - list.add(1) - list.add(2) - list.add(3) - list.add(4) - list.add(5) - list.add(6) - list.add(7) - - assertEquals(listOf(1, 2, 3, 4, 5, 6, 7), list.list) - assertEquals(listOf(7, 6, 5, 4, 3, 2, 1), list.reversedList) - - list.remove(1) - list.remove(4) - list.remove(7) - - assertEquals(listOf(2, 3, 5, 6), list.list) - assertEquals(listOf(6, 5, 3, 2), list.reversedList) - - list.remove(2) - list.remove(6) - - assertEquals(listOf(3, 5), list.list) - assertEquals(listOf(5, 3), list.reversedList) - - list.clear() - - assertEquals(emptyList(), list.list) - assertEquals(emptyList(), list.reversedList) - assertEquals(true, list.isEmpty) + list.add(10) + assertEquals(true, list.contains(10)) + list.addFirst(100) + list.addLast(300) + assertEquals(true, list.contains(300)) + assertEquals(false, list.contains(1000)) + list.remove(10) + assertEquals(false, list.contains(10)) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/DynamicArrayTest.kt b/src/test/kotlin/structures/DynamicArrayTest.kt deleted file mode 100644 index 68ee031e..00000000 --- a/src/test/kotlin/structures/DynamicArrayTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals - -internal class DynamicArrayTest { - - @Test - fun test() { - val array = DynamicArray() - array.add(1) - array.add(2) - array.add(3) - array.add(4) - - assertEquals(""" - capacity: 10 - size: 4 - elements: 1, 2, 3, 4 - """.trimIndent(), array.toString()) - - assertEquals(1, array.set(0, 10)) - assertEquals(10, array.get(0)) - - assertEquals(2, array.set(1, 20)) - assertEquals(20, array.get(1)) - - assertEquals(3, array.set(2, 30)) - assertEquals(30, array.get(2)) - - assertEquals(4, array.set(3, 40)) - assertEquals(40, array.get(3)) - - assertEquals(true, array.remove(10)) - assertEquals(true, array.remove(20)) - assertEquals(true, array.remove(30)) - assertEquals(true, array.remove(40)) - - array.add(1); array.add(2); array.add(3); array.add(4); array.add(5) - array.add(6); array.add(7); array.add(8); array.add(9); array.add(10) - array.add(11); array.add(12); array.add(13); array.add(14); array.add(15) - - assertEquals(""" - capacity: 20 - size: 15 - elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - """.trimIndent(), array.toString()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/structures/GraphTest.kt b/src/test/kotlin/structures/GraphTest.kt index 77f77d76..c79fbf48 100644 --- a/src/test/kotlin/structures/GraphTest.kt +++ b/src/test/kotlin/structures/GraphTest.kt @@ -1,12 +1,12 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class GraphTest { @Test - fun `test add and remove vertexes`() { + fun test_add_and_remove_vertexes() { val graph = Graph() graph.addVertex(10) @@ -17,21 +17,13 @@ internal class GraphTest { graph.addEdge(10, 30) graph.addEdge(20, 30) - assertEquals(listOf(20, 30), graph.connectedVertexes(10)) - assertEquals(listOf(10, 30), graph.connectedVertexes(20)) - graph.removeVertex(10) - assertEquals(listOf(20), graph.connectedVertexes(30)) - assertEquals(listOf(30), graph.connectedVertexes(20)) - - graph.removeVertex(20) - - assertEquals(listOf(), graph.connectedVertexes(30)) + assertEquals(listOf(Vertex(20), Vertex(30)), graph.breadthFirstTraversal()) } @Test - fun `test remove edges`() { + fun test_empty() { val graph = Graph() graph.addVertex(10) @@ -42,24 +34,16 @@ internal class GraphTest { graph.addEdge(10, 30) graph.addEdge(20, 30) - assertEquals(listOf(20, 30), graph.connectedVertexes(10)) - - graph.removeEdge(10, 20) - - assertEquals(listOf(30), graph.connectedVertexes(10)) - - graph.removeEdge(10, 30) - - assertEquals(listOf(), graph.connectedVertexes(10)) - assertEquals(listOf(30), graph.connectedVertexes(20)) - - graph.removeEdge(20, 30) + graph.removeVertex(10) + graph.removeVertex(20) + graph.removeVertex(30) - assertEquals(listOf(), graph.connectedVertexes(20)) + val expected: List> = listOf() + assertEquals(expected, graph.breadthFirstTraversal()) } @Test - fun `test depthFirstTraversal`() { + fun test_depth_first_traversal() { val graph = Graph() graph.addVertex(10) @@ -70,23 +54,11 @@ internal class GraphTest { graph.addEdge(20, 30) graph.addEdge(30, 10) - assertEquals(listOf(10, 20, 30), graph.depthFirstTraversal()) - - graph.removeVertex(10) - - assertEquals(listOf(20, 30), graph.depthFirstTraversal()) - - graph.removeVertex(30) - - assertEquals(listOf(20), graph.depthFirstTraversal()) - - graph.removeVertex(20) - - assertEquals(listOf(), graph.depthFirstTraversal()) + assertEquals(listOf(Vertex(10), Vertex(20), Vertex(30)), graph.depthFirstTraversal()) } @Test - fun `test breadthFirstTraversal`() { + fun test_breadth_first_traversal() { val graph = Graph() graph.addVertex(10) @@ -98,20 +70,7 @@ internal class GraphTest { graph.addEdge(20, 30) graph.addEdge(20, 40) - assertEquals(listOf(10, 20, 30, 40), graph.breadthFirstTraversal()) - - graph.removeVertex(10) - - assertEquals(listOf(20, 30, 40), graph.breadthFirstTraversal()) - - graph.removeVertex(40) - - assertEquals(listOf(20, 30), graph.breadthFirstTraversal()) - - graph.removeVertex(20) - graph.removeVertex(30) - - assertEquals(listOf(), graph.breadthFirstTraversal()) + assertEquals(listOf(Vertex(10), Vertex(20), Vertex(30), Vertex(40)), graph.breadthFirstTraversal()) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/GraphWithWeightsTest.kt b/src/test/kotlin/structures/GraphWithWeightsTest.kt deleted file mode 100644 index cdce5b7d..00000000 --- a/src/test/kotlin/structures/GraphWithWeightsTest.kt +++ /dev/null @@ -1,116 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals - -class GraphWithWeightsTest { - - @Test - fun `test add and remove vertexes`() { - val graph = GraphWithWeights() - - graph.addVertex(10) - graph.addVertex(20) - graph.addVertex(30) - - graph.addEdge(10, 20, 1) - graph.addEdge(10, 30, 2) - graph.addEdge(20, 30, 3) - - assertEquals(listOf( - "vertex -> 20, cost -> 1", - "vertex -> 30, cost -> 2" - ), graph.connectedVertexesWithWeights(10)) - - graph.removeVertex(10) - - assertEquals(listOf(), graph.connectedVertexesWithWeights(10)) - - assertEquals(listOf("vertex -> 30, cost -> 3"), graph.connectedVertexesWithWeights(20)) - - graph.removeVertex(20) - - assertEquals(listOf(), graph.connectedVertexesWithWeights(10)) - } - - @Test - fun `test remove edges`() { - val graph = GraphWithWeights() - - graph.addVertex(10) - graph.addVertex(20) - graph.addVertex(30) - - graph.addEdge(10, 20, 1) - graph.addEdge(10, 30, 2) - graph.addEdge(20, 30, 3) - - assertEquals(listOf( - "vertex -> 20, cost -> 1", - "vertex -> 30, cost -> 2" - ), graph.connectedVertexesWithWeights(10)) - - graph.removeEdge(10, 20) - - assertEquals(listOf("vertex -> 30, cost -> 2"), graph.connectedVertexesWithWeights(10)) - - graph.removeEdge(10, 30) - - assertEquals(listOf(), graph.connectedVertexesWithWeights(10)) - assertEquals(listOf("vertex -> 30, cost -> 3"), graph.connectedVertexesWithWeights(20)) - - graph.removeEdge(20, 30) - - assertEquals(listOf(), graph.connectedVertexesWithWeights(10)) - } - - @Test - fun test_dijkstraAlgorithm() { - val graph = GraphWithWeights() - - graph.addVertex(1) - graph.addVertex(2) - graph.addVertex(3) - graph.addVertex(4) - graph.addVertex(5) - - graph.addEdge(1, 2, 10) - graph.addEdge(1, 5, 100) - graph.addEdge(2, 3, 20) - graph.addEdge(2, 4, 5) - graph.addEdge(3, 4, 15) - graph.addEdge(4, 5, 5) - - assertEquals(linkedMapOf( - 1 to 0, - 2 to 10, - 3 to 30, - 4 to 15, - 5 to 20 - ), graph.dijkstraAlgorithm()) - - graph.removeVertex(4) - - assertEquals(linkedMapOf( - 1 to 0, - 2 to 10, - 3 to 30, - 5 to 100 - ), graph.dijkstraAlgorithm()) - - graph.removeVertex(5) - - assertEquals(linkedMapOf( - 1 to 0, - 2 to 10, - 3 to 30 - ), graph.dijkstraAlgorithm()) - - graph.removeVertex(1) - graph.removeVertex(2) - graph.removeVertex(3) - - assertEquals(mapOf(), graph.dijkstraAlgorithm()) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/structures/LinkedListQueueTest.kt b/src/test/kotlin/structures/LinkedListQueueTest.kt new file mode 100644 index 00000000..8f09c678 --- /dev/null +++ b/src/test/kotlin/structures/LinkedListQueueTest.kt @@ -0,0 +1,73 @@ +package structures + +import org.junit.Test +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.BeforeEach +import java.lang.IllegalStateException + +class LinkedListQueueTest { + private val queue : Queue = Queue.LinkedListQueue() + + @BeforeEach + fun clear() = queue.clear() + + @Test + fun test_is_empty() { + Assertions.assertEquals(true, queue.isEmpty()) + + queue.offer(1) + queue.offer(2) + + Assertions.assertEquals(false, queue.isEmpty()) + + } + + @Test + fun test_poll() { + queue.offer(1) + Assertions.assertEquals(1, queue.poll()) + Assertions.assertEquals(null, queue.poll()) + } + + @Test + fun test_peek() { + queue.offer(5) + Assertions.assertEquals(5, queue.peek()) + queue.clear() + Assertions.assertEquals(null, queue.peek()) + } + + @Test + fun test_remove() { + queue.offer(100) + Assertions.assertEquals(100, queue.remove()) + + val exception = Assertions.assertThrows(IllegalStateException::class.java) { + queue.remove() + } + Assertions.assertEquals("queue is empty!", exception.message) + } + + @Test + fun test_element() { + queue.offer(100) + Assertions.assertEquals(100, queue.element()) + + queue.clear() + + val exception = Assertions.assertThrows(IllegalStateException::class.java) { + queue.element() + } + Assertions.assertEquals("queue is empty!", exception.message) + } + + @Test + fun test_remove_object() { + queue.offer(10) + queue.offer(20) + queue.offer(1000) + + Assertions.assertEquals(true, queue.remove(20)) + Assertions.assertEquals(false, queue.remove(34)) + } +} \ No newline at end of file diff --git a/src/test/kotlin/structures/LinkedListStackTest.kt b/src/test/kotlin/structures/LinkedListStackTest.kt new file mode 100644 index 00000000..de859d7a --- /dev/null +++ b/src/test/kotlin/structures/LinkedListStackTest.kt @@ -0,0 +1,33 @@ +package structures + +import org.junit.Test +import org.junit.jupiter.api.Assertions + +class LinkedListStackTest { + + private val arrayListStack = Stack.LinkedListStack() + + @Test + fun test_push() { + arrayListStack.push(10) + Assertions.assertEquals(10, arrayListStack.peek()) + } + + @Test + fun test_pop() { + arrayListStack.push(20) + Assertions.assertEquals(20, arrayListStack.pop()) + } + + @Test + fun test_is_empty() { + arrayListStack.clear() + Assertions.assertEquals(true, arrayListStack.isEmpty()) + } + + @Test + fun test_is_not_empty() { + arrayListStack.push(20) + Assertions.assertEquals(false, arrayListStack.isEmpty()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/structures/MatrixTest.kt b/src/test/kotlin/structures/MatrixTest.kt deleted file mode 100644 index 5bd140a5..00000000 --- a/src/test/kotlin/structures/MatrixTest.kt +++ /dev/null @@ -1,239 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals -import org.junit.Assert.assertThrows -import java.lang.IllegalArgumentException - -class MatrixTest { - - @Test - fun `test when number of elements in each row is not the same`() { - assertThrows(IllegalArgumentException::class.java) { - matrix { - row(1, 2, 3) - row(4, 5) - } - } - } - - @Test - fun `test equals`() { - val matrix1 = matrix { - row(1, 2, 3) - row(4, 5, 6) - row(7, 8, 9) - } - - val matrix2 = matrix { - row(1, 2, 3) - row(4, 5, 6) - row(7, 8, 9) - } - - assertEquals(true, matrix1 == matrix2) - - val matrix3 = matrix { - row(1, 2, 3) - row(4, 5, 6) - } - - assertEquals(false, matrix2 == matrix3) - } - - @Test - fun `test plus minus a value`() { - val matrix1 = matrix { - row(4, 7, 2) - row(10, 12, 20) - row(100, 1000, 8) - } - - val expected1 = matrix { - row(6, 9, 4) - row(12, 14, 22) - row(102, 1002, 10) - } - val actual1 = matrix1 + 2 - - assertEquals(expected1, actual1) - - val actual2 = matrix1 - 10 - - val expected2 = matrix { - row(-6, -3, -8) - row(0, 2, 10) - row(90, 990, -2) - } - assertEquals(expected2, actual2) - } - - @Test - fun `test multiply and div by value`() { - val matrix1 = matrix { - row(2, 5) - row(10, 19) - } - - val expected1 = matrix { - row(4, 10) - row(20, 38) - } - val actual1 = matrix1 * 2 - - assertEquals(expected1, actual1) - - val matrix2 = matrix { - row(100, -95, 1200) - row(55, 110, -20) - row(5, 2, -10) - } - - val actual2 = matrix2 / 5 - - val expected2 = matrix { - row(20, -19, 240) - row(11, 22, -4) - row(1, 0, -2) - } - assertEquals(expected2, actual2) - } - - @Test - fun `test plus between matrices`() { - val matrix1 = matrix { - row(13, 109) - row(8, 6) - } - - val matrix2 = matrix { - row(9, 34, 2) - row(90, 20, 1005) - } - - assertThrows(IllegalArgumentException::class.java) { - matrix1 + matrix2 - } - - val matrix3 = matrix { - row(20, 30) - row(3, 56) - row(5, 28) - } - - assertThrows(IllegalArgumentException::class.java) { - matrix1 + matrix3 - } - - val matrix4 = matrix { - row(7, 1) - row(2, 4) - } - - val expected = matrix { - row(20, 110) - row(10, 10) - } - - val actual = matrix1 + matrix4 - - assertEquals(expected, actual) - } - - @Test - fun `test minus between matrices`() { - val matrix1 = matrix { - row(13, 109) - row(8, 6) - } - - val matrix2 = matrix { - row(9, 34, 2) - row(90, 20, 1005) - } - - assertThrows(IllegalArgumentException::class.java) { - matrix1 - matrix2 - } - - val matrix3 = matrix { - row(20, 30) - row(3, 56) - row(5, 28) - } - - assertThrows(IllegalArgumentException::class.java) { - matrix1 - matrix3 - } - - val matrix4 = matrix { - row(3, 9) - row(8, 6) - } - - val expected = matrix { - row(10, 100) - row(0, 0) - } - - val actual = matrix1 - matrix4 - - assertEquals(expected, actual) - } - - @Test - fun `test multiply between matrices`() { - val matrix1 = matrix { - row(1, 2) - row(8, 9) - } - val matrix2 = matrix { - row(2) - row(4) - row(8) - } - - assertThrows(IllegalArgumentException::class.java) { matrix1 * matrix2 } - - val matrix3 = matrix { - row(1, 4) - row(2, 5) - row(3, 6) - } - val matrix4 = matrix { - row(7, 8, 9, 10) - row(11, 12, 13, 14) - } - - val expected1 = matrix { - row(51, 56, 61, 66) - row(69, 76, 83, 90) - row(87, 96, 105, 114) - } - val actual1 = matrix3 * matrix4 - - assertEquals(expected1, actual1) - - val matrix5 = matrix { - row(45, 11, 20, -15) - row(-12, 9, -18, 0) - row(8, 3, -13, 36) - } - val matrix6 = matrix { - row(-1, 8, 55) - row(5, -2, 13) - row(14, 27, 6) - row(19, 3, -10) - } - - val expected2 = matrix { - row(5, 833, 2888) - row(-195, -600, -651) - row(509, -185, 41) - } - val actual2 = matrix5 * matrix6 - - assertEquals(expected2, actual2) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/structures/MaxHeapTest.kt b/src/test/kotlin/structures/MaxHeapTest.kt index 66c2ef07..49e6d113 100644 --- a/src/test/kotlin/structures/MaxHeapTest.kt +++ b/src/test/kotlin/structures/MaxHeapTest.kt @@ -2,61 +2,63 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class MaxHeapTest { @Test - fun `test operations`() { - val heap = MaxHeap(10) + fun test_add() { + val heap = MaxHeap(2) - assertEquals(true, heap.isEmpty) + assertEquals(true, heap.isEmpty()) - heap.add(10) - heap.add(17) - heap.add(20) - - assertEquals(false, heap.isEmpty) + heap.add(2) + heap.add(6) - assertEquals(20, heap.peekMax()) - assertEquals(20, heap.popMax()) - - heap.add(1) - heap.add(5) + assertEquals(false, heap.isEmpty()) - assertEquals(17, heap.peekMax()) - assertEquals(17, heap.popMax()) + } - assertEquals(10, heap.peekMax()) - assertEquals(10, heap.popMax()) + @Test + fun test_peek_max() { + val heap = MaxHeap(5) - heap.set(1, 100) + heap.add(17) + heap.add(2) + heap.add(100) assertEquals(100, heap.peekMax()) - assertEquals(100, heap.popMax()) - assertEquals(1, heap.peekMax()) - assertEquals(1, heap.popMax()) + heap.add(1) + heap.add(200) + + assertEquals(200, heap.peekMax()) - assertEquals(true, heap.isEmpty) } @Test - fun `test creating from array`() { - val array = intArrayOf(10, 2, 11, 17, 5, -1, 9, 0) - - val heap = MaxHeap.create(array) - - assertEquals(17, heap.popMax()) - assertEquals(11, heap.popMax()) + fun test_pop_max() { + val heap = MaxHeap(8).apply { + add(10) + add(40) + add(1) + add(1000) + add(555) + add(5) + add(7) + add(2) + } + + assertEquals(1000, heap.popMax()) + assertEquals(555, heap.popMax()) + assertEquals(40, heap.popMax()) assertEquals(10, heap.popMax()) - assertEquals(9, heap.popMax()) + assertEquals(7, heap.popMax()) assertEquals(5, heap.popMax()) assertEquals(2, heap.popMax()) - assertEquals(0, heap.popMax()) - assertEquals(-1, heap.popMax()) + assertEquals(1, heap.popMax()) - assertEquals(true, heap.isEmpty) + assertEquals(true, heap.isEmpty()) } diff --git a/src/test/kotlin/structures/MinHeapTest.kt b/src/test/kotlin/structures/MinHeapTest.kt index 528ee0bb..9da50c84 100644 --- a/src/test/kotlin/structures/MinHeapTest.kt +++ b/src/test/kotlin/structures/MinHeapTest.kt @@ -1,61 +1,67 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class MinHeapTest { @Test - fun `test operations`() { - val heap = MinHeap(10) + fun test_add() { + val heap = MaxHeap(2) + + assertEquals(true, heap.isEmpty()) - assertEquals(true, heap.isEmpty) + heap.add(2) + heap.add(6) - heap.add(10) - heap.add(17) - heap.add(20) + assertEquals(false, heap.isEmpty()) - assertEquals(false, heap.isEmpty) + } - assertEquals(10, heap.peekMin()) - assertEquals(10, heap.popMin()) + @Test + fun test_peek_min() { + val heap = MinHeap(6) - heap.add(1) - heap.add(5) + heap.add(17) + heap.add(2) + heap.add(100) - assertEquals(1, heap.peekMin()) - assertEquals(1, heap.popMin()) + assertEquals(2, heap.peekMin()) - assertEquals(5, heap.peekMin()) - assertEquals(5, heap.popMin()) + heap.add(1) + heap.add(200) - heap.set(1, 15) + assertEquals(1, heap.peekMin()) - assertEquals(15, heap.peekMin()) - assertEquals(15, heap.popMin()) + heap.add(0) - assertEquals(20, heap.peekMin()) - assertEquals(20, heap.popMin()) + assertEquals(0, heap.peekMin()) - assertEquals(true, heap.isEmpty) } @Test - fun `test creating from array`() { - val array = intArrayOf(10, 2, 11, 17, 5, -1, 9, 0) - - val heap = MinHeap.create(array) + fun test_pop_min() { + val heap = MinHeap(8).apply { + add(10) + add(40) + add(1) + add(1000) + add(555) + add(5) + add(7) + add(2) + } - assertEquals(-1, heap.popMin()) - assertEquals(0, heap.popMin()) + assertEquals(1, heap.popMin()) assertEquals(2, heap.popMin()) assertEquals(5, heap.popMin()) - assertEquals(9, heap.popMin()) + assertEquals(7, heap.popMin()) assertEquals(10, heap.popMin()) - assertEquals(11, heap.popMin()) - assertEquals(17, heap.popMin()) + assertEquals(40, heap.popMin()) + assertEquals(555, heap.popMin()) + assertEquals(1000, heap.popMin()) - assertEquals(true, heap.isEmpty) + assertEquals(true, heap.isEmpty()) } diff --git a/src/test/kotlin/structures/MyArrayListTest.kt b/src/test/kotlin/structures/MyArrayListTest.kt new file mode 100644 index 00000000..df8965b5 --- /dev/null +++ b/src/test/kotlin/structures/MyArrayListTest.kt @@ -0,0 +1,67 @@ +package structures + +import org.junit.Test +import org.junit.jupiter.api.Assertions.* + +internal class MyArrayListTest { + + @Test + fun test_add() { + val array = MyArrayList().apply { + for (i in 0 until 10) { add(i) } + } + assertEquals(5, array.get(5)) + } + + @Test + fun test_set() { + val array = MyArrayList().apply { + add(1) + add(2) + add(3) + } + assertEquals(1, array.get(0)) + array.set(0, 10) + assertEquals(10, array.get(0)) + } + + @Test + fun test_contains() { + val array = MyArrayList().apply { + add(1) + add(2) + add(100) + } + assertEquals(true, array.contains(100)) + assertEquals(false, array.contains(5)) + } + + @Test + fun test_remove() { + val array = MyArrayList().apply { + add(0) + add(1) + add(2) + add(3) + add(4) + } + assertEquals(3, array.get(3)) + array.remove(3) + assertEquals(4, array.get(3)) + array.remove(0) + assertEquals(1, array.get(0)) + } + + @Test + fun test_increasing() { + val array = MyArrayList().apply { + for (i in 0 until 10) { add(i) } + } + assertEquals(false, array.contains(10)) + assertEquals(20, array.capacity()) + array.add(10) + assertEquals(true, array.contains(10)) + assertEquals(20, array.capacity()) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/structures/QueueTest.kt b/src/test/kotlin/structures/QueueTest.kt deleted file mode 100644 index 97659776..00000000 --- a/src/test/kotlin/structures/QueueTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals - -class QueueTest { - - @Test - fun test() { - val queue = Queue() - - assertEquals(true, queue.isEmpty) - assertEquals(0, queue.size) - - queue.enqueue(1) - assertEquals(1, queue.peek()) - - queue.enqueue(2) - assertEquals(1, queue.peek()) - - queue.enqueue(3) - assertEquals(1, queue.peek()) - - assertEquals(false, queue.isEmpty) - assertEquals(3, queue.size) - - assertEquals(1, queue.dequeue()) - assertEquals(2, queue.peek()) - - assertEquals(2, queue.dequeue()) - assertEquals(3, queue.peek()) - - assertEquals(3, queue.dequeue()) - - assertEquals(true, queue.isEmpty) - assertEquals(0, queue.size) - - queue.enqueue(10) - queue.enqueue(20) - queue.enqueue(30) - - assertEquals(false, queue.isEmpty) - assertEquals(3, queue.size) - - queue.clear() - - assertEquals(true, queue.isEmpty) - assertEquals(0, queue.size) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/structures/SingleLinkedListTest.kt b/src/test/kotlin/structures/SingleLinkedListTest.kt index 1dffbbe2..b18c353e 100644 --- a/src/test/kotlin/structures/SingleLinkedListTest.kt +++ b/src/test/kotlin/structures/SingleLinkedListTest.kt @@ -1,187 +1,78 @@ package structures import org.junit.Test -import org.junit.Assert.assertEquals +import org.junit.jupiter.api.Assertions.* internal class SingleLinkedListTest { @Test - fun `test is empty`() { + fun test_is_empty() { val list = SingleLinkedList() + assertEquals(true, list.isEmpty()) + list.add(10) + assertEquals(false, list.isEmpty()) + } - assertEquals(true, list.isEmpty) - + @Test + fun test_size() { + val list = SingleLinkedList() + assertEquals(0, list.size()) list.add(1) list.add(2) list.add(3) - - assertEquals(false, list.isEmpty) - - list.remove(1) + assertEquals(3, list.size()) list.remove(2) - list.remove(3) - - assertEquals(true, list.isEmpty) + assertEquals(2, list.size()) } @Test - fun `test add by index`() { + fun test_add() { val list = SingleLinkedList() - - list.add(1) - list.add(3) - list.add(5) - - assertEquals(""" - size: 3 - elements: 1 - 3 - 5 - """.trimIndent(), list.toString()) - - list.add(1, 2) - list.add(3, 4) - - assertEquals(""" - size: 5 - elements: 1 - 2 - 3 - 4 - 5 - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.add(10) + list.add(20) + list.add(30) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test addFirst`() { + fun test_add_first() { val list = SingleLinkedList() - - list.addFirst(100) - list.addFirst(80) - list.addFirst(60) - list.addFirst(40) + assertEquals(listOf(), list.toList()) + list.addFirst(30) list.addFirst(20) - - assertEquals(""" - size: 5 - elements: 20 - 40 - 60 - 80 - 100 - """.trimIndent(), list.toString()) - - list.remove(80) - list.remove(40) - - assertEquals(""" - size: 3 - elements: 20 - 60 - 100 - """.trimIndent(), list.toString()) - - list.addFirst(0) - - assertEquals(""" - size: 4 - elements: 0 - 20 - 60 - 100 - """.trimIndent(), list.toString()) + list.addFirst(10) + assertEquals(listOf(10, 20, 30), list.toList()) } @Test - fun `test addLast`() { + fun test_remove() { val list = SingleLinkedList() - - list.addLast(100) - list.addLast(200) - list.addLast(300) - list.addLast(400) - list.addLast(500) - list.addLast(600) - list.addLast(700) - - assertEquals(""" - size: 7 - elements: 100 - 200 - 300 - 400 - 500 - 600 - 700 - """.trimIndent(), list.toString()) - - list.remove(200) - list.remove(400) - list.remove(600) - - assertEquals(""" - size: 4 - elements: 100 - 300 - 500 - 700 - """.trimIndent(), list.toString()) - - list.addLast(900) - - assertEquals(""" - size: 5 - elements: 100 - 300 - 500 - 700 - 900 - """.trimIndent(), list.toString()) + assertEquals(listOf(), list.toList()) + list.addLast(10) + list.addLast(20) + list.addLast(30) + assertEquals(listOf(10, 20, 30), list.toList()) + list.remove(20) + assertEquals(listOf(10, 30), list.toList()) + list.remove(30) + assertEquals(listOf(10), list.toList()) + list.remove(10) + assertEquals(true, list.isEmpty()) } @Test - fun `test contains`() { + fun test_contains() { val list = SingleLinkedList() - - list.add(1) - list.add(3) - list.add(5) - list.add(7) - list.add(9) - list.add(11) - - assertEquals(true, list.contains(1)) - assertEquals(true, list.contains(5)) - assertEquals(true, list.contains(9)) - assertEquals(true, list.contains(11)) - - assertEquals(false, list.contains(2)) - assertEquals(false, list.contains(4)) - assertEquals(false, list.contains(8)) assertEquals(false, list.contains(10)) - - list.clear() - - assertEquals(false, list.contains(1)) - assertEquals(false, list.contains(5)) - assertEquals(false, list.contains(9)) - assertEquals(false, list.contains(11)) - } - - @Test - fun `test remove and clear`() { - val list = SingleLinkedList() - - list.add(1) - list.add(2) - list.add(3) - list.add(4) - list.add(5) - - assertEquals(""" - size: 5 - elements: 1 - 2 - 3 - 4 - 5 - """.trimIndent(), list.toString()) - - assertEquals(true, list.remove(1)) - assertEquals(true, list.remove(3)) - assertEquals(true, list.remove(5)) - - assertEquals(""" - size: 2 - elements: 2 - 4 - """.trimIndent(), list.toString()) - - assertEquals(true, list.remove(2)) - assertEquals(true, list.remove(4)) - - assertEquals(true, list.isEmpty) - - list.add(6) - list.add(7) - list.add(11) - list.add(13) - - assertEquals(""" - size: 4 - elements: 6 - 7 - 11 - 13 - """.trimIndent(), list.toString()) - - list.clear() - - assertEquals(true, list.isEmpty) + list.add(10) + assertEquals(true, list.contains(10)) + list.addFirst(100) + list.addLast(300) + assertEquals(true, list.contains(300)) + assertEquals(false, list.contains(1000)) + list.remove(10) + assertEquals(false, list.contains(10)) } } \ No newline at end of file diff --git a/src/test/kotlin/structures/Stack1Test.kt b/src/test/kotlin/structures/Stack1Test.kt deleted file mode 100644 index 3050dcb1..00000000 --- a/src/test/kotlin/structures/Stack1Test.kt +++ /dev/null @@ -1,40 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals - -class Stack1Test { - - @Test - fun test() { - val stack = Stack1() - - stack.push(1) - stack.push(2) - stack.push(3) - - assertEquals(false, stack.isEmpty) - assertEquals(3, stack.size) - - assertEquals(3, stack.pop()) - assertEquals(2, stack.pop()) - assertEquals(1, stack.pop()) - - assertEquals(true, stack.isEmpty) - assertEquals(0, stack.size) - - stack.push(10) - stack.push(20) - stack.push(30) - - assertEquals(3, stack.size) - assertEquals(30, stack.peek()) - assertEquals(3, stack.size) - - stack.clear() - - assertEquals(true, stack.isEmpty) - assertEquals(0, stack.size) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/structures/Stack2Test.kt b/src/test/kotlin/structures/Stack2Test.kt deleted file mode 100644 index 5487c608..00000000 --- a/src/test/kotlin/structures/Stack2Test.kt +++ /dev/null @@ -1,40 +0,0 @@ -package structures - -import org.junit.Test -import org.junit.Assert.assertEquals - -class Stack2Test { - - @Test - fun test() { - val stack = Stack2() - - stack.push(1) - stack.push(2) - stack.push(3) - - assertEquals(false, stack.isEmpty) - assertEquals(3, stack.size) - - assertEquals(3, stack.pop()) - assertEquals(2, stack.pop()) - assertEquals(1, stack.pop()) - - assertEquals(true, stack.isEmpty) - assertEquals(0, stack.size) - - stack.push(10) - stack.push(20) - stack.push(30) - - assertEquals(3, stack.size) - assertEquals(30, stack.peek()) - assertEquals(3, stack.size) - - stack.clear() - - assertEquals(true, stack.isEmpty) - assertEquals(0, stack.size) - } - -} \ No newline at end of file