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