develop 1f89f062a056 cached
140 files
250.1 KB
66.6k tokens
1 requests
Download .txt
Showing preview only (285K chars total). Download the full file or copy to clipboard to get everything.
Repository: KiberneticWorm/Kotlin-Algorithms-and-Design-Patterns
Branch: develop
Commit: 1f89f062a056
Files: 140
Total size: 250.1 KB

Directory structure:
gitextract_pko15ir1/

├── .gitignore
├── LICENSE.txt
├── README.md
├── README_ru.md
├── build.gradle.kts
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src/
    ├── main/
    │   └── kotlin/
    │       ├── design_patterns/
    │       │   ├── Abstract Factory.kt
    │       │   ├── Adapter.kt
    │       │   ├── Bridge.kt
    │       │   ├── Builder.kt
    │       │   ├── Command.kt
    │       │   ├── Composite.kt
    │       │   ├── Decorator.kt
    │       │   ├── Facade.kt
    │       │   ├── Factory Method.kt
    │       │   ├── Flyweight.kt
    │       │   ├── Interpreter.kt
    │       │   ├── Iterator.kt
    │       │   ├── Mediator.kt
    │       │   ├── Memento.kt
    │       │   ├── Observer.kt
    │       │   ├── Prototype.kt
    │       │   ├── Proxy.kt
    │       │   ├── Singleton.kt
    │       │   ├── State.kt
    │       │   ├── Strategy.kt
    │       │   ├── Template Method.kt
    │       │   ├── Visitor.kt
    │       │   └── Сhain Of Responsibilities.kt
    │       ├── other/
    │       │   ├── BinaryDigitsCounter.kt
    │       │   ├── EuclidAlgorithm.kt
    │       │   ├── Factorial.kt
    │       │   ├── FactorialAdvanced.kt
    │       │   ├── FactorialBigWithCache.kt
    │       │   ├── FactorialWithCache.kt
    │       │   ├── FizzBuzz.kt
    │       │   ├── KnuthMorrisPrattAlgorithm.kt
    │       │   ├── LevenshteinLengthAlgorithm.kt
    │       │   ├── MaxAlgorithm.kt
    │       │   ├── MinAlgorithm.kt
    │       │   ├── PalindromeAlgorithm.kt
    │       │   ├── ParenthesisCheckAlgorithm.kt
    │       │   ├── ReverseArrayAlgorithm.kt
    │       │   ├── SieveOfEratosthenesAlgorithm.kt
    │       │   ├── Sqrt.kt
    │       │   ├── StringEqualsHashAlgorithm.kt
    │       │   └── SwapAlgorithm.kt
    │       ├── search/
    │       │   ├── BinarySearch.kt
    │       │   └── LinearSearch.kt
    │       ├── sorting/
    │       │   ├── BubbleSort.kt
    │       │   ├── CountingSort.kt
    │       │   ├── InsertionSort.kt
    │       │   ├── MergeSort.kt
    │       │   ├── QuickSort.kt
    │       │   ├── RadixSort.kt
    │       │   ├── SelectionSort.kt
    │       │   └── TimSort.kt
    │       └── structures/
    │           ├── BinaryTree.kt
    │           ├── CircularLinkedList.kt
    │           ├── DoubleLinkedList.kt
    │           ├── DynamicArray.kt
    │           ├── Graph.kt
    │           ├── GraphWithWeights.kt
    │           ├── Matrix.kt
    │           ├── MaxHeap.kt
    │           ├── MinHeap.kt
    │           ├── Queue.kt
    │           ├── SingleLinkedList.kt
    │           ├── Stack1.kt
    │           └── Stack2.kt
    └── test/
        └── kotlin/
            ├── TestUtils.kt
            ├── design_patterns/
            │   ├── AbstractFactoryTest.kt
            │   ├── AdapterTest.kt
            │   ├── BridgeTest.kt
            │   ├── BuilderTest.kt
            │   ├── ChainOfResponsibilitiesTest.kt
            │   ├── CommandTest.kt
            │   ├── CompositeTest.kt
            │   ├── DecoratorTest.kt
            │   ├── FacadeTest.kt
            │   ├── FactoryMethodTest.kt
            │   ├── FlyweightTest.kt
            │   ├── InterpreterTest.kt
            │   ├── IteratorTest.kt
            │   ├── MediatorTest.kt
            │   ├── MementoTest.kt
            │   ├── ObserverTest.kt
            │   ├── PrototypeTest.kt
            │   ├── ProxyTest.kt
            │   ├── SingletonTest.kt
            │   ├── StateTest.kt
            │   ├── StrategyTest.kt
            │   ├── TemplateMethodTest.kt
            │   └── VisitorTest.kt
            ├── other/
            │   ├── BinaryDigitsCounterTest.kt
            │   ├── EuclidAlgorithmTest.kt
            │   ├── FactorialAdvancedTest.kt
            │   ├── FactorialBigWithCacheTest.kt
            │   ├── FactorialTest.kt
            │   ├── FactorialWithCacheTest.kt
            │   ├── FizzBuzzTest.kt
            │   ├── KnuthMorrisPrattAlgorithmTest.kt
            │   ├── LevenshteinLengthAlgorithmTest.kt
            │   ├── MaxAlgorithmTest.kt
            │   ├── MinAlgorithmTest.kt
            │   ├── PalindromeAlgorithmTest.kt
            │   ├── ParenthesisCheckAlgorithmTest.kt
            │   ├── ReverseArrayAlgorithmTest.kt
            │   ├── SieveOfEratosthenesAlgorithmTest.kt
            │   ├── SqrtTest.kt
            │   ├── StringEqualsHashAlgorithmTest.kt
            │   └── SwapAlgorithmTest.kt
            ├── search/
            │   ├── BinarySearchTest.kt
            │   └── LinearSearchTest.kt
            ├── sorting/
            │   ├── BubbleSortTest.kt
            │   ├── CountingSortTest.kt
            │   ├── InsertionSortTest.kt
            │   ├── MergeSortTest.kt
            │   ├── QuickSortTest.kt
            │   ├── RadixSortTest.kt
            │   ├── SelectionSortTest.kt
            │   └── TimSortTest.kt
            └── structures/
                ├── BinaryTreeTest.kt
                ├── CircularLinkedListTest.kt
                ├── DoubleLinkedListTest.kt
                ├── DynamicArrayTest.kt
                ├── GraphTest.kt
                ├── GraphWithWeightsTest.kt
                ├── MatrixTest.kt
                ├── MaxHeapTest.kt
                ├── MinHeapTest.kt
                ├── QueueTest.kt
                ├── SingleLinkedListTest.kt
                ├── Stack1Test.kt
                └── Stack2Test.kt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# IDE-specific stuff
idea/

# CMake
cmake-build-*/

# File-based project format
*.iws

# IntelliJ
out/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

### Kotlin ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*

### Gradle ###
.gradle
**/build/
!src/**/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties

# Cache of project
.gradletasknamecache

# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

### Gradle Patch ###
# Java heap dump
*.hprof

# End of https://www.toptal.com/developers/gitignore/api/intellij,gradle,kotlin

================================================
FILE: LICENSE.txt
================================================
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.


================================================
FILE: README.md
================================================
![Алгоритмы на Kotlin](/assets/algo_logo.png)

# 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:

1. <code>sorting</code> - sorting algorithms
2. <code>search</code> - search algorithms
3. <code>structures</code> - data structure (lists, arrays, stack, queue, binary trees, e.t.c)
4. <code>design-patterns</code> - design patterns
5. <code>other</code> - other algorithms (Levenshtein distance, Knut Morris Pratt algorithm, e.t.c)

For each code file, tests are made, which are located in the <code>test/kotlin</code> directory

Also, whenever possible, I add *javadoc* for each class, method, and file

Content:

1. package <code>design_patterns</code> - 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)
    * [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)
    * [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)
    * [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)

2. package <code>structures</code> - 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)
    * [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)
    * [Min-heap](/src/main/kotlin/structures/MinHeap.kt)
    * [Max-heap](/src/main/kotlin/structures/MaxHeap.kt)

3. package <code>sorting</code> - sorting algorithms
    * [Bubble sort](/src/main/kotlin/sorting/BubbleSort.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)

4. package <code>search</code> - search algorithms
    * [Binary search](/src/main/kotlin/search/BinarySearch.kt)
    * [Linear search](/src/main/kotlin/search/LinearSearch.kt)

5. package <code>other</code> - 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)
    * [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)
    * [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)

## 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.

      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.


================================================
FILE: README_ru.md
================================================
![Алгоритмы на Kotlin](/assets/algo_ru.png)

# Kotlin Algorithms and Design Patterns

В этом репозитории приведены наиболее распространенные алгоритмы, структуры данных и паттерны проектирования, написанные на языке программирования Kotlin.

Весь код разбит по отдельным пакетам:

1. <code>ru.sorting</code> - алгоритмы сортировки
2. <code>ru.search</code> - алгоритмы поиска
3. <code>ru.structures</code> - структуры данных (списки, массивы, стэк, очередь, бинарное дерево и др.)
4. <code>design-patterns</code> - паттерны проектирования
5. <code>ru.other</code> - другие алгоритмы (расстояние Левенштейна, алгоритм Кнута Морриса Пратта и т.д.)

Для каждого файла с кодом сделаны тесты, которые находятся в директории <code>test/kotlin</code>

Также по возможности я добавляю *javadoc* для каждого класса, метода и файла

Структура:

1. пакет <code>ru.design_patterns</code> - паттерны проектирования
    * [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)
    * [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)
    * [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)
    * [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)

2. пакет <code>ru.structures</code> - структуры данных
    * [Бинарное дерево](/src/main/kotlin/structures/BinaryTree.kt)
    * [Стэк 1-ая реализация](/src/main/kotlin/structures/Stack1.kt)
    * [Стэк 2-ая реализация](/src/main/kotlin/structures/Stack2.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)
    * [Min-куча](/src/main/kotlin/structures/MinHeap.kt)
    * [Max-куча](/src/main/kotlin/structures/MaxHeap.kt)

3. пакет <code>ru.sorting</code> - алгоритмы сортировки
    * [Пузырьковая сортировка](/src/main/kotlin/sorting/BubbleSort.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)

4. пакет <code>ru.search</code> - алгоритмы поиска
    * [Бинарный поиск](/src/main/kotlin/search/BinarySearch.kt)
    * [Линейный поиск](/src/main/kotlin/search/LinearSearch.kt)

5. пакет <code>ru.other</code> - другие алгоритмы
    * [Конечный автомат](/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)
    * [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/Sqrt.kt)
    * [Сравнение строк с помощью хэша](/src/main/kotlin/other/StringEqualsHashAlgorithm.kt)
    * [Алгоритм обмена двух переменных](/src/main/kotlin/other/SwapAlgorithm.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.


================================================
FILE: build.gradle.kts
================================================
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")
}

================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: gradle.properties
================================================
kotlin.code.style=official

================================================
FILE: gradlew
================================================
#!/bin/sh

#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

##############################################################################
#
#   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/.
#
##############################################################################

# 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
done

APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

APP_NAME="Gradle"
APP_BASE_NAME=${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

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 ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
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
    else
        JAVACMD=$JAVA_HOME/bin/java
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    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
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
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 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" )

    # 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" )
        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
    done
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.
#

eval "set -- $(
        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
        xargs -n1 |
        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
        tr '\n' ' '
    )" '"$@"'

exec "$JAVACMD" "$@"


================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem      https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: settings.gradle.kts
================================================
rootProject.name = "Kotlin-Algorithms-and-Design-Patterns"

================================================
FILE: src/main/kotlin/design_patterns/Abstract Factory.kt
================================================
package design_patterns

/**
 *
 * Abstract factory is a generative design pattern that allows
 *
 * you to create families of related objects without being tied to
 *
 * the specific classes of objects you create.
 *
 */

interface Button {
    fun draw() {}
}

class AndroidButton : Button
class IOSButton : Button

interface Text {
    fun draw() {}
}

class AndroidText : Text
class IOSText : Text

interface ButtonFactory {
    fun createButton() : Button
    fun createText() : Text
}

class AndroidButtonFactory : ButtonFactory {
    override fun createButton() : Button = AndroidButton()
    override fun createText(): Text = AndroidText()
}

class IOSButtonFactory : ButtonFactory {
    override fun createButton() : Button = IOSButton()
    override fun createText(): Text = IOSText()
}


================================================
FILE: src/main/kotlin/design_patterns/Adapter.kt
================================================
package design_patterns

/**
 *
 * Adapter is a structural design pattern that allows objects with incompatible interfaces to work together
 *
 */

interface EnglishSpeaker {
    fun speakEnglish(): String
}

class EnglishSpeakerImpl : EnglishSpeaker {
    override fun speakEnglish(): String {
        return "Hello, friend!"
    }
}

interface SpainSpeaker {
    fun speakSpanish(): String
}

class SpainSpeakerAdapter(private val englishSpeaker: EnglishSpeaker) : SpainSpeaker {

    override fun speakSpanish(): String =
        when (englishSpeaker.speakEnglish()) {
            "Hello, friend!" -> "Hola, amigo!"
            else -> "No te entiendo"
        }

}

================================================
FILE: src/main/kotlin/design_patterns/Bridge.kt
================================================
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<String>()
    protected val circles = mutableListOf<String>()

    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)
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Builder.kt
================================================
package design_patterns

/**
 *
 * Builder is is a generative design pattern that is used to create complex objects,
 *
 * separates the construction of an object from its representation
 *
 */

/**
 * 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 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
        }

        fun callTimeout(timeout: Int) = apply {
            // we can add some checks such as:
            // if (timeout < 0) throw IllegalArgumentException("Uncorrected timeout: $timeout")
            callTimeout = timeout
        }

        fun connectTimeout(timeout: Int) = apply {
            connectTimeout = timeout
        }

        fun readTimeout(timeout: Int) = apply {
            readTimeout = timeout
        }

        fun writeTimeout(timeout: Int) = apply {
            writeTimeout = timeout
        }

        fun build() = HttpConnectionClient1(dnsServerAddress, callTimeout, connectTimeout, readTimeout, writeTimeout)

    }

}

/**
 * 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()

    companion object {
        fun newBuilder() = HttpConnectionClient2().Builder()
    }

    inner class Builder {

        fun dnsServerAddress(address: String) = apply {
            dnsServerAddress = address
        }

        fun callTimeout(timeout: Int) = apply {
            // we can add some checks such as:
            // if (timeout < 0) throw IllegalArgumentException("Uncorrected timeout: $timeout")
            callTimeout = timeout
        }

        fun connectTimeout(timeout: Int) = apply {
            connectTimeout = timeout
        }

        fun readTimeout(timeout: Int) = apply {
            readTimeout = timeout
        }

        fun writeTimeout(timeout: Int) = apply {
            writeTimeout = timeout
        }

        fun build() = this@HttpConnectionClient2
    }

}

/**
 * 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
) {
    override fun toString() = """
        dns -> $dnsServerAddress
        call timeout -> $callTimeout
        connect timeout -> $connectTimeout
        read timeout -> $readTimeout
        write timeout -> $writeTimeout
    """.trimIndent()
}

================================================
FILE: src/main/kotlin/design_patterns/Command.kt
================================================
package design_patterns

/**
 *
 * Command is a behavioral pattern that encapsulates a request to perform an action as a separate object
 *
 */

// 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 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
    }

}

// this command encapsulates a request to decrease the volume in StereoSystem
class DecreaseVolumeCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand {

    override fun execute() {
        stereoSystem.decreaseVolume()
    }

    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()
    }

    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<String, StereoSystemCommand> = mapOf()) {

    // we only know about StereoSystemCommand interface
    private val commandHistory = mutableListOf<StereoSystemCommand>()

    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()
        }
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Composite.kt
================================================
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<MenuComponent>()

    // 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()

}

================================================
FILE: src/main/kotlin/design_patterns/Decorator.kt
================================================
package design_patterns

/**
 *
 * 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,
 *
 * the old object is passed through the constructor
 *
 */

interface MyPrinter {
    fun printedText() : String
}

// just returns "Hello"
class HelloPrinter : MyPrinter {
    override fun printedText() : String {
        return "Hello"
    }
}

// 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
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
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
class ExclamationPrinter(private val printer: MyPrinter) : MyPrinter {
    override fun printedText() : String {
        return "${printer.printedText()}!"
    }
}

================================================
FILE: src/main/kotlin/design_patterns/Facade.kt
================================================
package design_patterns

/**
 *
 * Facade is a structural design pattern that simplifies the interface to a group of interfaces
 *
 * with a more complex implementation
 *
 */

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<GoodsEntity>()

    fun save(goods: List<GoodsEntity>) {
        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
)

class CategoryDatabase {
    private val cachedCategories = mutableListOf<CategoryEntity>()

    fun save(goods: List<CategoryEntity>) {
        cachedCategories.addAll(goods)
    }

    fun read() = cachedCategories
}

class CategoryNetworkService {

    fun fetch() = listOf(
        CategoryEntity(
            id = 1,
            name = "Books"
        )
    )

}

data class GoodsResult(
    val goods: List<GoodsEntity>,
    val categories: List<CategoryEntity>
)

// 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
) {

    // 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)
        }

        val categories = categoryDatabase.read().toMutableList()
        if (categories.isEmpty()) {
            val networkCategories = categoryNetworkService.fetch()
            categoryDatabase.save(networkCategories)
            categories.addAll(networkCategories)
        }

        return GoodsResult(
            goods = goods,
            categories = categories
        )
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Factory Method.kt
================================================
package design_patterns

/**
 *
 * A factory method is a generic design pattern that defines
 *
 * a common interface for creating objects in a superclass,
 *
 * allowing subclasses to change the type of objects they create.
 *
 */

abstract class House(private val address: String, private val price: Int) {

    override fun toString() = """
        address = $address
        price = $price
    """.trimIndent()

}

// 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 {

    private val alreadyBuiltHouses = mutableListOf<House>()

    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
    }

    // the subclasses define a specific implementation
    protected abstract fun buildHouse(address: String, cost: HouseCompanyCost): House

    enum class HouseCompanyCost { CHEAP, AVERAGE, EXPENSIVE }

}

// 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)
    }

}

// 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)
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Flyweight.kt
================================================
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<Tree>()

    // mutable state (coordinates) are stored outside the object
    private val placedTrees = mutableListOf<Triple<Int, Int, Tree>>()

    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
    )

}

================================================
FILE: src/main/kotlin/design_patterns/Interpreter.kt
================================================
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<String, Int>()

    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)
        )
    }
}

================================================
FILE: src/main/kotlin/design_patterns/Iterator.kt
================================================
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<T> {
    fun hasNext(): Boolean
    fun next(): T
}

interface BoxIterable<T> {
    fun iterator(): BoxIterator<T>
}

class GiftBox(private val presents: Array<String>) : BoxIterable<String> {

    override fun iterator() = object : BoxIterator<String> {
        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
        }
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Mediator.kt
================================================
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<String>()
    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)
    }
}

================================================
FILE: src/main/kotlin/design_patterns/Memento.kt
================================================
package design_patterns

/**
 *
 * Memento is a behavioral design pattern that allows without violating encapsulation to capture
 *
 * and save the internal state of an object so that it can be restored to this state later
 *
 */


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
class AndroidSystem {

    private var savedBundle: Bundle = Bundle("")

    fun saveBundle(bundle: Bundle) {
        savedBundle = bundle
    }

    fun restoreBundle() = savedBundle
}

// TextView is an Android component that draws text on the screen
class TextView {

    private var currentText: String = ""

    fun setText(text: String) {
        currentText = text
    }

    fun text() = currentText

    fun draw() {
        println(currentText)
    }

    // saves the current state of TextView before re-creating it
    fun onSaveInstanceState(): Bundle {
        return Bundle(currentText)
    }

    // restores the current state after TextView is recreated
    fun onRestoreInstanceState(bundle: Bundle) {
        currentText = bundle.str
    }
}

================================================
FILE: src/main/kotlin/design_patterns/Observer.kt
================================================
package design_patterns

/**
 *
 * Observer is is a behavioral design pattern that defines a one-to-many relationship between objects
 *
 * such that when the state of one object changes all dependent objects are automatically notified and updated
 *
 */

fun interface PonyObserver {
    fun update(item: List<String>)
}

interface PonyObservable {
    fun addObserver(observer: PonyObserver)
    fun removeObserver(observer: PonyObserver)
    fun notifyObservers()
}

// PonyList contains some data and when it changes we will notify observers
class PonyList : PonyObservable {

    private val ponies = mutableListOf<String>()

    private val observers = mutableSetOf<PonyObserver>()

    fun add(pony: String) {
        ponies.add(pony)
        // notify observers that the data has changed
        notifyObservers()
    }

    override fun addObserver(observer: PonyObserver) {
        observers.add(observer)
    }

    override fun removeObserver(observer: PonyObserver) {
        observers.remove(observer)
    }

    override fun notifyObservers() {
        observers.forEach { observer -> observer.update(ponies) }
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Prototype.kt
================================================
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
    }

}



================================================
FILE: src/main/kotlin/design_patterns/Proxy.kt
================================================
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")
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Singleton.kt
================================================
package design_patterns

/**
 *
 * Singleton is a generative design pattern that guarantees the existence of one instance of a class
 *
 * and provides a global access point to it
 *
 */

object SQLiteDatabase {

    // 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<String> {
        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
        }
    }

}

================================================
FILE: src/main/kotlin/design_patterns/State.kt
================================================
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
    }

}

================================================
FILE: src/main/kotlin/design_patterns/Strategy.kt
================================================
package design_patterns

/**
 *
 * Strategy is a behavioral design pattern used to define a family of algorithms,
 *
 * encapsulate each one and make them interchangeable
 *
 */

// encapsulates the filtering algorithm
interface FoodFilterStrategy {
    fun filter(items: List<FoodEntity>): List<FoodEntity>
}

class OnlyChipsFilterStrategy : FoodFilterStrategy {
    override fun filter(items: List<FoodEntity>): List<FoodEntity> {
        return items.filter { it.category == "chips" }
    }
}

class OnlyChocolateFilterStrategy : FoodFilterStrategy {
    override fun filter(items: List<FoodEntity>): List<FoodEntity> {
        return items.filter { it.category == "chocolate" }
    }
}

class PriceFilterStrategy(private val price: Int) : FoodFilterStrategy {
    override fun filter(items: List<FoodEntity>): List<FoodEntity> {
        return items.filter { it.price >= price }
    }
}

class SearchWordFilterStrategy(private val search: String) : FoodFilterStrategy {
    override fun filter(items: List<FoodEntity>): List<FoodEntity> {
        return items.filter { it.title.contains(search, ignoreCase = true) }
    }
}

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<FoodEntity> {
        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"
            )
        )

}



================================================
FILE: src/main/kotlin/design_patterns/Template Method.kt
================================================
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<String>,
    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"

}

================================================
FILE: src/main/kotlin/design_patterns/Visitor.kt
================================================
package design_patterns

/**
 *
 * Visitor is a behavioral design pattern that allows you to add a new operation
 *
 * to an entire class hierarchy without changing the code of these classes.
 *
 */

interface PonyVisitor {
    fun visitPonies(vararg ponies: LittlePony) : String
    fun visitEarthPony(pony: EarthPony) : String
    fun visitUnicorn(pony: Unicorn) : String
    fun visitPegasus(pony: Pegasus) : String
}

class JsonVisitor : PonyVisitor {

    override fun visitPonies(vararg ponies: LittlePony) : String {
        val poniesString = ponies.joinToString(",\n") { pony -> pony.accept(this) }
        return "[$poniesString]"
    }

    override fun visitEarthPony(pony: EarthPony): String {
        return """
            {
                "what" : "earth pony",
                "name" : "${pony.name()}",
                "cutie_mark" : "${pony.cutie()}
            }
        """.trimIndent()
    }

    override fun visitUnicorn(pony: Unicorn): String {
        return """
            {
                "what" : "unicorn",
                "name" : "${pony.name()}",
                "cutie_mark" : "${pony.cutie()}
            }
        """.trimIndent()
    }

    override fun visitPegasus(pony: Pegasus): String {
        return """
            {
                "what" : "pegasus",
                "name" : "${pony.name()}",
                "cutie_mark" : "${pony.cutie()}
            }
        """.trimIndent()
    }

}

class XmlVisitor : PonyVisitor {

    override fun visitPonies(vararg ponies: LittlePony) : String {
        val poniesString = ponies.joinToString("\n") { pony -> pony.accept(this) }
        return "<ponies>\n$poniesString\n</ponies>"
    }

    override fun visitEarthPony(pony: EarthPony): String {
        return """
            <pony>
                <what>earth pony</what>
                <name>${pony.name()}</name>
                <cutie_mark>${pony.cutie()}</cutie_mark>
            </pony>
        """.trimIndent()
    }

    override fun visitUnicorn(pony: Unicorn): String {
        return """
            <pony>
                <what>unicorn</what>
                <name>${pony.name()}</name>
                <cutie_mark>${pony.cutie()}</cutie_mark>
            </pony>
        """.trimIndent()
    }

    override fun visitPegasus(pony: Pegasus): String {
        return """
            <pony>
                <what>pegasus</what>
                <name>${pony.name()}</name>
                <cutie_mark>${pony.cutie()}</cutie_mark>
            </pony>
        """.trimIndent()
    }

}

abstract class LittlePony(private val name: String, private val cutieMark: String) {

    fun name() = name
    fun cutie() = cutieMark

    abstract fun accept(visitor: PonyVisitor) : String
}

class EarthPony(name: String, cutieMark: String) : LittlePony(name, cutieMark) {
    override fun accept(visitor: PonyVisitor) = visitor.visitEarthPony(this)
}

class Unicorn(name: String, cutieMark: String) : LittlePony(name, cutieMark) {
    override fun accept(visitor: PonyVisitor) = visitor.visitUnicorn(this)

}

class Pegasus(name: String, cutieMark: String) : LittlePony(name, cutieMark) {
    override fun accept(visitor: PonyVisitor) = visitor.visitPegasus(this)
}



================================================
FILE: src/main/kotlin/design_patterns/Сhain Of Responsibilities.kt
================================================
package design_patterns

/**
 *
 * Chain of responsibility is a behavioral design pattern that allows requests to be sent sequentially
 *
 * through a chain of handlers
 *
 */

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
abstract class Block(private val factor: BlockFactor) {
    fun mayMine(factor: BlockFactor) = this.factor.ordinal <= factor.ordinal
}

// the blocks are from the game
class StoneBlock: Block(BlockFactor.ONE)
class DiamondBlock: Block(BlockFactor.TWO)
class ObsidianBlock: Block(BlockFactor.THREE)

abstract class Pickaxe(private val factor: BlockFactor) {

    private var nextPickaxe: Pickaxe? = null

    fun changeNextPickaxe(pickaxe: Pickaxe) {
        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
    }

}

// the pickaxes are from the game
class StonePickaxe: Pickaxe(BlockFactor.ONE)

class IronPickaxe: Pickaxe(BlockFactor.TWO)

class DiamondPickaxe: Pickaxe(BlockFactor.THREE)

================================================
FILE: src/main/kotlin/other/BinaryDigitsCounter.kt
================================================
package other

/**
 *
 * This algorithm counts the number of ones and zeros in a binary string
 *
 * and implemented on a finite state machine
 *
 */

class BinaryDigitsCounter {
    
    data class Result(private val ones: Int = 0, private val zeros: Int = 0)

    // represents two states
    private enum class State { 
        ONE, ZERO 
    }

    fun compute(binaryString: String): Result { // 1010010011
        if (binaryString.isEmpty()) {
            return Result()
        }

        // define initial state
        var currentState = if (binaryString.first() == '1') State.ONE else State.ZERO

        var onesCount = 0
        var zerosCount = 0

        binaryString.forEach { symbol ->
            // we use 'when' statement to toggle the state
            when (currentState) {
                State.ONE -> {
                    if (symbol == '0') {
                        zerosCount++
                        // move to another state
                        currentState = State.ZERO
                    } else {
                        onesCount++
                    }
                }
                State.ZERO -> {
                    if (symbol == '1') {
                        onesCount++
                        // move to another state
                        currentState = State.ONE
                    } else {
                        zerosCount++
                    }
                }
            }
        }

        return Result(onesCount, zerosCount)
    }

}

================================================
FILE: src/main/kotlin/other/EuclidAlgorithm.kt
================================================
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
    }

}

================================================
FILE: src/main/kotlin/other/Factorial.kt
================================================
package other

/**
 *
 * Algorithm for finding the factorial of a positive number n
 *
 */

class Factorial {

    /**
     * iterative method
     * worst time: O(n)
     * amount of memory: O(1)
     */
    fun compute(number: Int) : Int {
        if (number <= 1) {
            return 1
        }

        var result = 1
        for (i in 2..number) {
           result *= i
        }
        return result
    }

    /**
     * recursive method
     * worst time: O(n)
     * amount of memory: O(n) - stack for recursion
     */
    fun computeRecursive(number: Int) : Int {
        return if (number <= 1) {
            1
        } else {
            number * computeRecursive(number - 1)
        }
    }

    // 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)

}

================================================
FILE: src/main/kotlin/other/FactorialAdvanced.kt
================================================
package other

import java.math.BigInteger

/**
 *
 * This algorithm is taken from Google Guava library
 *
 */

class FactorialAdvanced {

    // precomputed factorials
    private val factorials = longArrayOf(
        1L,
        1L,
        1L * 2,
        1L * 2 * 3,
        1L * 2 * 3 * 4,
        1L * 2 * 3 * 4 * 5,
        1L * 2 * 3 * 4 * 5 * 6,
        1L * 2 * 3 * 4 * 5 * 6 * 7,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18,
        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19,
        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 {
        if (n <= 0) {
            return BigInteger.ZERO
        }

        if (n < factorials.size) {
            return BigInteger.valueOf(factorials[n])
        }

        // pre-allocate space for our list of intermediate BigIntegers.
        val approxSize = divide(n * log2Celling(n), Long.SIZE_BITS)
        val bigNumbers = ArrayList<BigInteger>(approxSize)

        // 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()
        number = number shr shift

        // 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.
        var nextPowerOfTwo = 1 shl bits - 1

        // 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.
            if ((num and nextPowerOfTwo) != 0) {
                nextPowerOfTwo = nextPowerOfTwo shl 1
                bits++
            }
            // get rid of the 2s in num.
            val tz = num.toLong().countTrailingZeroBits()
            val normalizedNum = (num shr tz).toLong()
            shift += tz
            // 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) {
                bigNumbers.add(BigInteger.valueOf(number))
                number = 1
                numberBits = 0
            }
            number *= normalizedNum
            numberBits = log2Floor(number) + 1
        }
        // check for leftovers.
        if (number > 1) {
            bigNumbers.add(BigInteger.valueOf(number))
        }
        // efficiently multiply all the intermediate products together.
        return listNumbers(bigNumbers).shiftLeft(shift)
    }

    /**
     * Returns the result of dividing p by q, rounding using the celling
     *
     * @throws ArithmeticException if q == 0
     */
    private fun divide(number: Int, divider: Int): Int {
        if (divider == 0) {
            throw ArithmeticException("/ by zero") // for GWT
        }
        val div = number / divider
        val rem = number - divider * div // equal to number % divider
        if (rem == 0) {
            return div
        }
        val signedNumber = 1 or (number xor divider shr Int.SIZE_BITS - 1)
        val increment = signedNumber > 0
        return if (increment) div + signedNumber else div
    }

    private fun listNumbers(numbers: List<BigInteger>, start: Int = 0, end: Int = numbers.size): BigInteger {
        return when (end - start) {
            0 -> BigInteger.ONE
            1 -> numbers[start]
            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.
                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.
    private fun log2Celling(number: Int): Int {
        return Int.SIZE_BITS - (number - 1).countLeadingZeroBits()
    }

    // 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()
    }

}

================================================
FILE: src/main/kotlin/other/FactorialBigWithCache.kt
================================================
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<Int, BigInteger>()

    fun compute(number: Int) : BigInteger {
        if (number <= 1) {
            return BigInteger.ONE
        }

        val cachedResult = cache[number]
        if (cachedResult != null) {
            return cachedResult
        }

        var result = BigInteger.ONE
        for (i in 2..number) {
            result = result.multiply(i.toBigInteger())
            cache[i] = result
        }
        return result
    }

}

================================================
FILE: src/main/kotlin/other/FactorialWithCache.kt
================================================
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<Int, Int>()

    fun compute(number: Int) : Int {
        if (number <= 1) {
            return 1
        }

        val cachedResult = cache[number]
        if (cachedResult != null) {
            return cachedResult
        }

        var result = 1
        for (i in 2..number) {
            result *= i
            cache[i] = result
        }
        return result
    }

}

================================================
FILE: src/main/kotlin/other/FizzBuzz.kt
================================================
package other

/**
 * The simplest FizzBuzz game
 *
 * description: the player says numbers in sequence, provided:
 *  - if the number is divisible by 3 it says fizz
 *  - if the number is divisible by 5 it says buzz
 *  - if the number is divisible by both 3 and 5, it says FizzBuzz
 *  - otherwise, the player calls the number itself
 */

class FizzBuzz {

    // determines what to say for a number in the FizzBuzz game and returns Fizz, Buzz, FizzBuzz or number
    fun compute(number: Int) : String {
        return when {
            number % 3 == 0 && number % 5 == 0 -> "FizzBuzz"
            number % 3 == 0 -> "Fizz"
            number % 5 == 0 -> "Buzz"
            else -> number.toString()
        }
    }

}

================================================
FILE: src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt
================================================
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<Int> {
        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 = "#"
    }

}

================================================
FILE: src/main/kotlin/other/LevenshteinLengthAlgorithm.kt
================================================
package other

import java.lang.Integer.min

/**
 *
 * Algorithm for determining the Levenshtein distance
 *
 */

class LevenshteinLengthAlgorithm {

    fun compute(str1: String, str2: String) : Int {
        val matrix = Array(str1.length + 1) {
            Array(str2.length + 1) { 0 }
        }

        for (i in 0..str1.length) {
            matrix[i][0] = i
        }

        for (i in 0..str2.length) {
            matrix[0][i] = i
        }

        for (i in 1..str1.length) {
            for (j in 1..str2.length) {
                if (str1[i - 1] == str2[j - 1]) {
                    matrix[i][j] = matrix[i - 1][j - 1]
                } else {
                    matrix[i][j] = min(min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i - 1][j - 1]) + 1
                }
            }
        }

        return matrix[str1.length][str2.length]
    }

}

================================================
FILE: src/main/kotlin/other/MaxAlgorithm.kt
================================================
package other

import java.lang.IllegalArgumentException

/**
 *
 * Algorithm for finding the maximum value from a list
 *
 */

class MaxAlgorithm {

    fun <T : Comparable<T>> compute(items: List<T>) : T {
        if (items.isEmpty()) {
            throw IllegalArgumentException("items list is empty!")
        }
        var max = items[0]
        for (i in 1 until items.size) {
            if (max < items[i]) {
                max = items[i]
            }
        }
        return max
    }

    /**
     * returns the maximum element from the list recursively
     */
    fun <T : Comparable<T>> computeRecursive(items: List<T>) : T {
        if (items.isEmpty()) {
            throw IllegalArgumentException("items list is empty!")
        }
        if (items.size == 1) {
            return items.first()
        }
        val first = items.first()
        val others = items.subList(1, items.size)

        val max = computeRecursive(others)

        return if (first > max) first else max
    }

}

================================================
FILE: src/main/kotlin/other/MinAlgorithm.kt
================================================
package other

import java.lang.IllegalArgumentException

/**
 *
 * Algorithm for finding the minimum value from a list
 *
 */

class MinAlgorithm {

    fun <T : Comparable<T>> compute(items: List<T>) : T {
        if (items.isEmpty()) {
            throw IllegalArgumentException("items list is empty!")
        }
        var min = items[0]
        for (i in 1 until items.size) {
            if (min > items[i]) {
                min = items[i]
            }
        }
        return min
    }

    fun <T : Comparable<T>> computeRecursive(items: List<T>) : T {
        if (items.isEmpty()) {
            throw IllegalArgumentException("items list is empty!")
        }
        if (items.size == 1) {
            return items.first()
        }
        val first = items.first()
        val others = items.subList(1, items.size)

        val min = computeRecursive(others)

        return if (first < min) first else min
    }

}

================================================
FILE: src/main/kotlin/other/PalindromeAlgorithm.kt
================================================
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()
    }

}

================================================
FILE: src/main/kotlin/other/ParenthesisCheckAlgorithm.kt
================================================
package other

/**
 *
 * Algorithm for checking a string for correct placement of parentheses using stack
 *
 * ([]) - correctly
 * ()(){} - correctly
 * (() - incorrectly
 * (())[][]}{ - incorrectly
 *
 */

class ParenthesisCheckAlgorithm {

    fun check(code: String = DEFAULT_CODE): Boolean {
        // we use a regular kotlin list to create a stack
        val stack = mutableListOf<Char>()

        var index = 0
        while (index < code.length) {

            when (val symbol = code[index]) {
                '(', '{', '[' -> stack.add(symbol)
                ')', '}', ']' -> {
                    val value = bracketRelations[stack.removeLastOrNull()]
                    if (symbol != value) {
                        return false
                    }
                }
            }

            index++
        }

        return stack.isEmpty()
    }

    companion object {
        // the correct C program
        private const val DEFAULT_CODE = """
            void main() {
                printf("Hello, World!");
            }
        """

        private val bracketRelations = mapOf('(' to ')', '{' to '}', '[' to ']')
    }

}

================================================
FILE: src/main/kotlin/other/ReverseArrayAlgorithm.kt
================================================
package other

/**
 *
 * Algorithm for reversing the order of an array
 *
 * complexity: O(n/2) + O(n)
 *
 */

class ReverseArrayAlgorithm {

    fun <T> compute(array: Array<T>) {
        val size = array.size
        for (index in 0 until size / 2) {
            array[index] = array[size - index - 1].apply {
                array[size - index - 1] = array[index]
            }
        }
    }

}

================================================
FILE: src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt
================================================
package other

/**
 *
 * The sieve of Eratosthenes allows you to efficiently calculate a series of prime numbers
 *
 * algorithm complexity: nlog(logn) operations
 *
 */

class SieveOfEratosthenesAlgorithm {

    // computes a series of primes up to the maximum value and returns a list of prime numbers
    fun compute(maxNumber: Int) : List<Int> {
        val numbers = Array(maxNumber + 1) { index -> index >= 2 }

        var x = 2
        while (x * x <= maxNumber) {
            if (numbers[x]) {
                for (y in x * x..maxNumber step x) {
                    numbers[y] = false
                }
            }
            x++
        }

        val primes = mutableListOf<Int>()

        numbers.forEachIndexed { number, isPrime ->
            if (isPrime) {
                primes.add(number)
            }
        }

        return primes
    }

}

================================================
FILE: src/main/kotlin/other/Sqrt.kt
================================================
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
 *
 */

class Sqrt {

    // calculates the root of a number and returns result
    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
        }
        return value
    }

}

================================================
FILE: src/main/kotlin/other/StringEqualsHashAlgorithm.kt
================================================
package other

/**
 *
 * Algorithm for 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()

    /**
     *
     * computes the hash of a string according to the formula:
     *
     * hash(abc) = a.code * primeCoefficient⁰ + b.code * primeCoefficient¹ + c.code * primeCoefficient²
     *
     */
    private fun String.hash() : Int {
        var result = 0
        var factor = 1
        forEach { symbol ->
            result += symbol.code * factor
            factor *= PRIME_COEFFICIENT
        }
        // the hash can exceed the maximum Int value, so we limit it
        return result.mod(Int.MAX_VALUE)
    }

    companion object {
        /**
         *
         * I chose the nearest prime number for the size of the alphabet
         *
         * my alphabet is [a-z] [A-Z] ! , .
         *
         * size of the alphabet = 26 + 26 + 3 = 55 (is not prime)
         *
         */
        private const val PRIME_COEFFICIENT = 53
    }
}

================================================
FILE: src/main/kotlin/other/SwapAlgorithm.kt
================================================
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<Int>, 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<Int>, 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<Int>, 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<Int>, oldIndex: Int, newIndex: Int) {
        if (oldIndex in array.indices && newIndex in array.indices) {
            array[oldIndex] = array[newIndex].apply {
                array[newIndex] = array[oldIndex]
            }
        }
    }

}

================================================
FILE: src/main/kotlin/search/BinarySearch.kt
================================================
package search

/**
 *
 * Binary search algorithm only works for sorted lists and arrays
 *
 * best time: 1
 * worst 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 <T : Comparable<T>> search(array: Array<T>, 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 <T : Comparable<T>> searchRecursive(array: Array<T>, 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 <T : Comparable<T>> leftBound(array: Array<T>, element: T) : Int {
        if (array.isEmpty()) return 0

        var left = -1
        var right = array.size
        while ((right - left) > 1) {
            val middle = left + (right - left) / 2
            if (element > array[middle]) {
                left = middle
            } else {
                right = middle
            }
        }
        return left
    }

    // finds the right border index to insert an element into a sorted array
    fun <T : Comparable<T>> rightBound(array: Array<T>, element: T) : Int {
        if (array.isEmpty()) return -1

        var left = -1
        var right = array.size
        while ((right - left) > 1) {
            val middle = (right + left) / 2
            if (element > array[middle]) {
                left = middle
            } else {
                right = middle
            }
        }
        return right
    }

}

================================================
FILE: src/main/kotlin/search/LinearSearch.kt
================================================
package search

/**
 *
 * Linear search algorithm
 *
 * best time: 1
 * worst time: n
 * amount of memory: 1
 *
 */

class LinearSearch {

    fun <T : Comparable<T>> search(array: Array<T>, element: T) : Int {
        var index = 0
        while (index < array.size) {
            if (element == array[index]) {
                return index
            }
            index++
        }
        return -1
    }

}

================================================
FILE: src/main/kotlin/sorting/BubbleSort.kt
================================================
package sorting

/**
 *
 * 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
 *
 */

class BubbleSort {

    /**
     * worst time: n²
     * best time: n²
     * average time: n²
     *
     * amount of memory: 1
     */
    fun <T : Comparable<T>> sort(array: Array<T>) {
        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]
                    array[j + 1] = array[j]
                    array[j] = tmp
                }
            }
        }
    }

    /**
     * worst time: n²
     * best time: n
     * average time: n²
     *
     * amount of memory: 1
     */
    fun <T : Comparable<T>> sortImproved(array: Array<T>) {
        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
                }
            }
            if (isSorted) break
        }
    }

}


================================================
FILE: src/main/kotlin/sorting/CountingSort.kt
================================================
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<Int>, 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++
        }
    }

}

================================================
FILE: src/main/kotlin/sorting/InsertionSort.kt
================================================
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.
 *
 * worst time: n²
 * best time: n
 * average time: n²
 *
 * amount of time: 1
 *
 */

class InsertionSort {

    fun <T : Comparable<T>> sort(array: Array<T>) {
        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
        }
    }

}


================================================
FILE: src/main/kotlin/sorting/MergeSort.kt
================================================
package sorting

/**
 *
 * Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945
 *
 * 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.
 *
 */

class MergeSort {

    /**
     * worst time: n * log(n)
     * best time: n * log(n)
     * average time: n * log(n)
     *
     * amount of memory: n
     */
    fun <T : Comparable<T>> sort(array: Array<T>) {
        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++
                }

                while (i < middle) {
                    temporaryArray[k] = array[i]
                    i++
                    k++
                }

                while (j < right) {
                    temporaryArray[k] = array[j]
                    j++
                    k++
                }

                i = left
                while (i < right) {
                    array[i] = temporaryArray[i]
                    i++
                }

                left += windowSize * 2
            }

            windowSize *= 2
        }
    }

    /**
     * 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<Int>) {
        val arraySize = array.size

        if (arraySize < 2)
            return

        val middle = arraySize / 2

        val left = Array(middle) { 0 }
        val right = Array(arraySize - middle) { 0 }

        var i = 0
        while (i < middle) {
            left[i] = array[i]
            i++
        }

        while (i < arraySize) {
            right[i - middle] = array[i]
            i++
        }

        sortRecursive(left)
        sortRecursive(right)

        val leftSize = left.size
        val rightSize = right.size

        i = 0
        var j = 0
        var k = 0
        while (i < leftSize && j < rightSize) {
            if (left[i]  <= right[j]) {
                array[k] = left[i]
                i++
            } else {
                array[k] = right[j]
                j++
            }
            k++
        }

        while (i < leftSize) {
            array[k] = left[i]
            i++
            k++
        }

        while (j < rightSize) {
            array[k] = right[j]
            j++
            k++
        }
    }

}

================================================
FILE: src/main/kotlin/sorting/QuickSort.kt
================================================
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.
 *
 *
 * worst time: n²
 * best time: n * log(n)
 * average time: n * log(n)
 *
 * amount of memory: n
 *
 */

class QuickSort {

    fun <T : Comparable<T>> sort(array: Array<T>, start: Int = 0, end: Int = array.size - 1) {
        if (array.isEmpty()) return
        if (start >= end) return

        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) {
                val tmp = array[i]
                array[i] = array[j]
                array[j] = tmp
                i++
                j--
            }
        }

        if (i < end) sort(array, i, end)
        if (0 < j) sort(array, start, j)
    }

}

================================================
FILE: src/main/kotlin/sorting/RadixSort.kt
================================================
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.
 *
 * worst time: <number of bits of an integer> * n
 *
 * amount of memory: 2 * n
 */

class RadixSort {

    fun sort(array: Array<Int>) {
        val arraySize = array.size
        val arrayOfZeroBits = Array(arraySize) { 0 }
        val arrayOfOneBits = Array(arraySize) { 0 }

        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 (index in 0 until size1) {
                array[index] = arrayOfZeroBits[index]
            }

            for (index in 0 until size2) {
                array[size1 + index] = arrayOfOneBits[index]
            }
        }
    }

}

================================================
FILE: src/main/kotlin/sorting/SelectionSort.kt
================================================
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.
 *
 * worst time: n²
 * best time: n²
 * average time: n²
 *
 * amount of memory: 1
 *
 */

class SelectionSort {

    fun <T : Comparable<T>> sort(array: Array<T>) {
        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
                }
            }
            if (min != i) {
                val tmp = array[i]
                array[i] = array[min]
                array[min] = tmp
            }
        }
    }

}


================================================
FILE: src/main/kotlin/sorting/TimSort.kt
================================================
package sorting

import kotlin.math.min

/**
 *
 * 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
 * average time: n * log(n)
 *
 * amount of memory: n
 *
 */

class TimSort {

    fun sort(array: Array<Int>) {
        val arraySize = array.size
        val minRunSize = minRunSize(arraySize)

        var i = 0
        while (i < arraySize) {
            insertionSort(array, i, min(i + minRunSize - 1, arraySize - 1))
            i += minRunSize
        }

        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
            }
            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
        }

        return size + result
    }

    private fun insertionSort(array: Array<Int>, 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 merge(array: Array<Int>, 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++
        }

        i = 0
        val rightArray = Array(rightSize) { 0 }
        while (i < rightSize) {
            rightArray[i] = array[middle + i + 1]
            i++
        }

        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++
        }

        while (i < leftSize) {
            array[k] = leftArray[i]
            i++
            k++
        }

        while (j < rightSize) {
            array[k] = rightArray[j]
            j++
            k++
        }
    }

}

================================================
FILE: src/main/kotlin/structures/BinaryTree.kt
================================================
package structures

import java.util.LinkedList

/**
 *
 * 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:
 *
 *  1
 *   \
 *    2
 *     \
 *      3
 *       \
 *        4
 *
 */

class BinaryTree<T : Comparable<T>> {

    private var root: Node<T>? = null

    val isEmpty: Boolean
        get() = root == null

    /**
     * Complexity:
     * worst time: O(n), read the hint in the description
     * best time: O(log(n))
     * average time: O(log(n))
     */
    fun add(value: T) {
        fun addRecursive(current: Node<T>?, value: T): Node<T> {
            if (current == null) {
                return Node(value)
            }
            if (value < current.value()) {
                current.changeLeft(addRecursive(current.leftNode(), value))
            } else if (value > current.value()) {
                current.changeRight(addRecursive(current.rightNode(), value))
            }
            return current
        }

        root = addRecursive(root, value)
    }

    /**
     * Complexity:
     * worst time: O(n), read the hint in the description
     * best time: O(1)
     * average time: O(log(n))
     */
    fun remove(value: T) {
        fun smallestValue(root: Node<T>): T {
            val leftNode = root.leftNode()
            if (leftNode === null) return root.value()
            return smallestValue(leftNode)
        }

        fun removeRecursive(current: Node<T>?, value: T): Node<T>? {
            if (current == null) {
                return null
            }

            if (value == current.value()) {
                if (current.leftNode() == null && current.rightNode() == null) {
                    return null
                }
                if (current.leftNode() == null) {
                    return current.rightNode()
                }
                if (current.rightNode() == null) {
                    return current.leftNode()
                }

                val smallestValue = smallestValue(current.rightNode()!!)
                current.changeValue(smallestValue)
                current.changeRight(removeRecursive(current.rightNode(), smallestValue))
                return current
            }

            if (value < current.value()) {
                current.changeLeft(removeRecursive(current.leftNode(), value))
            } else {
                current.changeRight(removeRecursive(current.rightNode(), value))
            }

            return current
        }

        root = removeRecursive(root, value)
    }

    /**
     * Complexity:
     * worst time: O(n), read the hint in the description
     * best time: O(1)
     * average time: O(log(n))
     */
    fun contains(value: T): Boolean {
        fun containsRecursive(current: Node<T>?, value: T): Boolean {
            if (current == null) {
                return false
            }
            if (value == current.value()) {
                return true
            }
            return if (value < current.value()) {
                containsRecursive(current.leftNode(), value)
            } else {
                containsRecursive(current.rightNode(), value)
            }
        }

        return containsRecursive(root, value)
    }

    /**
     *
     * Traversal of the binary tree in depth
     *
     * order: the left child, the parent, the right child
     *
     */
    fun traverseInOrder(): List<T> {
        fun traverseInOrderRecursive(node: Node<T>?, nodes: MutableList<T>) {
            if (node != null) {
                traverseInOrderRecursive(node.leftNode(), nodes)
                nodes.add(node.value())
                traverseInOrderRecursive(node.rightNode(), nodes)
            }
        }

        val nodes = mutableListOf<T>()
        traverseInOrderRecursive(root, nodes)
        return nodes
    }

    /**
     *
     * Traversal of the binary tree in depth
     *
     * order: the parent, the left child, the right child
     *
     */
    fun traversePreOrder(): List<T> {
        fun traversePreOrderRecursive(node: Node<T>?, nodes: MutableList<T>) {
            if (node != null) {
                nodes.add(node.value())
                traversePreOrderRecursive(node.leftNode(), nodes)
                traversePreOrderRecursive(node.rightNode(), nodes)
            }
        }

        val nodes = mutableListOf<T>()
        traversePreOrderRecursive(root, nodes)
        return nodes
    }

    /**
     *
     * Traversal of the binary tree in depth
     *
     * order: the left child, the right child, the parent
     *
     */
    fun traversePostOrder(): List<T> {
        fun traversePostOrderRec(node: Node<T>?, nodes: MutableList<T>) {
            if (node != null) {
                traversePostOrderRec(node.leftNode(), nodes)
                traversePostOrderRec(node.rightNode(), nodes)
                nodes.add(node.value())
            }
        }

        val nodes = mutableListOf<T>()
        traversePostOrderRec(root, nodes)
        return nodes
    }

    /**
     *
     * Traversal of the binary tree in breadth uses an additional data structure - a queue into which new tree
     *
     * nodes are added until the last node is added
     *
     */
    fun traverseLevelOrder(): List<T> {
        val current = root ?: return emptyList()

        val queue = LinkedList<Node<T>>()
        queue.add(current)

        val nodeValues = mutableListOf<T>()

        while (queue.isNotEmpty()) {
            val node = queue.removeFirst()

            nodeValues.add(node.value())

            val leftNode = node.leftNode()
            if (leftNode != null) {
                queue.add(leftNode)
            }

            val rightNode = node.rightNode()
            if (rightNode != null) {
                queue.add(rightNode)
            }
        }

        return nodeValues
    }

    class Node<T>(
        private var value: T,
        private var left: Node<T>? = null,
        private var right: Node<T>? = null
    ) {

        fun value() = value
        fun changeValue(newValue: T) {
            value = newValue
        }

        fun leftNode() = left
        fun changeLeft(node: Node<T>?) {
            left = node
        }

        fun rightNode() = right
        fun changeRight(node: Node<T>?) {
            right = node
        }

    }

}

================================================
FILE: src/main/kotlin/structures/CircularLinkedList.kt
================================================
package structures

/**
 *
 * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.
 *
 * In the single LinkedList with circular reference each node contains a link to the next element,
 * the last one refers to the first
 *
 */

class CircularLinkedList<T> {

    private var head: Node<T>? = null
    private var tail: Node<T>? = null

    private var size: Int = 0

    val isEmpty: Boolean
        get() = head == null

    /**
     * The simple method to test functionality of the LinkedList with circular reference
     *
     * Complexity: O(n * cycleNumber)
     */
    fun cyclingList(cycleNumber: Int = 1): List<T> {
        val nodeList = mutableListOf<T>()
        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
    }

    /**
     * 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)
                prevNode.changeNext(newNode)
                size++
                return true
            }
            i++

            if (node === tail) {
                break
            }

            prevNode = node
            node = node.next()
        }

        return false
    }

    fun add(value: T) = addLast(value)

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    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++
    }

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    fun addLast(value: T) {
        val node = Node(value)
        if (head == null) {
            head = node
            tail = node
        } else {
            tail?.changeNext(node)
            tail = node
        }
        tail?.changeNext(head)
        size++
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun contains(value: T) : Boolean {
        if (head == null) return false

        var node = head
        while (node != null) {
            if (node.value() == value) {
                return true
            }

            if (node === tail) {
                break
            }

            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
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun remove(value: T) : Boolean {
        if (head == null) return false

        var previous: Node<T>? = null
        var node = head

        while (node != null) {
            if (node.value() == value) {
                var nextNode = node.next()
                if (nextNode === head) {
                    nextNode = null
                }
                previous?.changeNext(nextNode)

                if (head === node) {
                    head = nextNode
                }

                if (tail === node) {
                    tail = previous
                }

                node.changeNext(null)
                node.changeValue(null)

                tail?.changeNext(head)

                size--

                return true
            }

            if (node === tail) {
                break
            }

            previous = node
            node = node.next()
        }

        return false
    }

    override fun toString(): String {
        val builder = StringBuilder()
        builder.append("size: $size\n")
        builder.append("elements: ")

        var node = head
        while (node != null) {
            builder.append(node.value())

            // it's necessary to see the correct node connections
            if (node.next() != null) {
                builder.append(" - ")
            }

            if (node === tail) {
                break
            }

            node = node.next()
        }

        return builder.toString()
    }

    class Node<T>(
        private var value: T? = null,
        private var next: Node<T>? = null
    ) {

        fun next() = next
        fun changeNext(node: Node<T>? = null) {
            next = node
        }

        fun value() = value
        fun changeValue(newValue: T?) {
            value = newValue
        }
    }

}

================================================
FILE: src/main/kotlin/structures/DoubleLinkedList.kt
================================================
package structures

/**
 *
 * 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
 *
 */

class DoubleLinkedList<T> {

    private var head: Node<T>? = null
    private var tail: Node<T>? = null

    private var size: Int = 0

    val isEmpty: Boolean
        get() = head == null

    // Complexity: O(n)
    val list: List<T>
        get() {
            val nodes = mutableListOf<T>()
            var node = head
            while (node != null) {
                val nodeValue = node.value()
                if (nodeValue != null) {
                    nodes.add(nodeValue)
                }
                node = node.next()
            }
            return nodes
        }

    // Complexity: O(n)
    val reversedList: List<T>
        get() {
            val nodes = mutableListOf<T>()
            var node = tail
            while (node != null) {
                val nodeValue = node.value()
                if (nodeValue != null) {
                    nodes.add(nodeValue)
                }
                node = node.previous()
            }
            return nodes
        }

    /**
     * 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()
        }

        return false
    }

    fun add(value: T) = addLast(value)

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    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++
    }

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    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
        }
        size++
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun contains(value: T) : Boolean {
        if (head == null) return false

        var node = head
        while (node != null) {
            if (node.value() == value) {
                return true
            }
            node = node.next()
        }
        return false
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun remove(value: T) : Boolean {
        if (head == null) return false

        var previous: Node<T>? = null
        var node = head

        while (node != null) {
            if (node.value() == value) {
                val nextNode = node.next()
                previous?.changeNext(nextNode)
                nextNode?.changePrevious(previous)

                if (node === head) {
                    head = nextNode
                }

                if (node === tail) {
                    tail = previous
                }

                node.changePrevious(null)
                node.changeNext(null)
                node.changeValue(null)

                size--
                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
    }

    override fun toString(): String {
        val builder = StringBuilder()
        builder.append("size: $size\n")
        builder.append("elements: ")

        var node = head
        while (node != null) {

            // it's necessary to see the correct node connections
            if (node.previous() != null) {
                builder.append("- ")
            }

            builder.append(node.value())

            // it's necessary to see the correct node connections
            if (node.next() != null) {
                builder.append(" -")
            }

            node = node.next()
        }

        return builder.toString()
    }

    class Node<T>(
        private var value: T? = null,
        private var previous: Node<T>? = null,
        private var next: Node<T>? = null
    ) {

        fun next() = next
        fun changeNext(node: Node<T>? = null) {
            next = node
        }

        fun previous() = previous
        fun changePrevious(node: Node<T>? = null) {
            previous = node
        }

        fun value() = value
        fun changeValue(newValue: T?) {
            value = newValue
        }

    }

}

================================================
FILE: src/main/kotlin/structures/DynamicArray.kt
================================================
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<T>(private var capacity: Int = 10) {

    private var data = arrayOfNulls<Any>(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<Any>(capacity)
        for (i in data.indices) {
            newArray[i] = data[i]
        }
        data = newArray
    }

    companion object {
        private const val INCREASE_SIZE_COEFFICIENT = 1.5f
    }

}

================================================
FILE: src/main/kotlin/structures/Graph.kt
================================================
package structures

import java.util.LinkedList
import kotlin.collections.LinkedHashSet

/**
 *
 * 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.
 *
 */

class Graph<T> {

    private val data = linkedMapOf<Vertex<T>, MutableList<Vertex<T>>>()

    // Complexity: O(1)
    fun addVertex(value: T) {
        data.putIfAbsent(Vertex(value), mutableListOf())
    }

    // Complexity: O(n)
    fun removeVertex(value: T) {
        val removingVertex = Vertex(value)
        data.values.forEach { list ->
            list.remove(removingVertex)
        }
        data.remove(removingVertex)
    }

    // Complexity: O(1)
    fun addEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.add(vertex2)
        data[vertex2]?.add(vertex1)
    }

    // Complexity: O(1)
    fun removeEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.remove(vertex2)
        data[vertex2]?.remove(vertex1)
    }

    // returns the associated vertices with the given vertex value
    fun connectedVertexes(value: T) = data[Vertex(value)]?.map { it.value } ?: emptyList()

    /**
     *
     * Traversal of the graph in depth,
     *
     * returns all vertices of the graph
     *
     */
    fun depthFirstTraversal() : List<T> {
        val firstVertex = data.keys.firstOrNull() ?: return emptyList()

        val visited = LinkedHashSet<T>()
        val queue = LinkedList<Vertex<T>>()
        queue.push(firstVertex)
        while (queue.isNotEmpty()) {
            val vertex = queue.pollFirst()
            if (!visited.contains(vertex.value)) {
                visited.add(vertex.value)
                queue.addAll(data[vertex] ?: emptyList())
            }
        }
        return visited.toList()
    }

    /**
     *
     * Traversal of the graph in breadth,
     *
     * returns all vertices of the graph
     *
     */
    fun breadthFirstTraversal() : List<T> {
        val firstVertex = data.keys.firstOrNull() ?: return emptyList()

        val visited = LinkedHashSet<T>()
        val queue = LinkedList<Vertex<T>>()
        queue.add(firstVertex)
        visited.add(firstVertex.value)
        while (queue.isNotEmpty()) {
            val vertex = queue.pollFirst()
            data[vertex]?.forEach { connectedVertex ->
                if (!visited.contains(connectedVertex.value)) {
                    visited.add(connectedVertex.value)
                    queue.add(connectedVertex)
                }
            }
        }
        return visited.toList()
    }

    private data class Vertex<T>(val value: T)

}


================================================
FILE: src/main/kotlin/structures/GraphWithWeights.kt
================================================
package structures


/**
 *
 * Graph is a non-linear data structure consisting of vertices and edges.
 *
 * The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph.
 *
 * More formally a Graph is composed of a set of vertices V and a set of edges E. The graph is denoted by G(E, V).
 *
 * Directed graph with weights is a type of graph where the edges have specified direction and weights assigned to the them.
 *
 */

class GraphWithWeights<T> {

    private val data = linkedMapOf<Vertex<T>, MutableList<VertexConnection<T>>>()

    // Complexity: O(1)
    fun addVertex(value: T) {
        data.putIfAbsent(Vertex(value), mutableListOf())
    }

    // Complexity: O(n)
    fun removeVertex(value: T) {
        val removingVertex = Vertex(value)
        data.values.forEach { connections ->
            connections.removeIf { it.vertex == removingVertex }
        }
        data.remove(removingVertex)
    }

    // Complexity: O(1)
    fun addEdge(value1: T, value2: T, cost: Int) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.add(VertexConnection(vertex2, cost))
    }

    // Complexity: O(n)
    fun removeEdge(value1: T, value2: T) {
        val vertex1 = Vertex(value1)
        val vertex2 = Vertex(value2)
        data[vertex1]?.removeIf { it.vertex == vertex2 }
    }

    // returns the associated vertices and their weights with the given vertex value
    fun connectedVertexesWithWeights(value: T) = data[Vertex(value)]?.map { it.toString() }  ?: emptyList()

    /**
     *
     * Dijkstra's algorithm,
     *
     * returns pairs of a vertex and the minimum weight needed to get to that vertex,
     *
     * the starting vertex is the first added
     *
     */
    fun dijkstraAlgorithm(): Map<T, Int> {
        if (data.isEmpty()) return emptyMap()

        val unvisitedVertexes = linkedMapOf<Vertex<T>, Int>()
        data.keys.forEach { vertex ->
            unvisitedVertexes[vertex] = Int.MAX_VALUE
        }

        val visitedVertexes = linkedMapOf<T, Int>()
        var minimumCost = 0

        var currentVertex = unvisitedVertexes.keys.first()
        while(unvisitedVertexes.isNotEmpty()) {
            val neighbourVertexConnections = data[currentVertex] ?: emptyList()
            for (neighbourVertexConnection in neighbourVertexConnections) {
                val neighbourVertex = neighbourVertexConnection.vertex
                if (!unvisitedVertexes.contains(neighbourVertex)) continue

                val newCost = minimumCost + neighbourVertexConnection.cost
                val neighbourVertexCost = unvisitedVertexes[neighbourVertex] ?: Int.MAX_VALUE
                if (neighbourVertexCost > newCost) {
                    unvisitedVertexes[neighbourVertex] = newCost
                }
            }
            visitedVertexes[currentVertex.value] = minimumCost
            unvisitedVertexes.remove(currentVertex)
            val nextUnvisitedEntry = unvisitedVertexes.entries
                .filter { it.value != Int.MAX_VALUE }
                .minByOrNull { it.value } ?: return visitedVertexes
            currentVertex = nextUnvisitedEntry.key
            minimumCost = nextUnvisitedEntry.value
        }
        return visitedVertexes
    }

    private data class Vertex<T>(val value: T)

    // helper class for defining graph weights
    private data class VertexConnection<T>(val vertex: Vertex<T>, val cost: Int) {
        override fun toString(): String = "vertex -> ${vertex.value}, cost -> $cost"
    }

}

================================================
FILE: src/main/kotlin/structures/Matrix.kt
================================================
package structures

import java.lang.IllegalArgumentException

fun matrix(apply: Matrix.() -> Unit): Matrix {
    val matrix = Matrix()
    matrix.apply()
    return matrix
}

/**
 * Matrix is a rectangular table filled with numbers.
 *
 * For example:
 *   1, 2, 3
 *   4, 5, 6
 *   7, 8, 9
 */
class Matrix() {

    private val elements = mutableListOf<Int>()
    private var columnCount = 0
    private var rowCount = 0

    private constructor(elements: List<Int>, columnCount: Int, rowCount: Int) : this() {
        this.elements.addAll(elements)
        this.columnCount = columnCount
        this.rowCount = rowCount
    }

    fun row(vararg rowElements: Int) {
        if (rowElements.isEmpty()) {
            return
        }

        if (rowCount == 0) {
            columnCount = rowElements.size
        }

        if (columnCount != rowElements.size) {
            throw IllegalArgumentException("The number of elements in each row must be the same")
        }

        elements.addAll(rowElements.toTypedArray())

        rowCount++
    }

    operator fun plus(value: Int): Matrix {
        return Matrix(elements.map { it + value }, columnCount, rowCount)
    }

    operator fun plus(value: Matrix): Matrix {
        if (rowCount != value.rowCount) throw IllegalArgumentException("The number of rows doesn't match")
        if (columnCount != value.columnCount) throw IllegalArgumentException("The number of columns doesn't match")

        return Matrix(elements.zip(value.elements) { element1, element2 -> element1 + element2 }, columnCount, rowCount)
    }

    operator fun minus(value: Int): Matrix {
        return Matrix(elements.map { it - value }, columnCount, rowCount)
    }

    operator fun minus(value: Matrix): Matrix {
        if (rowCount != value.rowCount) throw IllegalArgumentException("The number of rows doesn't match")
        if (columnCount != value.columnCount) throw IllegalArgumentException("The number of columns doesn't match")

        return Matrix(elements.zip(value.elements) { element1, element2 -> element1 - element2 }, columnCount, rowCount)
    }

    operator fun times(value: Int): Matrix {
        return Matrix(elements.map { it * value }, columnCount, rowCount)
    }

    operator fun times(matrix: Matrix): Matrix {
        val columnCountMatrix1 = columnCount
        val rowCountMatrix1 = rowCount
        val columnCountMatrix2 = matrix.columnCount
        val rowCountMatrix2 = matrix.rowCount

        if (columnCountMatrix1 != rowCountMatrix2) throw IllegalArgumentException("The number of columns of the first matrix doesn't match the number of rows of the second matrix")

        val newElements = mutableListOf<Int>()
        for (rowIndexMatrix1 in 0 until rowCountMatrix1) {
            for (columnIndexMatrix2 in 0 until columnCountMatrix2) {
                var sum = 0
                for (sameSizeIndex in 0 until columnCountMatrix1) {
                    sum += elements[rowIndexMatrix1 * columnCountMatrix1 + sameSizeIndex] * matrix.elements[sameSizeIndex * columnCountMatrix2 + columnIndexMatrix2]
                }
                newElements.add(sum)
            }
        }

        return Matrix(newElements, columnCountMatrix2, rowCountMatrix1)
    }

    operator fun div(value: Int): Matrix {
        return Matrix(elements.map { it / value }, columnCount, rowCount)
    }

    override fun equals(other: Any?): Boolean {
        if (other == null) return false
        if (other !is Matrix) return false
        if (this === other) return true

        return columnCount == other.columnCount && rowCount == other.rowCount && elements == other.elements
    }

    override fun hashCode(): Int {
        var result = elements.hashCode()
        result = 31 * result + columnCount
        result = 31 * result + rowCount
        return result
    }

    override fun toString(): String {
        val stringBuilder = StringBuilder("\n")

        elements.forEachIndexed { index, value ->
            val floating = if ((index + 1) % columnCount == 0) "" else ", "
            stringBuilder.append("$value$floating")

            if ((index + 1) % columnCount == 0) {
                stringBuilder.append("\n")
            }
        }

        return stringBuilder.toString()
    }

}

================================================
FILE: src/main/kotlin/structures/MaxHeap.kt
================================================
package structures

import java.lang.IllegalArgumentException

/**
 *
 * Max-heap is a binary tree in which each parent is greater than its children
 *
 */

class MaxHeap(private val maxSize: Int) {

    private val data = IntArray(maxSize + 1) { Int.MIN_VALUE }

    private val root = 1
    private var size = 0

    val isEmpty: Boolean
        get() = size == 0

    private val Int.parent
        get() = this / 2

    private val Int.leftChild
        get() = this * 2

    private val Int.rightChild
        get() = this * 2 + 1

    init {
        if (maxSize <= 0) throw IllegalArgumentException("The heap must have maxSize larger than zero")

        data[0] = Int.MAX_VALUE
    }

    // Complexity: O(logn)
    fun add(element: Int) {
        if (size >= maxSize) throw IllegalStateException("The heap is full!")

        data[++size] = Int.MIN_VALUE
        set(size, element)
    }

    // Complexity: O(logn)
    fun set(index: Int, newValue: Int) {
        if (index < root || index > maxSize) throw IllegalArgumentException("The heap doesn't have the such index: $index!")
        if (newValue < data[index]) throw IllegalArgumentException("The new value $newValue is less than the previous: ${data[index]}")

        data[index] = newValue

        var current = index
        while (current > root && data[current.parent] < data[current]) {
            swap(current, current.parent)
            current = current.parent
        }
    }

    // Complexity: O(1)
    fun peekMax() = data[root]

    // Complexity: O(logn)
    fun popMax(): Int {
        if (size < 1) throw IllegalStateException("The heap is empty!")

        val max = data[root]
        data[root] = data[size--]
        heapify(root)
        return max
    }

    private tailrec fun heapify(pos: Int) {
        val leftChild = pos.leftChild
        val rightChild = pos.rightChild
        var largest = pos

        if (leftChild <= size && data[leftChild] > data[largest]) {
            largest = leftChild
        }

        if (rightChild <= size && data[rightChild] > data[largest]) {
            largest = rightChild
        }

        if (largest != pos) {
            swap(pos, largest)
            heapify(largest)
        }
    }

    private fun swap(index1: Int, index2: Int) {
        val tmp = data[index1]
        data[index1] = data[index2]
        data[index2] = tmp
    }

    companion object {
        fun create(intArray: IntArray): MaxHeap {
            val arraySize = intArray.size
            val heap = MaxHeap(arraySize)
            heap.size = intArray.size

            var index = 0
            while (index < arraySize) {
                heap.data[index + 1] = intArray[index]
                index++
            }

            var pos = arraySize / 2
            while (pos >= 0) {
                heap.heapify(pos)
                pos--
            }
            return heap
        }
    }

}

================================================
FILE: src/main/kotlin/structures/MinHeap.kt
================================================
package structures

import java.lang.IllegalArgumentException


/**
 *
 * Min-heap is a binary tree in which each parent is smaller than its children
 *
 */

class MinHeap(private val maxSize: Int) {

    private val data = IntArray(maxSize + 1) { Int.MAX_VALUE }

    private val root = 1
    private var size = 0

    val isEmpty: Boolean
        get() = size == 0

    private val Int.parent
        get() = this / 2

    private val Int.leftChild
        get() = this * 2

    private val Int.rightChild
        get() = this * 2 + 1

    init {
        if (maxSize <= 0) throw IllegalArgumentException("The heap must have maxSize larger than zero")

        data[0] = Int.MIN_VALUE
    }

    // Complexity: O(logn)
    fun add(element: Int) {
        if (size >= maxSize) throw IllegalStateException("The heap is full!")

        data[++size] = Int.MAX_VALUE
        set(size, element)
    }

    // Complexity: O(logn)
    fun set(index: Int, newValue: Int) {
        if (index < root || index > maxSize) throw IllegalArgumentException("The heap doesn't have the such index: $index!")
        if (newValue > data[index]) throw IllegalArgumentException("The new value $newValue is more than the previous: ${data[index]}")

        data[index] = newValue

        var current = index
        while (current > root && data[current.parent] > data[current]) {
            swap(current, current.parent)
            current = current.parent
        }
    }

    // Complexity: O(1)
    fun peekMin() = data[root]

    // Complexity: O(logn)
    fun popMin(): Int {
        if (size < 1) throw IllegalStateException("The heap is empty!")

        val max = data[root]
        data[root] = data[size--]
        heapify(root)
        return max
    }

    private tailrec fun heapify(pos: Int) {
        val leftChild = pos.leftChild
        val rightChild = pos.rightChild
        var minimum = pos

        if (leftChild <= size && data[leftChild] < data[minimum]) {
            minimum = leftChild
        }

        if (rightChild <= size && data[rightChild] < data[minimum]) {
            minimum = rightChild
        }

        if (minimum != pos) {
            swap(pos, minimum)
            heapify(minimum)
        }
    }

    private fun swap(index1: Int, index2: Int) {
        val tmp = data[index1]
        data[index1] = data[index2]
        data[index2] = tmp
    }

    companion object {
        fun create(intArray: IntArray): MinHeap {
            val arraySize = intArray.size
            val heap = MinHeap(arraySize)
            heap.size = intArray.size

            var index = 0
            while (index < arraySize) {
                heap.data[index + 1] = intArray[index]
                index++
            }

            var pos = arraySize / 2
            while (pos >= 0) {
                heap.heapify(pos)
                pos--
            }
            return heap
        }
    }

}

================================================
FILE: src/main/kotlin/structures/Queue.kt
================================================
package structures

import java.util.LinkedList

/**
 *
 * Queue is a data structure that follows the FIFO (first in, first out) principle
 *
 * LIFO implies that the element that is inserted first, comes out first
 *
 * The main operations:
 *
 * 1) enqueue - inserts an element at the end of the queue
 * 2) dequeue - removes an element from the beginning of the queue
 *
 * All these operations performed in O(1) time.
 *
 */
class Queue<T> {

    private val data = LinkedList<T>()

    val isEmpty: Boolean
        get() = data.isEmpty()

    val size: Int
        get() = data.size

    fun enqueue(item: T) {
        data.add(item)
    }

    fun dequeue(): T {
        if (isEmpty) throw IllegalStateException("The queue is empty")

        // LinkedList under the hood stores a link to the first element
        // this operation will be completed in time O(1)
        return data.removeFirst()
    }

    fun peek(): T {
        if (isEmpty) throw IllegalStateException("The queue is empty")

        return data.first
    }

    fun clear() {
        data.clear()
    }

}

================================================
FILE: src/main/kotlin/structures/SingleLinkedList.kt
================================================
package structures

/**
 *
 * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.
 *
 * In the single LinkedList each node contains a link only to the next element
 *
 */

class SingleLinkedList<T>() {

    private var head: Node<T>? = null
    private var tail: Node<T>? = null

    private var size: Int = 0

    val isEmpty: Boolean
        get() = head == null

    /**
     * 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)
                prevNode.changeNext(newNode)
                size++
                return true
            }
            i++
            prevNode = node
            node = node.next()
        }

        return false
    }

    fun add(value: T) = addLast(value)

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    fun addFirst(value: T) {
        val node = Node(value)
        if (head == null) {
            head = node
            tail = node
        } else {
            node.changeNext(head)
            head = node
        }
        size++
    }

    /**
     * Complexity:
     * worst time: O(1)
     * best time: O(1)
     * average time: O(1)
     */
    fun addLast(value: T) {
        val node = Node(value)
        if (head == null) {
            head = node
            tail = node
        } else {
            tail?.changeNext(node)
            tail = node
        }
        size++
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun contains(value: T) : Boolean {
        if (head == null) return false

        var node = head
        while (node != null) {
            if (node.value() == value) {
                return true
            }
            node = node.next()
        }

        return false
    }

    /**
     * Complexity:
     * worst time: O(n)
     * best time: O(1)
     * average time: O(n)
     */
    fun remove(value: T) : Boolean {
        if (head == null) return false

        var previous: Node<T>? = null
        var node = head

        while (node != null) {
            if (node.value() == value) {
                val nextNode = node.next()
                previous?.changeNext(nextNode)

                if (head === node) {
                    head = nextNode
                }

                if (tail === node) {
                    tail = previous
                }

                node.changeNext(null)
                node.changeValue(null)

                size--
                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.changeValue(null)
        }

        head = null
        tail = null
        size = 0
    }

    override fun toString(): String {
        val builder = StringBuilder()
        builder.append("size: $size\n")
        builder.append("elements: ")

        var node = head
        while (node != null) {
            builder.append(node.value())

            // it's necessary to see the correct node connections
            if (node.next() != null) {
                builder.append(" - ")
            }

            node = node.next()
        }

        return builder.toString()
    }

    class Node<T>(
        private var value: T? = null,
        private var next: Node<T>? = null
    ) {

        fun next() = next
        fun changeNext(node: Node<T>? = null) {
            next = node
        }

        fun value() = value
        fun changeValue(newValue: T?) {
            value = newValue
        }

    }

}

================================================
FILE: src/main/kotlin/structures/Stack1.kt
================================================
package structures

import java.lang.IllegalArgumentException
import java.util.ArrayList

/**
 *
 * Stack is a linear data structure that follows the LIFO (last in first out) principle
 *
 * LIFO implies that the element that is inserted last, comes out first.
 *
 * The main operations:
 *
 * 1) push() - when we insert an element in a stack then the operation is known as a push
 * 2) pop() - when we delete an element from the stack, the operation is known as a pop
 *
 * All these operations performed in O(1) time.
 *
 */

class Stack1<T> {
    // this implementation uses ArrayList
    private val data = ArrayList<T>()

    val isEmpty: Boolean
        get() = data.size == 0

    val size: Int
        get() = data.size

    fun push(item: T) {
        data.add(item)
    }

    fun pop() : T {
        if (isEmpty) {
            throw IllegalArgumentException("Stack is empty!")
        }
        return data.removeLast()
    }

    fun peek() : T {
        if (isEmpty) {
            throw IllegalArgumentException("Stack is empty!")
        }
        return data.last()
    }

    fun clear() {
        data.clear()
    }

}

================================================
FILE: src/main/kotlin/structures/Stack2.kt
================================================
package structures

import java.util.LinkedList

/**
 *
 * Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle
 *
 * LIFO implies that the element that is inserted last, comes out first.
 *
 * The main operations:
 *
 *     push() - when we insert an element in a stack then the operation is known as a push.
 *     pop() - when we delete an element from the stack, the operation is known as a pop.
 *     If the stack is empty means that no element exists in the stack.
 *
 * All these operations performed in O(1) time.
 *
 */

class Stack2<T> {
    // this implementation uses LinkedList
    private val data = LinkedList<T>()

    val isEmpty: Boolean
        get() = data.size == 0

    val size: Int
        get() = data.size

    fun push(item: T) {
        data.add(item)
    }

    fun pop(): T {
        if (isEmpty) {
            throw IllegalArgumentException("Stack is empty!")
        }
        return data.removeLast()
    }

    fun peek(): T {
        if (isEmpty) {
            throw IllegalArgumentException("Stack is empty!")
        }
        return data.peekLast()
    }

    fun clear() {
        data.clear()
    }

}

================================================
FILE: src/test/kotlin/TestUtils.kt
================================================

import kotlin.random.Random

object TestUtils {

    fun randomArray(size: Int) =  List(size) { Random.nextInt(100) }.toTypedArray()
    fun sortedArray(size: Int) = List(size) { it }.toTypedArray()

    fun mutableRandomList(size: Int) = List(size) { Random.nextInt(100) }.toMutableList()
    fun list(size: Int) = List(size) { it }


}

================================================
FILE: src/test/kotlin/design_patterns/AbstractFactoryTest.kt
================================================
package design_patterns

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.core.IsInstanceOf.instanceOf
import org.junit.Test

internal class AbstractFactoryTest {

    @Test
    fun test() {
        val iosFactory = IOSButtonFactory()

        val iosButton = iosFactory.createButton()
        val iosText = iosFactory.createText()

        assertThat(iosButton, instanceOf(IOSButton::class.java))
        assertThat(iosText, instanceOf(IOSText::class.java))

        val androidFactory = AndroidButtonFactory()

        val androidButton = androidFactory.createButton()
        val androidText = androidFactory.createText()

        assertThat(androidButton, instanceOf(AndroidButton::class.java))
        assertThat(androidText, instanceOf(AndroidText::class.java))

        // we can draw iOS and Android components regardless of their implementation
        listOf(iosButton, androidButton).forEach { it.draw() }
        listOf(iosText, androidText).forEach { it.draw() }
    }

}

================================================
FILE: src/test/kotlin/design_patterns/AdapterTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class AdapterTest {

    @Test
    fun test() {
        // we don't understand EnglishSpeaker interface
        val englishSpeaker = EnglishSpeakerImpl()
        // but we know about SpainSpeaker interface
        val speakerAdapter = SpainSpeakerAdapter(englishSpeaker)

        // EnglishSpeaker interface was changed to SpainSpeaker interface
        val actual = speakerAdapter.speakSpanish()

        assertEquals("Hola, amigo!", actual)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/BridgeTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class BridgeTest {

    @Test
    fun test() {
        val windowsSystem = WindowsSystem()
        val macOSSystem = MacOSSystem()

        // the line doesn't know how graphics are implemented in different operating systems
        val line = GraphicLinePrimitive(0, 0, 100, 100)
        line.draw(windowsSystem)
        line.draw(macOSSystem)

        // the circle doesn't know how graphics are implemented in different operating systems
        val circle = GraphicCirclePrimitive(10, 10, 6)
        circle.draw(windowsSystem)
        circle.draw(macOSSystem)

        assertEquals("""
            Windows 10
            Lines:
            Windows graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100
            Circles:
            Windows graphic subsystem -> centerX: 10, centerY: 10, radius: 6
        """.trimIndent(), windowsSystem.toString())

        assertEquals("""
            MacOS 14
            Lines:
            MacOS graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100
            Circles:
            MacOS graphic subsystem -> centerX: 10, centerY: 10, radius: 6
        """.trimIndent(), macOSSystem.toString())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/BuilderTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class BuilderTest {

    @Test
    fun test_first_variant() {
        val dnsServerAddress = "8.8.8.8"
        val callTimeout = 500
        val connectTimeout = 3_000
        val writeTimeout = 3_000
        val readTimeout = 3_000

        val httpClient = HttpConnectionClient1.Builder()
            .dnsServerAddress(dnsServerAddress)
            .callTimeout(callTimeout)
            .connectTimeout(connectTimeout)
            .writeTimeout(writeTimeout)
            .readTimeout(readTimeout)
            .build()

        val expected = """
            dns -> $dnsServerAddress
            call timeout -> $callTimeout
            connect timeout -> $connectTimeout
            read timeout -> $readTimeout
            write timeout -> $writeTimeout
        """.trimIndent()

        assertEquals(expected, httpClient.toString())
    }

    @Test
    fun test_the_second_variant() {
        val dnsServerAddress = "8.8.8.8"
        val callTimeout = 500
        val connectTimeout = 3_000
        val writeTimeout = 3_000
        val readTimeout = 3_000

        val httpClient = HttpConnectionClient2.newBuilder()
            .dnsServerAddress(dnsServerAddress)
            .callTimeout(callTimeout)
            .connectTimeout(connectTimeout)
            .writeTimeout(writeTimeout)
            .readTimeout(readTimeout)
            .build()

        val expected = """
            dns -> $dnsServerAddress
            call timeout -> $callTimeout
            connect timeout -> $connectTimeout
            read timeout -> $readTimeout
            write timeout -> $writeTimeout
        """.trimIndent()

        assertEquals(expected, httpClient.toString())
    }

    @Test
    fun test_third_variant() {
        val dnsServerAddress = "8.8.8.8"
        val callTimeout = 500
        val connectTimeout = 3_000
        val writeTimeout = 3_000
        val readTimeout = 3_000

        val httpClient = HttpConnectionClient3(
            dnsServerAddress = dnsServerAddress,
            callTimeout = callTimeout,
            connectTimeout = connectTimeout,
            readTimeout = readTimeout,
            writeTimeout = writeTimeout
        )

        val expected = """
            dns -> $dnsServerAddress
            call timeout -> $callTimeout
            connect timeout -> $connectTimeout
            read timeout -> $readTimeout
            write timeout -> $writeTimeout
        """.trimIndent()

        assertEquals(expected, httpClient.toString())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class ChainOfResponsibilitiesTest {

    @Test
    fun test_when_we_have_only_stone_pickaxe() {
        val pickaxe = StonePickaxe()

        assertEquals(true, pickaxe.mine(StoneBlock()))
        assertEquals(false, pickaxe.mine(DiamondBlock()))
        assertEquals(false, pickaxe.mine(ObsidianBlock()))
    }

    @Test
    fun test_when_we_have_stone_and_iron_pickaxes() {
        val pickaxe = StonePickaxe()
        pickaxe.changeNextPickaxe(IronPickaxe())

        assertEquals(true, pickaxe.mine(StoneBlock()))
        assertEquals(true, pickaxe.mine(DiamondBlock()))
        assertEquals(false, pickaxe.mine(ObsidianBlock()))
    }

    @Test
    fun test_when_we_have_all_three_pickaxes() {
        val ironPickaxe = IronPickaxe()
        ironPickaxe.changeNextPickaxe(DiamondPickaxe())

        val stonePickaxe = StonePickaxe()
        stonePickaxe.changeNextPickaxe(ironPickaxe)

        assertEquals(true, stonePickaxe.mine(StoneBlock()))
        assertEquals(true, stonePickaxe.mine(DiamondBlock()))
        assertEquals(true, stonePickaxe.mine(ObsidianBlock()))
    }

}

================================================
FILE: src/test/kotlin/design_patterns/CommandTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class CommandTest {

    @Test
    fun `test usual commands`() {
        val stereoSystem = StereoSystem()
        val remoteControl = StereoSystemRemoteControl(mapOf(
            "turnOn" to TurnOnCommand(stereoSystem),
            "turnOff" to TurnOffCommand(stereoSystem),
            "volume+" to IncreaseVolumeCommand(stereoSystem),
            "volume-" to DecreaseVolumeCommand(stereoSystem)
        ))

        remoteControl.pressButton("turnOn")

        assertEquals("""
            running status: true
            volume value: 50
        """.trimIndent(), stereoSystem.currentState)

        remoteControl.pressButton("volume+")
        remoteControl.pressButton("volume+")
        remoteControl.pressButton("volume+")

        assertEquals("""
            running status: true
            volume value: 80
        """.trimIndent(), stereoSystem.currentState)

        remoteControl.pressUndoButton()
        remoteControl.pressUndoButton()
        remoteControl.pressUndoButton()
        remoteControl.pressUndoButton()

        assertEquals("""
            running status: false
            volume value: 50
        """.trimIndent(), stereoSystem.currentState)
    }

    @Test
    fun `test macro command`() {
        val stereoSystem = StereoSystem()
        val remoteControl = StereoSystemRemoteControl(mapOf(
            "party" to MacroCommand(
                TurnOnCommand(stereoSystem),
                IncreaseVolumeCommand(stereoSystem),
                IncreaseVolumeCommand(stereoSystem),
                IncreaseVolumeCommand(stereoSystem),
                IncreaseVolumeCommand(stereoSystem),
                IncreaseVolumeCommand(stereoSystem)
            )
        ))

        remoteControl.pressButton("party")

        assertEquals("""
            running status: true
            volume value: 100
        """.trimIndent(), stereoSystem.currentState)

        remoteControl.pressUndoButton()

        assertEquals("""
            running status: false
            volume value: 50
        """.trimIndent(), stereoSystem.currentState)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/CompositeTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class CompositeTest {

    @Test
    fun test() {
        val menu = Menu("Delicious Restaurant")

        val pizzasMenu = Menu("Pizzas")
        pizzasMenu.addComponent(MenuItem("Cheese pizza", 10))
        pizzasMenu.addComponent(MenuItem("Pepperoni pizza", 11))
        menu.addComponent(pizzasMenu)

        val cakesMenu = Menu("Cakes")
        cakesMenu.addComponent(MenuItem("Chocolate cake", 13))
        cakesMenu.addComponent(MenuItem("Cheese cake", 13))
        menu.addComponent(cakesMenu)

        assertEquals("""
            Menu: Delicious Restaurant
            Menu: Pizzas
            title: Cheese pizza
            price: 10
            -------------
            title: Pepperoni pizza
            price: 11
            -------------
            Menu: Cakes
            title: Chocolate cake
            price: 13
            -------------
            title: Cheese cake
            price: 13
            -------------
        """.trimIndent(), menu.fetchMenuInformation())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/DecoratorTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class DecoratorTest {

    @Test
    fun test() {
        val printer = ExclamationPrinter(
            WorldPrinter(
                SpacePrinter(
                    CommaPrinter(
                        HelloPrinter()
                    )
                )
            )
        )
        assertEquals("Hello, World!", printer.printedText())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/FacadeTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class FacadeTest {

    @Test
    fun test() {
        val goodsRepository = GoodsRepository(
            GoodsDatabase(),
            GoodsNetworkService(),
            CategoryDatabase(),
            CategoryNetworkService()
        )

        val actual = goodsRepository.goodsAndCategories()

        assertEquals(
            GoodsResult(
                goods = listOf(GoodsEntity(
                    id = 1,
                    name = "Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition",
                    description = "You know you don't want to reinvent the wheel, so you look to Design Patterns: the lessons learned by those who've faced the same software design problems.",
                    price = 41.94
                )),
                categories = listOf(CategoryEntity(
                    id = 1,
                    name = "Books"
                ))
            ),
            actual
        )
    }

}

================================================
FILE: src/test/kotlin/design_patterns/FactoryMethodTest.kt
================================================
package design_patterns

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.core.IsInstanceOf.instanceOf
import org.junit.Assert.assertEquals
import org.junit.Test

class FactoryMethodTest {

    @Test
    fun `test WoodenHouseCompany`() {
        val woodenHouseCompany = WoodenHouseCompany()

        val house1 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.CHEAP)
        assertThat(house1, instanceOf(WoodenCheapHouse::class.java))

        val house2 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.AVERAGE)
        assertThat(house2, instanceOf(WoodenAverageHouse::class.java))

        val house3 = woodenHouseCompany.orderHouse("77, Brook Ave", HouseCompany.HouseCompanyCost.EXPENSIVE)
        assertThat(house3, instanceOf(WoodenExpensiveHouse::class.java))

        val expected = """
            address = 77, Brook Ave
            price = 50000
            
            address = 77, Brook Ave
            price = 250000
            
            address = 77, Brook Ave
            price = 1000000
        """.trimIndent()
        assertEquals(expected, woodenHouseCompany.examplesAlreadyBuiltHouses)
    }

    @Test
    fun `test StoneHouseCompany`() {
        val stoneHouseCompany = StoneHouseCompany()

        val house1 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.CHEAP)
        assertThat(house1, instanceOf(StoneCheapHouse::class.java))

        val house2 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.AVERAGE)
        assertThat(house2, instanceOf(StoneAverageHouse::class.java))

        val house3 = stoneHouseCompany.orderHouse("55, Brook Ave", HouseCompany.HouseCompanyCost.EXPENSIVE)
        assertThat(house3, instanceOf(StoneExpensiveHouse::class.java))

        val expected = """
            address = 55, Brook Ave
            price = 45000
            
            address = 55, Brook Ave
            price = 230000
            
            address = 55, Brook Ave
            price = 900000
        """.trimIndent()
        assertEquals(expected, stoneHouseCompany.examplesAlreadyBuiltHouses)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/FlyweightTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class FlyweightTest {

    @Test
    fun test() {
        val garden = BeautifulGarden()

        garden.placeTree("oak", "", 21, 10, 10)
        garden.placeTree("birch", "", 15, 10, 20)
        garden.placeTree("birch", "", 16, 10, 30)
        garden.placeTree("birch", "", 17, 10, 40)
        garden.placeTree("oak", "", 21, 20, 10)
        garden.placeTree("oak", "", 21, 20, 20)
        garden.placeTree("oak", "", 21, 20, 30)
        garden.placeTree("birch", "", 15, 20, 40)

        assertEquals("""
            Beautiful Garden:
            name: oak, height: 21, x: 10, y: 10
            name: birch, height: 15, x: 10, y: 20
            name: birch, height: 16, x: 10, y: 30
            name: birch, height: 17, x: 10, y: 40
            name: oak, height: 21, x: 20, y: 10
            name: oak, height: 21, x: 20, y: 20
            name: oak, height: 21, x: 20, y: 30
            name: birch, height: 15, x: 20, y: 40
            -|-|-|-|-|-|-|-|-|-|-
        """.trimIndent(), garden.placedTreesAsString())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/InterpreterTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class InterpreterTest {

    @Test
    fun test() {
        // x = 10, y = 20, d = 5
        // sum = x + y
        // result = sum * d
        val expression = PerformExpression(
            SetIntVariableExpression("x", 10),
            SetIntVariableExpression("y", 20),
            AddVariablesExpression("x", "y", "sum"),
            SetIntVariableExpression("d", 5),
            MultipleVariablesExpression("sum", "d", "result")
        )

        val context = InterpreterContext()

        expression.interpret(context)

        assertEquals(150, context.fetchVariable("result"))
    }

}

================================================
FILE: src/test/kotlin/design_patterns/IteratorTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class IteratorTest {

    @Test
    fun test() {
        val presents = arrayOf("chocolate cake", "snowboard", "snowman")
        val giftBox = GiftBox(presents)
        val giftBoxIterator = giftBox.iterator()
        val actualPresents = mutableListOf<String>()
        while (giftBoxIterator.hasNext()) {
            val present = giftBoxIterator.next()
            actualPresents.add(present)
        }
        assertEquals(presents.toList(), actualPresents)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/MediatorTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class MediatorTest {

    @Test
    fun test() {
        val manager = SoftwareDevelopmentManager()

        val customer = CustomerSoftwareDevelopmentMember(manager)
        manager.changeCustomer(customer)
        val designer = DesignerSoftwareDevelopmentMember(manager)
        manager.changeDesigner(designer)
        val programmer = ProgrammerSoftwareDevelopmentMember(manager)
        manager.changeProgrammer(programmer)
        val tester = TesterSoftwareDevelopmentMember(manager)
        manager.changeTester(tester)

        customer.finishWork()
        designer.finishWork()
        programmer.finishWork()
        tester.finishWork()

        assertEquals("""
            Designer accepted the work: design development
            Programmer accepted the work: writing code
            Tester accepted the work: application testing
            Customer accepted the work: business valuation
        """.trimIndent(), manager.stagesAsString)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/MementoTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class MementoTest {

    @Test
    fun test() {
        // start Android system
        val androidOS = AndroidSystem()

        val greetingText = "Hello, World!"
        val greetingView = TextView()
        greetingView.setText(greetingText)
        greetingView.draw()

        // rotating Android device (recreating application components)
        // Android system saves the states of running applications
        androidOS.saveBundle(greetingView.onSaveInstanceState())

        // the state of the text was lost, but we saved it
        greetingView.setText("")

        // Android device has already rotated
        // The system restores the states of running applications
        greetingView.onRestoreInstanceState(androidOS.restoreBundle())

        assertEquals(greetingText, greetingView.text())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/ObserverTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class ObserverTest {

    @Test
    fun test() {
        val ponyList = PonyList()

        val observer1 = PonyObserver { items ->
            assertEquals(listOf("Twillight Sparkle"), items)
        }
        ponyList.addObserver(observer1)
        // we add the first item, observer1 is triggered
        ponyList.add("Twillight Sparkle")
        // we remove observer1 so that it is not called again
        ponyList.removeObserver(observer1)

        val observer2 = PonyObserver { items ->
            assertEquals(listOf("Twillight Sparkle", "Starlight Glimmer"), items)
        }
        ponyList.addObserver(observer2)
        // we add the second item, observer2 is triggered
        ponyList.add("Starlight Glimmer")
    }

}

================================================
FILE: src/test/kotlin/design_patterns/PrototypeTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class PrototypeTest {

    @Test
    fun test() {
        // we have a list of sweets that need to be made at the confectionery factory
        val recipesOfSweets = listOf(
            OreoCookies("Original OREO", "Rich chocolate cookies with vanilla creme", 12),
            OreoCookies("Golden OREO", "Sweet vanilla cookies with vanilla creme", 13),
            OreoCookies("OREO Thins", "Sweet vanilla cookies with vanilla creme", 11),
            `M&MsChocolate`("with puffed rice", 10),
            `M&MsChocolate`("with peanuts", 11)
        )

        // we produce sweets according to existing recipes
        val producedSweets = recipesOfSweets.flatMap { sweets -> List(10) { sweets.copy() } }

        assertEquals(producedSweets.size, 50)
        assertEquals(producedSweets[9], recipesOfSweets[0])
        assertEquals(producedSweets[19], recipesOfSweets[1])
        assertEquals(producedSweets[29], recipesOfSweets[2])
        assertEquals(producedSweets[39], recipesOfSweets[3])
        assertEquals(producedSweets[49], recipesOfSweets[4])
    }

}

================================================
FILE: src/test/kotlin/design_patterns/ProxyTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class ProxyTest {

    @Test
    fun test() {
        // we use the proxy object instead of a real one
        val mediaPlayer = AudioPlayerProxy()

        mediaPlayer.play("track_0.mp3")
        assertEquals("""
            current audio: track_0.mp3
            current status: RUNNING
        """.trimIndent(), mediaPlayer.currentState)

        mediaPlayer.pause()
        assertEquals("""
            current audio: track_0.mp3
            current status: PAUSED
        """.trimIndent(), mediaPlayer.currentState)

        mediaPlayer.resume()
        assertEquals("""
            current audio: track_0.mp3
            current status: RUNNING
        """.trimIndent(), mediaPlayer.currentState)

        mediaPlayer.stop()
        assertEquals("""
            current audio: 
            current status: NOT_INITIALIZED
        """.trimIndent(), mediaPlayer.currentState)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/SingletonTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class SingletonTest {

    @Test
    fun test() {
        // we have one instance of SQLiteDatabase class
        SQLiteDatabase.openConnection()

        val actual = SQLiteDatabase.execSQL("select * from names")
        val expected = listOf("Rick", "Morty", "Jerry", "Beth")

        assertEquals(expected, actual)

        SQLiteDatabase.closeConnection()
    }

}

================================================
FILE: src/test/kotlin/design_patterns/StateTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class StateTest {

    @Test
    fun test() {
        val machine = CocaColaMachine()

        assertEquals("NoDollarCocaColaState", machine.currentState)
        machine.pressButton()
        assertEquals("NoDollarCocaColaState", machine.currentState)

        machine.insertDollar()
        assertEquals("HaveDollarCocaColaState", machine.currentState)
        machine.takeBackDollar()
        assertEquals("NoDollarCocaColaState", machine.currentState)
        machine.takeBackDollar()
        assertEquals("NoDollarCocaColaState", machine.currentState)

        machine.insertDollar()
        assertEquals("HaveDollarCocaColaState", machine.currentState)
        machine.pressButton()
        assertEquals("NoDollarCocaColaState", machine.currentState)

        machine.insertDollar()
        assertEquals("HaveDollarCocaColaState", machine.currentState)
        machine.pressButton()
        assertEquals("NoDollarCocaColaState", machine.currentState)

        machine.insertDollar()
        assertEquals("HaveDollarCocaColaState", machine.currentState)
        machine.pressButton()
        assertEquals("EmptyCocaColaState", machine.currentState)

        machine.insertDollar()
        assertEquals("EmptyCocaColaState", machine.currentState)

        machine.loadDrinks(1)
        machine.insertDollar()
        assertEquals("HaveDollarCocaColaState", machine.currentState)
        machine.pressButton()
        assertEquals("EmptyCocaColaState", machine.currentState)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/StrategyTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class StrategyTest {

    @Test
    fun test() {
        val strategy = OnlyChipsFilterStrategy()
        val foodStore = FoodStore(strategy)

        assertEquals(listOf(
            FoodEntity(
                "Lays Potato Chips Fried Crab Flavor",
                2,
                "chips"
            ),
            FoodEntity(
                "Lay's Potato Chips, Classic",
                3,
                "chips"
            )
        ), foodStore.foodItems())

        foodStore.changeStrategy(OnlyChocolateFilterStrategy())

        assertEquals(listOf(
            FoodEntity(
                "Dove Chocolate",
                3,
                "chocolate"
            ),
            FoodEntity(
                "Ritter Sport Chocolate",
                4,
                "chocolate"
            )
        ), foodStore.foodItems())

        foodStore.changeStrategy(PriceFilterStrategy(3))

        assertEquals(listOf(
            FoodEntity(
                "Lay's Potato Chips, Classic",
                3,
                "chips"
            ),
            FoodEntity(
                "Dove Chocolate",
                3,
                "chocolate"
            ),
            FoodEntity(
                "Ritter Sport Chocolate",
                4,
                "chocolate"
            )
        ), foodStore.foodItems())

        foodStore.changeStrategy(SearchWordFilterStrategy("Ritter Sport"))

        assertEquals(listOf(
            FoodEntity(
                "Ritter Sport Chocolate",
                4,
                "chocolate"
            )
        ), foodStore.foodItems())
    }

}

================================================
FILE: src/test/kotlin/design_patterns/TemplateMethodTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

class TemplateMethodTest {

    @Test
    fun `test ChocolateCakeBaker`() {
        val baker = ChocolateCakeBaker()

        val actual = baker.makeCake(3)
        val expected = Cake(
            layers = listOf(
                "chocolate cake layer",
                "chocolate cake layer",
                "chocolate cake layer"
            ),
            cream = "chocolate cream",
            sprinkles = "chocolate chips"
        )

        assertEquals(expected, actual)
    }

    @Test
    fun `test WaffleCakeBaker`() {
        val baker = WaffleCakeBaker()

        val actual = baker.makeCake(3)
        val expected = Cake(
            layers = listOf(
                "waffle cake layer",
                "waffle cake layer",
                "waffle cake layer"
            ),
            cream = "custard cream",
            sprinkles = "coconut flakes"
        )

        assertEquals(expected, actual)
    }

}

================================================
FILE: src/test/kotlin/design_patterns/VisitorTest.kt
================================================
package design_patterns

import org.junit.Test
import org.junit.Assert.assertEquals

internal class VisitorTest {

    private val expectedJson = """
        [{
            "what" : "unicorn",
            "name" : "Twilight Sparkle",
            "cutie_mark" : "star
        },
        {
            "what" : "pegasus",
            "name" : "Rainbow Dash",
            "cutie_mark" : "lightning
        },
        {
            "what" : "earth pony",
            "name" : "Apple Jack",
            "cutie_mark" : "apple
        }]
    """.trimIndent()

    private val expectedXml = """
        <ponies>
        <pony>
            <what>unicorn</what>
            <name>Twilight Sparkle</name>
            <cutie_mark>star</cutie_mark>
        </pony>
        <pony>
            <what>pegasus</what>
            <name>Rainbow Dash</name>
            <cutie_mark>lightning</cutie_mark>
        </pony>
        <pony>
            <what>earth pony</what>
            <name>Apple Jack</name>
            <cutie_mark>apple</cutie_mark>
        </pony>
        </ponies>
    """.trimIndent()

    @Test
    fun test_json_visitor() {
        val jsonVisitor = JsonVisitor()
        val twilightSparkle = Unicorn("Twilight Sparkle", "star")
        val rainbowDash = Pegasus("Rainbow Dash", "lightning")
        val appleJack = EarthPony("Apple Jack", "apple")
        val actual = jsonVisitor.visitPonies(twilightSparkle, rainbowDash, appleJack)
        assertEquals(expectedJson, actual)
    }

    @Test
    fun test_xml_visitor() {
        val xmlVisitor = XmlVisitor()
        val twilightSparkle = Unicorn("Twilight Sparkle", "star")
        val rainbowDash = Pegasus("Rainbow Dash", "lightning")
        val appleJack = EarthPony("Apple Jack", "apple")
        val actual = xmlVisitor.visitPonies(twilightSparkle, rainbowDash, appleJack)
        assertEquals(expectedXml, actual)
    }

}

================================================
FILE: src/test/kotlin/other/BinaryDigitsCounterTest.kt
================================================
package other

import org.junit.Test
import org.junit.Assert.assertEquals

internal class BinaryDigitsCounterTest {

    private val counter = BinaryDigitsCounter()

    @Test
    fun test_empty_string() {
        val result = counter.compute("")

        assertEquals(BinaryDigitsCounter.Result(), result)
    }

    @Test
    fun test_binary_string_1() {
        val result = counter.compute("10101111000")

        assertEquals(BinaryDigitsCounter.Result(6, 5), result)
    }

    @Test
    fun test_binary_string_2() {
        val result = counter.compute("0100000111110010101010")

        assertEquals(BinaryDigitsCounter.Result(10, 12), result)
    }

    @Test
    fun test_binary_string_3() {
        val result = counter.compute("1111111111")

        assertEquals(BinaryDigitsCounter.Result(10, 0), result)
    }

    @Test
    fun test_binary_string_4() {
        val result = counter.compute("0000000000")

        assertEquals(BinaryDigitsCounter.Result(0, 10), result)
    }

}

================================================
FILE: src/test/kotlin/other/EuclidAlgorithmTest.kt
================================================
package other

import org.junit.Test
import org.junit.Assert.assertEquals

internal class EuclidAlgorithmTest {

    private val euclidAlgorithm = EuclidAlgorithm()

    @Test
    fun `test computeByDivisionWithRemainder`() {
        assertEquals(5, euclidAlgorithm.computeByDivisionWithRemainder(10, 5))
        assertEquals(10, euclidAlgorithm.computeByDivisionWithRemainder(10, 100))
        assertEquals(9, euclidAlgorithm.computeByDivisionWithRemainder(9, 27))
        assertEquals(13, euclidAlgorithm.computeByDivisionWithRemainder(26, 39))
        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(135, 13))
        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(27, 19))
        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(2, 17))
        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(4, 9))
    }

    @Test
    fun `test computeBySubtraction`() {
        assertEquals(5, euclidAlgorithm.computeBySubtraction(10, 5))
        assertEquals(10, euclidAlgorithm.computeBySubtraction(10, 100))
        assertEquals(9, euclidAlgorithm.computeBySubtraction(9, 27))
        assertEquals(13, euclidAlgorithm.computeBySubtraction(26, 39))
        assertEquals(1, euclidAlgorithm.computeBySubtraction(135, 13))
        assertEquals(1, euclidAlgorithm.
Download .txt
gitextract_pko15ir1/

├── .gitignore
├── LICENSE.txt
├── README.md
├── README_ru.md
├── build.gradle.kts
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src/
    ├── main/
    │   └── kotlin/
    │       ├── design_patterns/
    │       │   ├── Abstract Factory.kt
    │       │   ├── Adapter.kt
    │       │   ├── Bridge.kt
    │       │   ├── Builder.kt
    │       │   ├── Command.kt
    │       │   ├── Composite.kt
    │       │   ├── Decorator.kt
    │       │   ├── Facade.kt
    │       │   ├── Factory Method.kt
    │       │   ├── Flyweight.kt
    │       │   ├── Interpreter.kt
    │       │   ├── Iterator.kt
    │       │   ├── Mediator.kt
    │       │   ├── Memento.kt
    │       │   ├── Observer.kt
    │       │   ├── Prototype.kt
    │       │   ├── Proxy.kt
    │       │   ├── Singleton.kt
    │       │   ├── State.kt
    │       │   ├── Strategy.kt
    │       │   ├── Template Method.kt
    │       │   ├── Visitor.kt
    │       │   └── Сhain Of Responsibilities.kt
    │       ├── other/
    │       │   ├── BinaryDigitsCounter.kt
    │       │   ├── EuclidAlgorithm.kt
    │       │   ├── Factorial.kt
    │       │   ├── FactorialAdvanced.kt
    │       │   ├── FactorialBigWithCache.kt
    │       │   ├── FactorialWithCache.kt
    │       │   ├── FizzBuzz.kt
    │       │   ├── KnuthMorrisPrattAlgorithm.kt
    │       │   ├── LevenshteinLengthAlgorithm.kt
    │       │   ├── MaxAlgorithm.kt
    │       │   ├── MinAlgorithm.kt
    │       │   ├── PalindromeAlgorithm.kt
    │       │   ├── ParenthesisCheckAlgorithm.kt
    │       │   ├── ReverseArrayAlgorithm.kt
    │       │   ├── SieveOfEratosthenesAlgorithm.kt
    │       │   ├── Sqrt.kt
    │       │   ├── StringEqualsHashAlgorithm.kt
    │       │   └── SwapAlgorithm.kt
    │       ├── search/
    │       │   ├── BinarySearch.kt
    │       │   └── LinearSearch.kt
    │       ├── sorting/
    │       │   ├── BubbleSort.kt
    │       │   ├── CountingSort.kt
    │       │   ├── InsertionSort.kt
    │       │   ├── MergeSort.kt
    │       │   ├── QuickSort.kt
    │       │   ├── RadixSort.kt
    │       │   ├── SelectionSort.kt
    │       │   └── TimSort.kt
    │       └── structures/
    │           ├── BinaryTree.kt
    │           ├── CircularLinkedList.kt
    │           ├── DoubleLinkedList.kt
    │           ├── DynamicArray.kt
    │           ├── Graph.kt
    │           ├── GraphWithWeights.kt
    │           ├── Matrix.kt
    │           ├── MaxHeap.kt
    │           ├── MinHeap.kt
    │           ├── Queue.kt
    │           ├── SingleLinkedList.kt
    │           ├── Stack1.kt
    │           └── Stack2.kt
    └── test/
        └── kotlin/
            ├── TestUtils.kt
            ├── design_patterns/
            │   ├── AbstractFactoryTest.kt
            │   ├── AdapterTest.kt
            │   ├── BridgeTest.kt
            │   ├── BuilderTest.kt
            │   ├── ChainOfResponsibilitiesTest.kt
            │   ├── CommandTest.kt
            │   ├── CompositeTest.kt
            │   ├── DecoratorTest.kt
            │   ├── FacadeTest.kt
            │   ├── FactoryMethodTest.kt
            │   ├── FlyweightTest.kt
            │   ├── InterpreterTest.kt
            │   ├── IteratorTest.kt
            │   ├── MediatorTest.kt
            │   ├── MementoTest.kt
            │   ├── ObserverTest.kt
            │   ├── PrototypeTest.kt
            │   ├── ProxyTest.kt
            │   ├── SingletonTest.kt
            │   ├── StateTest.kt
            │   ├── StrategyTest.kt
            │   ├── TemplateMethodTest.kt
            │   └── VisitorTest.kt
            ├── other/
            │   ├── BinaryDigitsCounterTest.kt
            │   ├── EuclidAlgorithmTest.kt
            │   ├── FactorialAdvancedTest.kt
            │   ├── FactorialBigWithCacheTest.kt
            │   ├── FactorialTest.kt
            │   ├── FactorialWithCacheTest.kt
            │   ├── FizzBuzzTest.kt
            │   ├── KnuthMorrisPrattAlgorithmTest.kt
            │   ├── LevenshteinLengthAlgorithmTest.kt
            │   ├── MaxAlgorithmTest.kt
            │   ├── MinAlgorithmTest.kt
            │   ├── PalindromeAlgorithmTest.kt
            │   ├── ParenthesisCheckAlgorithmTest.kt
            │   ├── ReverseArrayAlgorithmTest.kt
            │   ├── SieveOfEratosthenesAlgorithmTest.kt
            │   ├── SqrtTest.kt
            │   ├── StringEqualsHashAlgorithmTest.kt
            │   └── SwapAlgorithmTest.kt
            ├── search/
            │   ├── BinarySearchTest.kt
            │   └── LinearSearchTest.kt
            ├── sorting/
            │   ├── BubbleSortTest.kt
            │   ├── CountingSortTest.kt
            │   ├── InsertionSortTest.kt
            │   ├── MergeSortTest.kt
            │   ├── QuickSortTest.kt
            │   ├── RadixSortTest.kt
            │   ├── SelectionSortTest.kt
            │   └── TimSortTest.kt
            └── structures/
                ├── BinaryTreeTest.kt
                ├── CircularLinkedListTest.kt
                ├── DoubleLinkedListTest.kt
                ├── DynamicArrayTest.kt
                ├── GraphTest.kt
                ├── GraphWithWeightsTest.kt
                ├── MatrixTest.kt
                ├── MaxHeapTest.kt
                ├── MinHeapTest.kt
                ├── QueueTest.kt
                ├── SingleLinkedListTest.kt
                ├── Stack1Test.kt
                └── Stack2Test.kt
Condensed preview — 140 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (278K chars).
[
  {
    "path": ".gitignore",
    "chars": 1163,
    "preview": "# IDE-specific stuff\nidea/\n\n# CMake\ncmake-build-*/\n\n# File-based project format\n*.iws\n\n# IntelliJ\nout/\n\n# JIRA plugin\nat"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1072,
    "preview": "MIT License\n\nCopyright (c) 2023 Dmitry Tsyvtsyn\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 6739,
    "preview": "![Алгоритмы на Kotlin](/assets/algo_logo.png)\n\n# Kotlin Algorithms and Design Patterns\n\nThis repository lists the most c"
  },
  {
    "path": "README_ru.md",
    "chars": 6908,
    "preview": "![Алгоритмы на Kotlin](/assets/algo_ru.png)\n\n# Kotlin Algorithms and Design Patterns\n\nВ этом репозитории приведены наибо"
  },
  {
    "path": "build.gradle.kts",
    "chars": 299,
    "preview": "plugins {\n    id(\"org.jetbrains.kotlin.jvm\") version \"1.8.22\"\n}\n\ngroup = \"io.github.dmitrytsyvtsyn.algorithmsdesignpatte"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 200,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "gradle.properties",
    "chars": 26,
    "preview": "kotlin.code.style=official"
  },
  {
    "path": "gradlew",
    "chars": 8047,
    "preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "gradlew.bat",
    "chars": 2763,
    "preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
  },
  {
    "path": "settings.gradle.kts",
    "chars": 58,
    "preview": "rootProject.name = \"Kotlin-Algorithms-and-Design-Patterns\""
  },
  {
    "path": "src/main/kotlin/design_patterns/Abstract Factory.kt",
    "chars": 797,
    "preview": "package design_patterns\n\n/**\n *\n * Abstract factory is a generative design pattern that allows\n *\n * you to create famil"
  },
  {
    "path": "src/main/kotlin/design_patterns/Adapter.kt",
    "chars": 668,
    "preview": "package design_patterns\n\n/**\n *\n * Adapter is a structural design pattern that allows objects with incompatible interfac"
  },
  {
    "path": "src/main/kotlin/design_patterns/Bridge.kt",
    "chars": 2551,
    "preview": "package design_patterns\n\n/**\n *\n * Bridge is a structural design pattern used to separate abstraction and implementation"
  },
  {
    "path": "src/main/kotlin/design_patterns/Builder.kt",
    "chars": 3653,
    "preview": "package design_patterns\n\n/**\n *\n * Builder is is a generative design pattern that is used to create complex objects,\n *\n"
  },
  {
    "path": "src/main/kotlin/design_patterns/Command.kt",
    "chars": 3404,
    "preview": "package design_patterns\n\n/**\n *\n * Command is a behavioral pattern that encapsulates a request to perform an action as a"
  },
  {
    "path": "src/main/kotlin/design_patterns/Composite.kt",
    "chars": 1499,
    "preview": "package design_patterns\n\n/**\n *\n * Composite is a structural design pattern that organizes objects into a tree structure"
  },
  {
    "path": "src/main/kotlin/design_patterns/Decorator.kt",
    "chars": 1404,
    "preview": "package design_patterns\n\n/**\n *\n * Decorator is a structural design pattern that adds new functionality to an object:\n *"
  },
  {
    "path": "src/main/kotlin/design_patterns/Facade.kt",
    "chars": 2555,
    "preview": "package design_patterns\n\n/**\n *\n * Facade is a structural design pattern that simplifies the interface to a group of int"
  },
  {
    "path": "src/main/kotlin/design_patterns/Factory Method.kt",
    "chars": 2274,
    "preview": "package design_patterns\n\n/**\n *\n * A factory method is a generic design pattern that defines\n *\n * a common interface fo"
  },
  {
    "path": "src/main/kotlin/design_patterns/Flyweight.kt",
    "chars": 1370,
    "preview": "package design_patterns\n\n/**\n *\n * Flyweight is a structural design pattern that reduces memory costs by reusing a famil"
  },
  {
    "path": "src/main/kotlin/design_patterns/Interpreter.kt",
    "chars": 1900,
    "preview": "package design_patterns\n\n/**\n *\n * Interpreter is a behavioral design pattern that defines a simple language grammar for"
  },
  {
    "path": "src/main/kotlin/design_patterns/Iterator.kt",
    "chars": 817,
    "preview": "package design_patterns\n\n/**\n *\n * Iterator is a behavioral design pattern that provides a mechanism for sequentially en"
  },
  {
    "path": "src/main/kotlin/design_patterns/Mediator.kt",
    "chars": 3095,
    "preview": "package design_patterns\n\n/**\n *\n * Mediator is a behavioral design pattern that reduces the coupling of many classes amo"
  },
  {
    "path": "src/main/kotlin/design_patterns/Memento.kt",
    "chars": 1177,
    "preview": "package design_patterns\n\n/**\n *\n * Memento is a behavioral design pattern that allows without violating encapsulation to"
  },
  {
    "path": "src/main/kotlin/design_patterns/Observer.kt",
    "chars": 1134,
    "preview": "package design_patterns\n\n/**\n *\n * Observer is is a behavioral design pattern that defines a one-to-many relationship be"
  },
  {
    "path": "src/main/kotlin/design_patterns/Prototype.kt",
    "chars": 1879,
    "preview": "package design_patterns\n\n/**\n *\n * Prototype is a generative design pattern that allows you to copy objects\n *\n * withou"
  },
  {
    "path": "src/main/kotlin/design_patterns/Proxy.kt",
    "chars": 3016,
    "preview": "package design_patterns\n\n/**\n *\n * Proxy is a structural design pattern that provides an object\n *\n * that controls acce"
  },
  {
    "path": "src/main/kotlin/design_patterns/Singleton.kt",
    "chars": 900,
    "preview": "package design_patterns\n\n/**\n *\n * Singleton is a generative design pattern that guarantees the existence of one instanc"
  },
  {
    "path": "src/main/kotlin/design_patterns/State.kt",
    "chars": 2521,
    "preview": "package design_patterns\n\n/**\n *\n * State is a behavioral design pattern that controls changes in the behavior of an obje"
  },
  {
    "path": "src/main/kotlin/design_patterns/Strategy.kt",
    "chars": 2187,
    "preview": "package design_patterns\n\n/**\n *\n * Strategy is a behavioral design pattern used to define a family of algorithms,\n *\n * "
  },
  {
    "path": "src/main/kotlin/design_patterns/Template Method.kt",
    "chars": 1221,
    "preview": "package design_patterns\n\n/**\n *\n * Template method a behavioral design pattern that defines the basis of an algorithm\n *"
  },
  {
    "path": "src/main/kotlin/design_patterns/Visitor.kt",
    "chars": 3214,
    "preview": "package design_patterns\n\n/**\n *\n * Visitor is a behavioral design pattern that allows you to add a new operation\n *\n * t"
  },
  {
    "path": "src/main/kotlin/design_patterns/Сhain Of Responsibilities.kt",
    "chars": 1410,
    "preview": "package design_patterns\n\n/**\n *\n * Chain of responsibility is a behavioral design pattern that allows requests to be sen"
  },
  {
    "path": "src/main/kotlin/other/BinaryDigitsCounter.kt",
    "chars": 1499,
    "preview": "package other\n\n/**\n *\n * This algorithm counts the number of ones and zeros in a binary string\n *\n * and implemented on "
  },
  {
    "path": "src/main/kotlin/other/EuclidAlgorithm.kt",
    "chars": 927,
    "preview": "package other\n\n/**\n *\n * Euclid's algorithm for finding the greatest common divisor\n *\n */\n\nclass EuclidAlgorithm {\n\n   "
  },
  {
    "path": "src/main/kotlin/other/Factorial.kt",
    "chars": 997,
    "preview": "package other\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n */\n\nclass Factorial {\n\n    /**\n "
  },
  {
    "path": "src/main/kotlin/other/FactorialAdvanced.kt",
    "chars": 5169,
    "preview": "package other\n\nimport java.math.BigInteger\n\n/**\n *\n * This algorithm is taken from Google Guava library\n *\n */\n\nclass Fa"
  },
  {
    "path": "src/main/kotlin/other/FactorialBigWithCache.kt",
    "chars": 849,
    "preview": "package other\n\nimport java.math.BigInteger\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n * o"
  },
  {
    "path": "src/main/kotlin/other/FactorialWithCache.kt",
    "chars": 657,
    "preview": "package other\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n * optimization: caching previous"
  },
  {
    "path": "src/main/kotlin/other/FizzBuzz.kt",
    "chars": 721,
    "preview": "package other\n\n/**\n * The simplest FizzBuzz game\n *\n * description: the player says numbers in sequence, provided:\n *  -"
  },
  {
    "path": "src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt",
    "chars": 1503,
    "preview": "package other\n\n/**\n *\n * Knut Morris Pratt's Algorithm for finding a substring in a string\n *\n */\n\nclass KnuthMorrisPrat"
  },
  {
    "path": "src/main/kotlin/other/LevenshteinLengthAlgorithm.kt",
    "chars": 864,
    "preview": "package other\n\nimport java.lang.Integer.min\n\n/**\n *\n * Algorithm for determining the Levenshtein distance\n *\n */\n\nclass "
  },
  {
    "path": "src/main/kotlin/other/MaxAlgorithm.kt",
    "chars": 1008,
    "preview": "package other\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Algorithm for finding the maximum value from a list\n"
  },
  {
    "path": "src/main/kotlin/other/MinAlgorithm.kt",
    "chars": 931,
    "preview": "package other\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Algorithm for finding the minimum value from a list\n"
  },
  {
    "path": "src/main/kotlin/other/PalindromeAlgorithm.kt",
    "chars": 777,
    "preview": "package other\n\n/**\n *\n * Algorithm for checking a string for a palindrome\n *\n * P.S. A palindrome is a word, number, phr"
  },
  {
    "path": "src/main/kotlin/other/ParenthesisCheckAlgorithm.kt",
    "chars": 1154,
    "preview": "package other\n\n/**\n *\n * Algorithm for checking a string for correct placement of parentheses using stack\n *\n * ([]) - c"
  },
  {
    "path": "src/main/kotlin/other/ReverseArrayAlgorithm.kt",
    "chars": 399,
    "preview": "package other\n\n/**\n *\n * Algorithm for reversing the order of an array\n *\n * complexity: O(n/2) + O(n)\n *\n */\n\nclass Rev"
  },
  {
    "path": "src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt",
    "chars": 866,
    "preview": "package other\n\n/**\n *\n * The sieve of Eratosthenes allows you to efficiently calculate a series of prime numbers\n *\n * a"
  },
  {
    "path": "src/main/kotlin/other/Sqrt.kt",
    "chars": 546,
    "preview": "package other\n\n/**\n *\n * Algorithm for finding the square root of a number\n *\n * read the wikipedia article: https://en."
  },
  {
    "path": "src/main/kotlin/other/StringEqualsHashAlgorithm.kt",
    "chars": 1121,
    "preview": "package other\n\n/**\n *\n * Algorithm for comparing two strings with a hash\n *\n */\n\nclass StringEqualsHashAlgorithm {\n\n    "
  },
  {
    "path": "src/main/kotlin/other/SwapAlgorithm.kt",
    "chars": 1582,
    "preview": "package other\n\n/**\n *\n * Algorithm for exchanging two variables without a third additional\n *\n */\n\nclass SwapAlgorithm {"
  },
  {
    "path": "src/main/kotlin/search/BinarySearch.kt",
    "chars": 2488,
    "preview": "package search\n\n/**\n *\n * Binary search algorithm only works for sorted lists and arrays\n *\n * best time: 1\n * worst tim"
  },
  {
    "path": "src/main/kotlin/search/LinearSearch.kt",
    "chars": 412,
    "preview": "package search\n\n/**\n *\n * Linear search algorithm\n *\n * best time: 1\n * worst time: n\n * amount of memory: 1\n *\n */\n\ncla"
  },
  {
    "path": "src/main/kotlin/sorting/BubbleSort.kt",
    "chars": 1438,
    "preview": "package sorting\n\n/**\n *\n * Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm\n *\n * that "
  },
  {
    "path": "src/main/kotlin/sorting/CountingSort.kt",
    "chars": 1205,
    "preview": "package sorting\n\n/**\n *\n * Counting sort is a sorting technique based on keys between a specific range\n *\n * worst time:"
  },
  {
    "path": "src/main/kotlin/sorting/InsertionSort.kt",
    "chars": 791,
    "preview": "package sorting\n\n/**\n *\n * Insertion sort is a simple sorting algorithm that works similar to the way you sort playing c"
  },
  {
    "path": "src/main/kotlin/sorting/MergeSort.kt",
    "chars": 3302,
    "preview": "package sorting\n\n/**\n *\n * Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945\n *"
  },
  {
    "path": "src/main/kotlin/sorting/QuickSort.kt",
    "chars": 1183,
    "preview": "package sorting\n\nimport kotlin.random.Random\n\n/**\n *\n * QuickSort is a sorting algorithm based on the Divide and Conquer"
  },
  {
    "path": "src/main/kotlin/sorting/RadixSort.kt",
    "chars": 1144,
    "preview": "package sorting\n\n/**\n *\n * Radix Sort is a linear sorting algorithm that sorts elements by processing them digit by digi"
  },
  {
    "path": "src/main/kotlin/sorting/SelectionSort.kt",
    "chars": 842,
    "preview": "package sorting\n\n/**\n *\n * Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting"
  },
  {
    "path": "src/main/kotlin/sorting/TimSort.kt",
    "chars": 3476,
    "preview": "package sorting\n\nimport kotlin.math.min\n\n/**\n *\n * Tim Sort is a hybrid sorting algorithm derived from merge sort and in"
  },
  {
    "path": "src/main/kotlin/structures/BinaryTree.kt",
    "chars": 6609,
    "preview": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Binary tree consists of nodes each of which has a maximum of "
  },
  {
    "path": "src/main/kotlin/structures/CircularLinkedList.kt",
    "chars": 5591,
    "preview": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the"
  },
  {
    "path": "src/main/kotlin/structures/DoubleLinkedList.kt",
    "chars": 5763,
    "preview": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the"
  },
  {
    "path": "src/main/kotlin/structures/DynamicArray.kt",
    "chars": 3134,
    "preview": "package structures\n\nimport java.lang.IllegalStateException\n\n/**\n *\n * Dynamic array or array list is a random access, va"
  },
  {
    "path": "src/main/kotlin/structures/Graph.kt",
    "chars": 3050,
    "preview": "package structures\n\nimport java.util.LinkedList\nimport kotlin.collections.LinkedHashSet\n\n/**\n *\n * Graph is a non-linear"
  },
  {
    "path": "src/main/kotlin/structures/GraphWithWeights.kt",
    "chars": 3587,
    "preview": "package structures\n\n\n/**\n *\n * Graph is a non-linear data structure consisting of vertices and edges.\n *\n * The vertices"
  },
  {
    "path": "src/main/kotlin/structures/Matrix.kt",
    "chars": 4271,
    "preview": "package structures\n\nimport java.lang.IllegalArgumentException\n\nfun matrix(apply: Matrix.() -> Unit): Matrix {\n    val ma"
  },
  {
    "path": "src/main/kotlin/structures/MaxHeap.kt",
    "chars": 2913,
    "preview": "package structures\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Max-heap is a binary tree in which each parent "
  },
  {
    "path": "src/main/kotlin/structures/MinHeap.kt",
    "chars": 2914,
    "preview": "package structures\n\nimport java.lang.IllegalArgumentException\n\n\n/**\n *\n * Min-heap is a binary tree in which each parent"
  },
  {
    "path": "src/main/kotlin/structures/Queue.kt",
    "chars": 1083,
    "preview": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Queue is a data structure that follows the FIFO (first in, fi"
  },
  {
    "path": "src/main/kotlin/structures/SingleLinkedList.kt",
    "chars": 4198,
    "preview": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the"
  },
  {
    "path": "src/main/kotlin/structures/Stack1.kt",
    "chars": 1135,
    "preview": "package structures\n\nimport java.lang.IllegalArgumentException\nimport java.util.ArrayList\n\n/**\n *\n * Stack is a linear da"
  },
  {
    "path": "src/main/kotlin/structures/Stack2.kt",
    "chars": 1174,
    "preview": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Stack is a linear data structure that follows the LIFO (Last-"
  },
  {
    "path": "src/test/kotlin/TestUtils.kt",
    "chars": 338,
    "preview": "\nimport kotlin.random.Random\n\nobject TestUtils {\n\n    fun randomArray(size: Int) =  List(size) { Random.nextInt(100) }.t"
  },
  {
    "path": "src/test/kotlin/design_patterns/AbstractFactoryTest.kt",
    "chars": 1000,
    "preview": "package design_patterns\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.core.IsInstanceOf.instanceOf\ni"
  },
  {
    "path": "src/test/kotlin/design_patterns/AdapterTest.kt",
    "chars": 545,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class AdapterTest {\n\n    @"
  },
  {
    "path": "src/test/kotlin/design_patterns/BridgeTest.kt",
    "chars": 1253,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass BridgeTest {\n\n    @Test\n    f"
  },
  {
    "path": "src/test/kotlin/design_patterns/BuilderTest.kt",
    "chars": 2577,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BuilderTest {\n\n    @"
  },
  {
    "path": "src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt",
    "chars": 1171,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass ChainOfResponsibilitiesTest {"
  },
  {
    "path": "src/test/kotlin/design_patterns/CommandTest.kt",
    "chars": 2171,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class CommandTest {\n\n    @"
  },
  {
    "path": "src/test/kotlin/design_patterns/CompositeTest.kt",
    "chars": 1089,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass CompositeTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/design_patterns/DecoratorTest.kt",
    "chars": 439,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass DecoratorTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/design_patterns/FacadeTest.kt",
    "chars": 1075,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FacadeTest {\n\n    @T"
  },
  {
    "path": "src/test/kotlin/design_patterns/FactoryMethodTest.kt",
    "chars": 2180,
    "preview": "package design_patterns\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.core.IsInstanceOf.instanceOf\ni"
  },
  {
    "path": "src/test/kotlin/design_patterns/FlyweightTest.kt",
    "chars": 1113,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass FlyweightTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/design_patterns/InterpreterTest.kt",
    "chars": 681,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass InterpreterTest {\n\n    @Test\n"
  },
  {
    "path": "src/test/kotlin/design_patterns/IteratorTest.kt",
    "chars": 556,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass IteratorTest {\n\n    @Test\n   "
  },
  {
    "path": "src/test/kotlin/design_patterns/MediatorTest.kt",
    "chars": 1050,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass MediatorTest {\n\n    @Test\n   "
  },
  {
    "path": "src/test/kotlin/design_patterns/MementoTest.kt",
    "chars": 904,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass MementoTest {\n\n    @Test\n    "
  },
  {
    "path": "src/test/kotlin/design_patterns/ObserverTest.kt",
    "chars": 830,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class ObserverTest {\n\n    "
  },
  {
    "path": "src/test/kotlin/design_patterns/PrototypeTest.kt",
    "chars": 1149,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass PrototypeTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/design_patterns/ProxyTest.kt",
    "chars": 973,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass ProxyTest {\n\n    @Test\n    fu"
  },
  {
    "path": "src/test/kotlin/design_patterns/SingletonTest.kt",
    "chars": 462,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SingletonTest {\n\n   "
  },
  {
    "path": "src/test/kotlin/design_patterns/StateTest.kt",
    "chars": 1571,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass StateTest {\n\n    @Test\n    fu"
  },
  {
    "path": "src/test/kotlin/design_patterns/StrategyTest.kt",
    "chars": 1714,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class StrategyTest {\n\n    "
  },
  {
    "path": "src/test/kotlin/design_patterns/TemplateMethodTest.kt",
    "chars": 1014,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass TemplateMethodTest {\n\n    @Te"
  },
  {
    "path": "src/test/kotlin/design_patterns/VisitorTest.kt",
    "chars": 1887,
    "preview": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class VisitorTest {\n\n    p"
  },
  {
    "path": "src/test/kotlin/other/BinaryDigitsCounterTest.kt",
    "chars": 992,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinaryDigitsCounterTest {\n\n   "
  },
  {
    "path": "src/test/kotlin/other/EuclidAlgorithmTest.kt",
    "chars": 1489,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class EuclidAlgorithmTest {\n\n    pri"
  },
  {
    "path": "src/test/kotlin/other/FactorialAdvancedTest.kt",
    "chars": 4934,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialAdvancedTest {\n\n    p"
  },
  {
    "path": "src/test/kotlin/other/FactorialBigWithCacheTest.kt",
    "chars": 583,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialBigWithCacheTest {\n\n "
  },
  {
    "path": "src/test/kotlin/other/FactorialTest.kt",
    "chars": 1208,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialTest {\n\n    private v"
  },
  {
    "path": "src/test/kotlin/other/FactorialWithCacheTest.kt",
    "chars": 396,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialWithCacheTest {\n\n    "
  },
  {
    "path": "src/test/kotlin/other/FizzBuzzTest.kt",
    "chars": 757,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FizzBuzzTest {\n\n    private va"
  },
  {
    "path": "src/test/kotlin/other/KnuthMorrisPrattAlgorithmTest.kt",
    "chars": 1848,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class KnuthMorrisPrattAlgorithmTest "
  },
  {
    "path": "src/test/kotlin/other/LevenshteinLengthAlgorithmTest.kt",
    "chars": 789,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class LevenshteinLengthAlgorithmTest"
  },
  {
    "path": "src/test/kotlin/other/MaxAlgorithmTest.kt",
    "chars": 991,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MaxAlgorithmTest {\n\n    privat"
  },
  {
    "path": "src/test/kotlin/other/MinAlgorithmTest.kt",
    "chars": 989,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MinAlgorithmTest {\n\n    privat"
  },
  {
    "path": "src/test/kotlin/other/PalindromeAlgorithmTest.kt",
    "chars": 2725,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass PalindromeAlgorithmTest {\n\n    private "
  },
  {
    "path": "src/test/kotlin/other/ParenthesisCheckAlgorithmTest.kt",
    "chars": 1793,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class ParenthesisCheckAlgorithmTest "
  },
  {
    "path": "src/test/kotlin/other/ReverseArrayAlgorithmTest.kt",
    "chars": 759,
    "preview": "package other\n\nimport org.junit.Test\nimport junit.framework.TestCase.assertEquals\n\ninternal class ReverseArrayAlgorithmT"
  },
  {
    "path": "src/test/kotlin/other/SieveOfEratosthenesAlgorithmTest.kt",
    "chars": 1223,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SieveOfEratosthenesAlgorithmTe"
  },
  {
    "path": "src/test/kotlin/other/SqrtTest.kt",
    "chars": 314,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SqrtTest {\n\n    @Test\n    fun "
  },
  {
    "path": "src/test/kotlin/other/StringEqualsHashAlgorithmTest.kt",
    "chars": 624,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class StringEqualsHashAlgorithmTest "
  },
  {
    "path": "src/test/kotlin/other/SwapAlgorithmTest.kt",
    "chars": 1298,
    "preview": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SwapAlgorithmTest {\n\n    priva"
  },
  {
    "path": "src/test/kotlin/search/BinarySearchTest.kt",
    "chars": 2218,
    "preview": "package search\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinarySearchTest {\n\n    priva"
  },
  {
    "path": "src/test/kotlin/search/LinearSearchTest.kt",
    "chars": 737,
    "preview": "package search\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class LinearSearchTest {\n\n    @Test"
  },
  {
    "path": "src/test/kotlin/sorting/BubbleSortTest.kt",
    "chars": 1728,
    "preview": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\ninternal c"
  },
  {
    "path": "src/test/kotlin/sorting/CountingSortTest.kt",
    "chars": 1146,
    "preview": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\n\nclass CountingSortTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/sorting/InsertionSortTest.kt",
    "chars": 954,
    "preview": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\ninternal c"
  },
  {
    "path": "src/test/kotlin/sorting/MergeSortTest.kt",
    "chars": 1763,
    "preview": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass Merg"
  },
  {
    "path": "src/test/kotlin/sorting/QuickSortTest.kt",
    "chars": 942,
    "preview": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass Quic"
  },
  {
    "path": "src/test/kotlin/sorting/RadixSortTest.kt",
    "chars": 935,
    "preview": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\nclass Radi"
  },
  {
    "path": "src/test/kotlin/sorting/SelectionSortTest.kt",
    "chars": 938,
    "preview": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\nclass Sele"
  },
  {
    "path": "src/test/kotlin/sorting/TimSortTest.kt",
    "chars": 928,
    "preview": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass TimS"
  },
  {
    "path": "src/test/kotlin/structures/BinaryTreeTest.kt",
    "chars": 4932,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinaryTreeTest {\n\n    @Te"
  },
  {
    "path": "src/test/kotlin/structures/CircularLinkedListTest.kt",
    "chars": 5572,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class CircularLinkedListTest {\n"
  },
  {
    "path": "src/test/kotlin/structures/DoubleLinkedListTest.kt",
    "chars": 5070,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class DoubleLinkedListTest {\n\n "
  },
  {
    "path": "src/test/kotlin/structures/DynamicArrayTest.kt",
    "chars": 1357,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class DynamicArrayTest {\n\n    @"
  },
  {
    "path": "src/test/kotlin/structures/GraphTest.kt",
    "chars": 2787,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class GraphTest {\n\n    @Test\n  "
  },
  {
    "path": "src/test/kotlin/structures/GraphWithWeightsTest.kt",
    "chars": 2881,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass GraphWithWeightsTest {\n\n    @Test\n"
  },
  {
    "path": "src/test/kotlin/structures/MatrixTest.kt",
    "chars": 5037,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertThrows\nimpo"
  },
  {
    "path": "src/test/kotlin/structures/MaxHeapTest.kt",
    "chars": 1375,
    "preview": "package structures\n\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MaxHeapTest {\n\n    @Test"
  },
  {
    "path": "src/test/kotlin/structures/MinHeapTest.kt",
    "chars": 1369,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MinHeapTest {\n\n    @Test\n"
  },
  {
    "path": "src/test/kotlin/structures/QueueTest.kt",
    "chars": 1060,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass QueueTest {\n\n    @Test\n    fun tes"
  },
  {
    "path": "src/test/kotlin/structures/SingleLinkedListTest.kt",
    "chars": 4158,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SingleLinkedListTest {\n\n "
  },
  {
    "path": "src/test/kotlin/structures/Stack1Test.kt",
    "chars": 791,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass Stack1Test {\n\n    @Test\n    fun te"
  },
  {
    "path": "src/test/kotlin/structures/Stack2Test.kt",
    "chars": 791,
    "preview": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass Stack2Test {\n\n    @Test\n    fun te"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the KiberneticWorm/Kotlin-Algorithms-and-Design-Patterns GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 140 files (250.1 KB), approximately 66.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!