[
  {
    "path": ".gitignore",
    "content": "# 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\natlassian-ide-plugin.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n### Kotlin ###\n# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.nar\n*.ear\n*.zip\n*.tar.gz\n*.rar\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\nreplay_pid*\n\n### Gradle ###\n.gradle\n**/build/\n!src/**/build/\n\n# Ignore Gradle GUI config\ngradle-app.setting\n\n# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)\n!gradle-wrapper.jar\n\n# Avoid ignore Gradle wrappper properties\n!gradle-wrapper.properties\n\n# Cache of project\n.gradletasknamecache\n\n# Eclipse Gradle plugin generated files\n# Eclipse Core\n.project\n# JDT-specific (Eclipse Java Development Tools)\n.classpath\n\n### Gradle Patch ###\n# Java heap dump\n*.hprof\n\n# End of https://www.toptal.com/developers/gitignore/api/intellij,gradle,kotlin"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2023 Dmitry Tsyvtsyn\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![Алгоритмы на Kotlin](/assets/algo_logo.png)\n\n# Kotlin Algorithms and Design Patterns\n\nThis repository lists the most common algorithms, data structures, and design patterns written in the Kotlin programming language.\n\nAll code is divided into separate packages:\n\n1. <code>sorting</code> - sorting algorithms\n2. <code>search</code> - search algorithms\n3. <code>structures</code> - data structure (lists, arrays, stack, queue, binary trees, e.t.c)\n4. <code>design-patterns</code> - design patterns\n5. <code>other</code> - other algorithms (Levenshtein distance, Knut Morris Pratt algorithm, e.t.c)\n\nFor each code file, tests are made, which are located in the <code>test/kotlin</code> directory\n\nAlso, whenever possible, I add *javadoc* for each class, method, and file\n\nContent:\n\n1. package <code>design_patterns</code> - design patterns\n    * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt)\n    * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt)\n    * [Bridge](/src/main/kotlin/design_patterns/Bridge.kt)\n    * [Builder](/src/main/kotlin/design_patterns/Builder.kt)\n    * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt)\n    * [Command](/src/main/kotlin/design_patterns/Command.kt)\n    * [Composite](/src/main/kotlin/design_patterns/Composite.kt)\n    * [Decorator](/src/main/kotlin/design_patterns/Decorator.kt)\n    * [Facade](/src/main/kotlin/design_patterns/Facade.kt)\n    * [Factory Method](/src/main/kotlin/design_patterns/Factory%20Method.kt)\n    * [Flyweight](/src/main/kotlin/design_patterns/Flyweight.kt)\n    * [Interpreter](/src/main/kotlin/design_patterns/Interpreter.kt)\n    * [Iterator](/src/main/kotlin/design_patterns/Iterator.kt)\n    * [Mediator](/src/main/kotlin/design_patterns/Mediator.kt)\n    * [Memento](/src/main/kotlin/design_patterns/Memento.kt)\n    * [Observer](/src/main/kotlin/design_patterns/Observer.kt)\n    * [Prototype](/src/main/kotlin/design_patterns/Prototype.kt)\n    * [Proxy](/src/main/kotlin/design_patterns/Proxy.kt)\n    * [Singleton](/src/main/kotlin/design_patterns/Singleton.kt)\n    * [State](/src/main/kotlin/design_patterns/State.kt)\n    * [Strategy](/src/main/kotlin/design_patterns/Strategy.kt)\n    * [Template Method](/src/main/kotlin/design_patterns/Template%20Method.kt)\n    * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt)\n\n2. package <code>structures</code> - data structure\n    * [Binary tree](/src/main/kotlin/structures/BinaryTree.kt)\n    * [Stack 1st implementation](/src/main/kotlin/structures/Stack1.kt)\n    * [Stack 2nd implementation](/src/main/kotlin/structures/Stack2.kt)\n    * [Queue](/src/main/kotlin/structures/Queue.kt)\n    * [Undirected Graph](/src/main/kotlin/structures/Graph.kt)\n    * [Directed Graph with weights](/src/main/kotlin/structures/GraphWithWeights.kt)\n    * [Matrix](/src/main/kotlin/structures/Matrix.kt)\n    * [Dynamic Array](/src/main/kotlin/structures/DynamicArray.kt)\n    * [Single linked list](/src/main/kotlin/structures/SingleLinkedList.kt)\n    * [Double linked list](/src/main/kotlin/structures/DoubleLinkedList.kt)\n    * [Min-heap](/src/main/kotlin/structures/MinHeap.kt)\n    * [Max-heap](/src/main/kotlin/structures/MaxHeap.kt)\n\n3. package <code>sorting</code> - sorting algorithms\n    * [Bubble sort](/src/main/kotlin/sorting/BubbleSort.kt)\n    * [Insertion sort](/src/main/kotlin/sorting/InsertionSort.kt)\n    * [Merge sort](/src/main/kotlin/sorting/MergeSort.kt)\n    * [Quick sort](/src/main/kotlin/sorting/QuickSort.kt)\n    * [Selection sort](/src/main/kotlin/sorting/SelectionSort.kt)\n    * [Radix sort](/src/main/kotlin/sorting/RadixSort.kt)\n    * [Tim sort](/src/main/kotlin/sorting/TimSort.kt)\n    * [Count sort](/src/main/kotlin/sorting/CountingSort.kt)\n\n4. package <code>search</code> - search algorithms\n    * [Binary search](/src/main/kotlin/search/BinarySearch.kt)\n    * [Linear search](/src/main/kotlin/search/LinearSearch.kt)\n\n5. package <code>other</code> - other algorithms\n    * [Finite state machine](/src/main/kotlin/other/BinaryDigitsCounter.kt)\n    * [Euclid's algorithm](/src/main/kotlin/other/EuclidAlgorithm.kt)\n    * [Factorial](/src/main/kotlin/other/Factorial.kt)\n    * [Factorial from Google Guava library](/src/main/kotlin/other/FactorialAdvanced.kt)\n    * [Factorial of BigInteger's with cache](/src/main/kotlin/other/FactorialBigWithCache.kt)\n    * [Factorial with cache](/src/main/kotlin/other/FactorialWithCache.kt)\n    * [FizzBuzz](/src/main/kotlin/other/FizzBuzz.kt)\n    * [Knut Morris Pratt's Algorithm for finding a substring](/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt)\n    * [Levenshtein distance](/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt)\n    * [Finding the maximum](/src/main/kotlin/other/MaxAlgorithm.kt)\n    * [Finding the minimum](/src/main/kotlin/other/MinAlgorithm.kt)\n    * [Palindrome](/src/main/kotlin/other/PalindromeAlgorithm.kt)\n    * [Parenthesis checking algorithm](/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt)\n    * [Reverse Array](/src/main/kotlin/other/ReverseArrayAlgorithm.kt)\n    * [Sieve of Eratosthenes](/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt)\n    * [The square root of a number](/src/main/kotlin/other/Sqrt.kt)\n    * [StringEqualsHash](/src/main/kotlin/other/StringEqualsHashAlgorithm.kt)\n    * [Swap algorithm](/src/main/kotlin/other/SwapAlgorithm.kt)\n\n## Your wishes and ideas\n\nIf 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)\n\n## License\n\n      MIT License\n\n      Copyright (c) 2023 Dmitry Tsyvtsyn\n\n      Permission is hereby granted, free of charge, to any person obtaining a copy\n      of this software and associated documentation files (the \"Software\"), to deal\n      in the Software without restriction, including without limitation the rights\n      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n      copies of the Software, and to permit persons to whom the Software is\n      furnished to do so, subject to the following conditions:\n\n      The above copyright notice and this permission notice shall be included in all\n      copies or substantial portions of the Software.\n\n      THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n      SOFTWARE.\n"
  },
  {
    "path": "README_ru.md",
    "content": "![Алгоритмы на Kotlin](/assets/algo_ru.png)\n\n# Kotlin Algorithms and Design Patterns\n\nВ этом репозитории приведены наиболее распространенные алгоритмы, структуры данных и паттерны проектирования, написанные на языке программирования Kotlin.\n\nВесь код разбит по отдельным пакетам:\n\n1. <code>ru.sorting</code> - алгоритмы сортировки\n2. <code>ru.search</code> - алгоритмы поиска\n3. <code>ru.structures</code> - структуры данных (списки, массивы, стэк, очередь, бинарное дерево и др.)\n4. <code>design-patterns</code> - паттерны проектирования\n5. <code>ru.other</code> - другие алгоритмы (расстояние Левенштейна, алгоритм Кнута Морриса Пратта и т.д.)\n\nДля каждого файла с кодом сделаны тесты, которые находятся в директории <code>test/kotlin</code>\n\nТакже по возможности я добавляю *javadoc* для каждого класса, метода и файла\n\nСтруктура:\n\n1. пакет <code>ru.design_patterns</code> - паттерны проектирования\n    * [Abstract Factory](/src/main/kotlin/design_patterns/Abstract%20Factory.kt)\n    * [Adapter](/src/main/kotlin/design_patterns/Adapter.kt)\n    * [Bridge](/src/main/kotlin/design_patterns/Bridge.kt)\n    * [Builder](/src/main/kotlin/design_patterns/Builder.kt)\n    * [Chain Of Responsibilities](/src/main/kotlin/design_patterns/Сhain%20Of%20Responsibilities.kt)\n    * [Command](/src/main/kotlin/design_patterns/Command.kt)\n    * [Composite](/src/main/kotlin/design_patterns/Composite.kt)\n    * [Decorator](/src/main/kotlin/design_patterns/Decorator.kt)\n    * [Facade](/src/main/kotlin/design_patterns/Facade.kt)\n    * [Factory Method](/src/main/kotlin/design_patterns/Factory%20Method.kt)\n    * [Flyweight](/src/main/kotlin/design_patterns/Flyweight.kt)\n    * [Interpreter](/src/main/kotlin/design_patterns/Interpreter.kt)\n    * [Iterator](/src/main/kotlin/design_patterns/Iterator.kt)\n    * [Mediator](/src/main/kotlin/design_patterns/Mediator.kt)\n    * [Memento](/src/main/kotlin/design_patterns/Memento.kt)\n    * [Observer](/src/main/kotlin/design_patterns/Observer.kt)\n    * [Prototype](/src/main/kotlin/design_patterns/Prototype.kt)\n    * [Proxy](/src/main/kotlin/design_patterns/Proxy.kt)\n    * [Singleton](/src/main/kotlin/design_patterns/Singleton.kt)\n    * [State](/src/main/kotlin/design_patterns/State.kt)\n    * [Strategy](/src/main/kotlin/design_patterns/Strategy.kt)\n    * [Template Method](/src/main/kotlin/design_patterns/Template%20Method.kt)\n    * [Visitor](/src/main/kotlin/design_patterns/Visitor.kt)\n\n2. пакет <code>ru.structures</code> - структуры данных\n    * [Бинарное дерево](/src/main/kotlin/structures/BinaryTree.kt)\n    * [Стэк 1-ая реализация](/src/main/kotlin/structures/Stack1.kt)\n    * [Стэк 2-ая реализация](/src/main/kotlin/structures/Stack2.kt)\n    * [Очередь](/src/main/kotlin/structures/Queue.kt)\n    * [Неориентированный граф](/src/main/kotlin/structures/Graph.kt)\n    * [Ориентированный граф с весами](/src/main/kotlin/structures/GraphWithWeights.kt)\n    * [Матрица](/src/main/kotlin/structures/Matrix.kt)\n    * [Динамический массив](/src/main/kotlin/structures/DynamicArray.kt)\n    * [Односвязный список](/src/main/kotlin/structures/SingleLinkedList.kt)\n    * [Двусвязный список](/src/main/kotlin/structures/DoubleLinkedList.kt)\n    * [Min-куча](/src/main/kotlin/structures/MinHeap.kt)\n    * [Max-куча](/src/main/kotlin/structures/MaxHeap.kt)\n\n3. пакет <code>ru.sorting</code> - алгоритмы сортировки\n    * [Пузырьковая сортировка](/src/main/kotlin/sorting/BubbleSort.kt)\n    * [Сортировка вставками](/src/main/kotlin/sorting/InsertionSort.kt)\n    * [Сортировака слиянием](/src/main/kotlin/sorting/MergeSort.kt)\n    * [Быстрая сортировка](/src/main/kotlin/sorting/QuickSort.kt)\n    * [Сортировка выбором](/src/main/kotlin/sorting/SelectionSort.kt)\n    * [Поразрядная сортировка](/src/main/kotlin/sorting/RadixSort.kt)\n    * [Tim sort](/src/main/kotlin/sorting/TimSort.kt)\n    * [Сортировка подсчётом](/src/main/kotlin/sorting/CountingSort.kt)\n\n4. пакет <code>ru.search</code> - алгоритмы поиска\n    * [Бинарный поиск](/src/main/kotlin/search/BinarySearch.kt)\n    * [Линейный поиск](/src/main/kotlin/search/LinearSearch.kt)\n\n5. пакет <code>ru.other</code> - другие алгоритмы\n    * [Конечный автомат](/src/main/kotlin/other/BinaryDigitsCounter.kt)\n    * [Алгоритм Эвклида](/src/main/kotlin/other/EuclidAlgorithm.kt)\n    * [Факториал](/src/main/kotlin/other/Factorial.kt)\n    * [Факториал из Google Guava библиотеки](/src/main/kotlin/other/FactorialAdvanced.kt)\n    * [Факториал BigInteger'ов с кэшем](/src/main/kotlin/other/FactorialBigWithCache.kt)\n    * [Факториал с кэшем](/src/main/kotlin/other/FactorialWithCache.kt)\n    * [FizzBuzz](/src/main/kotlin/other/FizzBuzz.kt)\n    * [Алгоритм Кнута Морриса Пратта для поиска подстроки](/src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt)\n    * [Расстояние Левенштейна](/src/main/kotlin/other/LevenshteinLengthAlgorithm.kt)\n    * [Поиск максимума](/src/main/kotlin/other/MaxAlgorithm.kt)\n    * [Поиск минимума](/src/main/kotlin/other/MinAlgorithm.kt)\n    * [Палиндром](/src/main/kotlin/other/PalindromeAlgorithm.kt)\n    * [Проверка скобок на корректность](/src/main/kotlin/other/ParenthesisCheckAlgorithm.kt)\n    * [Алгоритм переворота массива](/src/main/kotlin/other/ReverseArrayAlgorithm.kt)\n    * [Решето Эратосфена](/src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt)\n    * [Квадратный корень из числа](/src/main/kotlin/other/Sqrt.kt)\n    * [Сравнение строк с помощью хэша](/src/main/kotlin/other/StringEqualsHashAlgorithm.kt)\n    * [Алгоритм обмена двух переменных](/src/main/kotlin/other/SwapAlgorithm.kt)\n\n## Ваши пожелания и идеи\n\nЕсли вы заинтересовались моим репозиторием или у вас появились идеи как его улучшить или что-то добавить, напишите: [Telegram](https://t.me/rwcwuwr), [Gmail](mailto:dmitry.kind.2@gmail.com)\n\n## Лицензия\n\n      MIT License\n\n      Copyright (c) 2023 Dmitry Tsyvtsyn\n\n      Permission is hereby granted, free of charge, to any person obtaining a copy\n      of this software and associated documentation files (the \"Software\"), to deal\n      in the Software without restriction, including without limitation the rights\n      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n      copies of the Software, and to permit persons to whom the Software is\n      furnished to do so, subject to the following conditions:\n\n      The above copyright notice and this permission notice shall be included in all\n      copies or substantial portions of the Software.\n\n      THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n      SOFTWARE.\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "plugins {\n    id(\"org.jetbrains.kotlin.jvm\") version \"1.8.22\"\n}\n\ngroup = \"io.github.dmitrytsyvtsyn.algorithmsdesignpatterns\"\nversion = \"1.0.1\"\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"org.jetbrains.kotlin:kotlin-stdlib\")\n    testImplementation(\"junit:junit:4.13.1\")\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.2-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "kotlin.code.style=official"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@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 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "rootProject.name = \"Kotlin-Algorithms-and-Design-Patterns\""
  },
  {
    "path": "src/main/kotlin/design_patterns/Abstract Factory.kt",
    "content": "package design_patterns\n\n/**\n *\n * Abstract factory is a generative design pattern that allows\n *\n * you to create families of related objects without being tied to\n *\n * the specific classes of objects you create.\n *\n */\n\ninterface Button {\n    fun draw() {}\n}\n\nclass AndroidButton : Button\nclass IOSButton : Button\n\ninterface Text {\n    fun draw() {}\n}\n\nclass AndroidText : Text\nclass IOSText : Text\n\ninterface ButtonFactory {\n    fun createButton() : Button\n    fun createText() : Text\n}\n\nclass AndroidButtonFactory : ButtonFactory {\n    override fun createButton() : Button = AndroidButton()\n    override fun createText(): Text = AndroidText()\n}\n\nclass IOSButtonFactory : ButtonFactory {\n    override fun createButton() : Button = IOSButton()\n    override fun createText(): Text = IOSText()\n}\n"
  },
  {
    "path": "src/main/kotlin/design_patterns/Adapter.kt",
    "content": "package design_patterns\n\n/**\n *\n * Adapter is a structural design pattern that allows objects with incompatible interfaces to work together\n *\n */\n\ninterface EnglishSpeaker {\n    fun speakEnglish(): String\n}\n\nclass EnglishSpeakerImpl : EnglishSpeaker {\n    override fun speakEnglish(): String {\n        return \"Hello, friend!\"\n    }\n}\n\ninterface SpainSpeaker {\n    fun speakSpanish(): String\n}\n\nclass SpainSpeakerAdapter(private val englishSpeaker: EnglishSpeaker) : SpainSpeaker {\n\n    override fun speakSpanish(): String =\n        when (englishSpeaker.speakEnglish()) {\n            \"Hello, friend!\" -> \"Hola, amigo!\"\n            else -> \"No te entiendo\"\n        }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Bridge.kt",
    "content": "package design_patterns\n\n/**\n *\n * Bridge is a structural design pattern used to separate abstraction and implementation\n *\n * so they can change independently\n *\n */\n\n// OperatingSystem implements an internal algorithm for drawing primitives (operating systems are implementations in this example)\nabstract class OperatingSystem(private val name: String, private val version: Int) {\n\n    protected val lines = mutableListOf<String>()\n    protected val circles = mutableListOf<String>()\n\n    abstract fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int)\n\n    abstract fun drawCircle(centerX: Int, centerY: Int, radius: Int)\n\n    override fun toString(): String {\n        return \"\"\"\n            $name $version\n            Lines:\n            ${lines.joinToString(\"\\n\")}\n            Circles:\n            ${circles.joinToString(\"\\n\")}\n        \"\"\".trimIndent()\n    }\n\n}\n\n// different implementations have different algorithms for drawing primitives\nclass WindowsSystem : OperatingSystem(\"Windows\", 10) {\n\n    override fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int) {\n        lines.add(\"Windows graphic subsystem -> startX: $startX, startY: $startY, endX: $endX, endY: $endY\")\n    }\n\n    override fun drawCircle(centerX: Int, centerY: Int, radius: Int) {\n        circles.add(\"Windows graphic subsystem -> centerX: $centerX, centerY: $centerY, radius: $radius\")\n    }\n\n}\n\nclass MacOSSystem : OperatingSystem(\"MacOS\", 14) {\n\n    override fun drawLine(startX: Int, startY: Int, endX: Int, endY: Int) {\n        lines.add(\"MacOS graphic subsystem -> startX: $startX, startY: $startY, endX: $endX, endY: $endY\")\n    }\n\n    override fun drawCircle(centerX: Int, centerY: Int, radius: Int) {\n        circles.add(\"MacOS graphic subsystem -> centerX: $centerX, centerY: $centerY, radius: $radius\")\n    }\n\n}\n\n// we can add new primitives without changing OperatingSystem implementations (primitives are abstractions in this example)\nabstract class GraphicPrimitive {\n    abstract fun draw(system: OperatingSystem)\n}\n\nclass GraphicCirclePrimitive(\n    private val centerX: Int,\n    private val centerY: Int,\n    private val radius: Int\n) : GraphicPrimitive() {\n\n    override fun draw(system: OperatingSystem) {\n        system.drawCircle(centerX, centerY, radius)\n    }\n\n}\n\nclass GraphicLinePrimitive(\n    private val startX: Int,\n    private val startY: Int,\n    private val endX: Int,\n    private val endY: Int\n) : GraphicPrimitive() {\n\n    override fun draw(system: OperatingSystem) {\n        system.drawLine(startX, startY, endX, endY)\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Builder.kt",
    "content": "package design_patterns\n\n/**\n *\n * Builder is is a generative design pattern that is used to create complex objects,\n *\n * separates the construction of an object from its representation\n *\n */\n\n/**\n * The first variant\n */\nclass HttpConnectionClient1 private constructor(\n    private val dnsServerAddress: String,\n    private val callTimeout: Int,\n    private val connectTimeout: Int,\n    private val readTimeout: Int,\n    private val writeTimeout: Int,\n    // class can have many more fields\n) {\n\n    override fun toString() = \"\"\"\n        dns -> $dnsServerAddress\n        call timeout -> $callTimeout\n        connect timeout -> $connectTimeout\n        read timeout -> $readTimeout\n        write timeout -> $writeTimeout\n    \"\"\".trimIndent()\n\n    class Builder {\n        private var dnsServerAddress: String = \"8.8.8.8\"\n        private var callTimeout: Int = 0\n        private var connectTimeout: Int = 10_000\n        private var readTimeout: Int = 10_000\n        private var writeTimeout: Int = 0\n\n        fun dnsServerAddress(address: String) = apply {\n            dnsServerAddress = address\n        }\n\n        fun callTimeout(timeout: Int) = apply {\n            // we can add some checks such as:\n            // if (timeout < 0) throw IllegalArgumentException(\"Uncorrected timeout: $timeout\")\n            callTimeout = timeout\n        }\n\n        fun connectTimeout(timeout: Int) = apply {\n            connectTimeout = timeout\n        }\n\n        fun readTimeout(timeout: Int) = apply {\n            readTimeout = timeout\n        }\n\n        fun writeTimeout(timeout: Int) = apply {\n            writeTimeout = timeout\n        }\n\n        fun build() = HttpConnectionClient1(dnsServerAddress, callTimeout, connectTimeout, readTimeout, writeTimeout)\n\n    }\n\n}\n\n/**\n * The second variant\n */\nclass HttpConnectionClient2 private constructor() {\n    private var dnsServerAddress: String = \"8.8.8.8\"\n    private var callTimeout: Int = 0\n    private var connectTimeout: Int = 10_000\n    private var readTimeout: Int = 10_000\n    private var writeTimeout: Int = 0\n\n    override fun toString() = \"\"\"\n        dns -> $dnsServerAddress\n        call timeout -> $callTimeout\n        connect timeout -> $connectTimeout\n        read timeout -> $readTimeout\n        write timeout -> $writeTimeout\n    \"\"\".trimIndent()\n\n    companion object {\n        fun newBuilder() = HttpConnectionClient2().Builder()\n    }\n\n    inner class Builder {\n\n        fun dnsServerAddress(address: String) = apply {\n            dnsServerAddress = address\n        }\n\n        fun callTimeout(timeout: Int) = apply {\n            // we can add some checks such as:\n            // if (timeout < 0) throw IllegalArgumentException(\"Uncorrected timeout: $timeout\")\n            callTimeout = timeout\n        }\n\n        fun connectTimeout(timeout: Int) = apply {\n            connectTimeout = timeout\n        }\n\n        fun readTimeout(timeout: Int) = apply {\n            readTimeout = timeout\n        }\n\n        fun writeTimeout(timeout: Int) = apply {\n            writeTimeout = timeout\n        }\n\n        fun build() = this@HttpConnectionClient2\n    }\n\n}\n\n/**\n * Kotlin variant with default arguments\n */\nclass HttpConnectionClient3(\n    private val dnsServerAddress: String = \"8.8.8.8\",\n    private val callTimeout: Int = 0,\n    private val connectTimeout: Int = 10_000,\n    private val readTimeout: Int = 10_000,\n    private val writeTimeout: Int = 0\n) {\n    override fun toString() = \"\"\"\n        dns -> $dnsServerAddress\n        call timeout -> $callTimeout\n        connect timeout -> $connectTimeout\n        read timeout -> $readTimeout\n        write timeout -> $writeTimeout\n    \"\"\".trimIndent()\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Command.kt",
    "content": "package design_patterns\n\n/**\n *\n * Command is a behavioral pattern that encapsulates a request to perform an action as a separate object\n *\n */\n\n// StereoSystem is the receiver that performs the action\nclass StereoSystem {\n\n    private var hasTurnedOn = false\n    private var volume = 50\n\n    val currentState: String\n        get() = \"\"\"\n            running status: $hasTurnedOn\n            volume value: $volume\n        \"\"\".trimIndent()\n\n    fun turnOn() {\n        hasTurnedOn = true\n    }\n\n    fun turnOff() {\n        hasTurnedOn = false\n    }\n\n    fun increaseVolume() {\n        if (!hasTurnedOn) return\n        if (volume < 100) {\n            volume += 10\n        }\n    }\n\n    fun decreaseVolume() {\n        if (!hasTurnedOn) return\n        if (volume > 0) {\n            volume -= 10\n        }\n    }\n\n}\n\ninterface StereoSystemCommand {\n    fun execute()\n    fun undo() : Boolean\n}\n\n// this command encapsulates a request to increase the volume in StereoSystem\nclass IncreaseVolumeCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand {\n\n    override fun execute() {\n        stereoSystem.increaseVolume()\n    }\n\n    override fun undo(): Boolean {\n        stereoSystem.decreaseVolume()\n        return true\n    }\n\n}\n\n// this command encapsulates a request to decrease the volume in StereoSystem\nclass DecreaseVolumeCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand {\n\n    override fun execute() {\n        stereoSystem.decreaseVolume()\n    }\n\n    override fun undo(): Boolean {\n        stereoSystem.increaseVolume()\n        return true\n    }\n\n}\n\n// this command encapsulates a request to turn on StereoSystem\nclass TurnOnCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand {\n\n    override fun execute() {\n        stereoSystem.turnOn()\n    }\n\n    override fun undo(): Boolean {\n        stereoSystem.turnOff()\n        return true\n    }\n\n}\n\n// this command encapsulates a request to turn off StereoSystem\nclass TurnOffCommand(private val stereoSystem: StereoSystem) : StereoSystemCommand {\n\n    override fun execute() {\n        stereoSystem.turnOff()\n    }\n\n    override fun undo() = false\n\n}\n\n// we can also create the command that combines others\nclass MacroCommand(private vararg val commands: StereoSystemCommand) : StereoSystemCommand {\n\n    override fun execute() {\n        for (command in commands) {\n            command.execute()\n        }\n    }\n\n    override fun undo(): Boolean {\n        for (command in commands.reversed()) {\n            val isNotCancelableCommand = !command.undo()\n            if (isNotCancelableCommand) return false\n        }\n        return true\n    }\n\n}\n\n// StereoSystemRemoteControl executes commands without breaking their encapsulation\nclass StereoSystemRemoteControl(private val buttons: Map<String, StereoSystemCommand> = mapOf()) {\n\n    // we only know about StereoSystemCommand interface\n    private val commandHistory = mutableListOf<StereoSystemCommand>()\n\n    fun pressButton(name: String) {\n        val command = buttons[name]\n        if (command != null) {\n            command.execute()\n            commandHistory.add(command)\n        }\n    }\n\n    fun pressUndoButton() {\n        val lastCommand = commandHistory.removeLastOrNull()\n        if (lastCommand != null) {\n            val isNotCancelableCommand = !lastCommand.undo()\n            if (isNotCancelableCommand) commandHistory.clear()\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Composite.kt",
    "content": "package design_patterns\n\n/**\n *\n * Composite is a structural design pattern that organizes objects into a tree structure\n *\n * and allows clients to access individual objects and groups of objects in the same way.\n *\n */\n\n// all components have a common interface\nabstract class MenuComponent(val title: String) {\n    // menus and items can give information about themselves\n    abstract fun fetchMenuInformation() : String\n}\n\nclass Menu(title: String) : MenuComponent(title) {\n\n    // menu can contain other menus and items\n    private val childMenuComponents = mutableListOf<MenuComponent>()\n\n    // addComponent/removeComponent operations are only available for the menu\n    fun addComponent(component: MenuComponent) {\n        childMenuComponents.add(component)\n    }\n\n    fun removeComponent(component: MenuComponent) {\n        childMenuComponents.remove(component)\n    }\n\n    override fun fetchMenuInformation(): String {\n        val builder = StringBuilder()\n        builder.append(\"Menu: $title\")\n        childMenuComponents.forEach { component ->\n            builder.append(\"\\n\")\n            builder.append(component.fetchMenuInformation())\n        }\n        return builder.toString()\n    }\n\n}\n\n// the simple component that contains no others\nclass MenuItem(title: String, private val price: Int) : MenuComponent(title) {\n\n    override fun fetchMenuInformation(): String =\n        \"\"\"\n            title: $title\n            price: $price\n            -------------\n        \"\"\".trimIndent()\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Decorator.kt",
    "content": "package design_patterns\n\n/**\n *\n * Decorator is a structural design pattern that adds new functionality to an object:\n *\n * classes implement a common interface and to extend the functionality of the previous object,\n *\n * the old object is passed through the constructor\n *\n */\n\ninterface MyPrinter {\n    fun printedText() : String\n}\n\n// just returns \"Hello\"\nclass HelloPrinter : MyPrinter {\n    override fun printedText() : String {\n        return \"Hello\"\n    }\n}\n\n// adds a comma to the previous value of the printedText() function\nclass CommaPrinter(private val printer: MyPrinter) : MyPrinter {\n    override fun printedText() : String {\n        return \"${printer.printedText()},\"\n    }\n}\n\n// adds a space to the previous value of the printedText() function\nclass SpacePrinter(private val printer: MyPrinter) : MyPrinter {\n    override fun printedText() : String {\n        return \"${printer.printedText()} \"\n    }\n}\n\n// adds the word \"World\" to the previous value of the printedText() function\nclass WorldPrinter(private val printer: MyPrinter) : MyPrinter {\n    override fun printedText() : String {\n        return \"${printer.printedText()}World\"\n    }\n}\n\n// adds an exclamation mark to the previous value of the printedText() function\nclass ExclamationPrinter(private val printer: MyPrinter) : MyPrinter {\n    override fun printedText() : String {\n        return \"${printer.printedText()}!\"\n    }\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Facade.kt",
    "content": "package design_patterns\n\n/**\n *\n * Facade is a structural design pattern that simplifies the interface to a group of interfaces\n *\n * with a more complex implementation\n *\n */\n\ndata class GoodsEntity(\n    private val id: Long,\n    private val name: String,\n    private val description: String,\n    private val price: Double\n)\n\nclass GoodsDatabase {\n    private val cachedGoods = mutableListOf<GoodsEntity>()\n\n    fun save(goods: List<GoodsEntity>) {\n        cachedGoods.addAll(goods)\n    }\n\n    fun read() = cachedGoods\n}\n\nclass GoodsNetworkService {\n\n    fun fetch() = listOf(\n        GoodsEntity(\n            id = 1,\n            name = \"Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition\",\n            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.\",\n            price = 41.94\n        )\n    )\n\n}\n\ndata class CategoryEntity(\n    private val id: Long,\n    private val name: String\n)\n\nclass CategoryDatabase {\n    private val cachedCategories = mutableListOf<CategoryEntity>()\n\n    fun save(goods: List<CategoryEntity>) {\n        cachedCategories.addAll(goods)\n    }\n\n    fun read() = cachedCategories\n}\n\nclass CategoryNetworkService {\n\n    fun fetch() = listOf(\n        CategoryEntity(\n            id = 1,\n            name = \"Books\"\n        )\n    )\n\n}\n\ndata class GoodsResult(\n    val goods: List<GoodsEntity>,\n    val categories: List<CategoryEntity>\n)\n\n// we have a group of interfaces (databases and network services)\nclass GoodsRepository(\n    private val goodsDatabase: GoodsDatabase,\n    private val goodsNetworkService: GoodsNetworkService,\n    private val categoryDatabase: CategoryDatabase,\n    private val categoryNetworkService: CategoryNetworkService\n) {\n\n    // we need a simpler interface\n    fun goodsAndCategories() : GoodsResult {\n        val goods = goodsDatabase.read().toMutableList()\n        if (goods.isEmpty()) {\n            val networkGoods = goodsNetworkService.fetch()\n            goodsDatabase.save(networkGoods)\n            goods.addAll(networkGoods)\n        }\n\n        val categories = categoryDatabase.read().toMutableList()\n        if (categories.isEmpty()) {\n            val networkCategories = categoryNetworkService.fetch()\n            categoryDatabase.save(networkCategories)\n            categories.addAll(networkCategories)\n        }\n\n        return GoodsResult(\n            goods = goods,\n            categories = categories\n        )\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Factory Method.kt",
    "content": "package design_patterns\n\n/**\n *\n * A factory method is a generic design pattern that defines\n *\n * a common interface for creating objects in a superclass,\n *\n * allowing subclasses to change the type of objects they create.\n *\n */\n\nabstract class House(private val address: String, private val price: Int) {\n\n    override fun toString() = \"\"\"\n        address = $address\n        price = $price\n    \"\"\".trimIndent()\n\n}\n\n// the factory method makes sense if we have a hierarchy of objects\nclass WoodenCheapHouse(address: String) : House(address, 50_000)\nclass WoodenAverageHouse(address: String) : House(address, 250_000)\nclass WoodenExpensiveHouse(address: String) : House(address, 1_000_000)\n\nclass StoneCheapHouse(address: String) : House(address, 45_000)\nclass StoneAverageHouse(address: String) : House(address, 230_000)\nclass StoneExpensiveHouse(address: String) : House(address, 900_000)\n\n// we have a common logic for every HouseCompany\nabstract class HouseCompany {\n\n    private val alreadyBuiltHouses = mutableListOf<House>()\n\n    val examplesAlreadyBuiltHouses: String\n        get() = alreadyBuiltHouses.joinToString(\"\\n\\n\")\n\n    fun orderHouse(address: String, cost: HouseCompanyCost): House {\n        val house = buildHouse(address, cost)\n        alreadyBuiltHouses.add(house)\n        return house\n    }\n\n    // the subclasses define a specific implementation\n    protected abstract fun buildHouse(address: String, cost: HouseCompanyCost): House\n\n    enum class HouseCompanyCost { CHEAP, AVERAGE, EXPENSIVE }\n\n}\n\n// WoodenHouseCompany only builds wooden houses\nclass WoodenHouseCompany : HouseCompany() {\n\n    override fun buildHouse(address: String, cost: HouseCompanyCost) = when(cost) {\n        HouseCompanyCost.CHEAP -> WoodenCheapHouse(address)\n        HouseCompanyCost.AVERAGE -> WoodenAverageHouse(address)\n        HouseCompanyCost.EXPENSIVE -> WoodenExpensiveHouse(address)\n    }\n\n}\n\n// StoneHouseCompany only builds stone houses\nclass StoneHouseCompany : HouseCompany() {\n\n    override fun buildHouse(address: String, cost: HouseCompanyCost) = when(cost) {\n        HouseCompanyCost.CHEAP -> StoneCheapHouse(address)\n        HouseCompanyCost.AVERAGE -> StoneAverageHouse(address)\n        HouseCompanyCost.EXPENSIVE -> StoneExpensiveHouse(address)\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Flyweight.kt",
    "content": "package design_patterns\n\n/**\n *\n * Flyweight is a structural design pattern that reduces memory costs by reusing a family of objects\n *\n * and storing mutable state outside the object.\n *\n */\n\nclass BeautifulGarden {\n\n    // we reuse objects with immutable state, in this example trees\n    private val existingTrees = mutableListOf<Tree>()\n\n    // mutable state (coordinates) are stored outside the object\n    private val placedTrees = mutableListOf<Triple<Int, Int, Tree>>()\n\n    fun placeTree(name: String, description: String, height: Int, x: Int, y: Int) {\n        // check if such a tree already exists reuse it otherwise create a new one\n        val tree = existingTrees.find { tree -> tree.name == name && tree.description == description && tree.height == height }\n            ?: Tree(name, description, height).apply(existingTrees::add)\n\n        placedTrees.add(Triple(x, y, tree))\n    }\n\n    fun placedTreesAsString(): String {\n        val builder = StringBuilder()\n        builder.append(\"Beautiful Garden:\\n\")\n\n        placedTrees.forEach { (x, y, tree) ->\n            builder.append(\"name: ${tree.name}, height: ${tree.height}, x: $x, y: $y\\n\")\n        }\n\n        builder.append(\"-|-|-|-|-|-|-|-|-|-|-\")\n\n        return builder.toString()\n    }\n\n    data class Tree(\n        val name: String,\n        val description: String,\n        val height: Int\n    )\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Interpreter.kt",
    "content": "package design_patterns\n\n/**\n *\n * Interpreter is a behavioral design pattern that defines a simple language grammar for a problem domain,\n *\n * represents grammatical rules as language sentences and interprets them to solve commonly encountered problems\n *\n */\n\n// contains general information for the interpreter\nclass InterpreterContext {\n    private val variables = mutableMapOf<String, Int>()\n\n    fun putVariable(key: String, value: Int) {\n        variables[key] = value\n    }\n\n    fun fetchVariable(key: String): Int {\n        return variables[key] ?: 0\n    }\n}\n\n// represents a specific interpreter grammar expression\ninterface InterpreterExpression {\n    fun interpret(context: InterpreterContext)\n}\n\nclass SetIntVariableExpression(\n    private val key: String,\n    private val intValue: Int\n) : InterpreterExpression {\n    override fun interpret(context: InterpreterContext) {\n        context.putVariable(key = key, value = intValue)\n    }\n}\n\nclass PerformExpression(private vararg val expressions: InterpreterExpression) : InterpreterExpression {\n    override fun interpret(context: InterpreterContext) {\n        expressions.forEach { it.interpret(context) }\n    }\n}\n\nclass AddVariablesExpression(\n    private val key0: String,\n    private val key1: String,\n    private val result: String\n) : InterpreterExpression {\n    override fun interpret(context: InterpreterContext) {\n        context.putVariable(\n            key = result,\n            value = context.fetchVariable(key0) + context.fetchVariable(key1)\n        )\n    }\n}\n\nclass MultipleVariablesExpression(\n    private val key0: String,\n    private val key1: String,\n    private val result: String\n) : InterpreterExpression {\n    override fun interpret(context: InterpreterContext) {\n        context.putVariable(\n            key = result,\n            value = context.fetchVariable(key0) * context.fetchVariable(key1)\n        )\n    }\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Iterator.kt",
    "content": "package design_patterns\n\n/**\n *\n * Iterator is a behavioral design pattern that provides a mechanism for sequentially enumerating the elements\n *\n * of a collection without revealing its internal representation.\n *\n */\n\ninterface BoxIterator<T> {\n    fun hasNext(): Boolean\n    fun next(): T\n}\n\ninterface BoxIterable<T> {\n    fun iterator(): BoxIterator<T>\n}\n\nclass GiftBox(private val presents: Array<String>) : BoxIterable<String> {\n\n    override fun iterator() = object : BoxIterator<String> {\n        private var current = -1\n\n        override fun next(): String {\n            return presents[current]\n        }\n\n        override fun hasNext(): Boolean {\n            if (current < presents.size - 1) {\n                current++\n                return true\n            }\n            return false\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Mediator.kt",
    "content": "package design_patterns\n\n/**\n *\n * Mediator is a behavioral design pattern that reduces the coupling of many classes among themselves\n *\n * by moving these couplings into one mediator class\n *\n */\n\n// SoftwareDevelopmentManager is a mediator for the customer, designer, programmer and tester\nclass SoftwareDevelopmentManager {\n\n    private lateinit var customer: SoftwareDevelopmentMember\n    private lateinit var designer: SoftwareDevelopmentMember\n    private lateinit var programmer: SoftwareDevelopmentMember\n    private lateinit var tester: SoftwareDevelopmentMember\n\n    fun changeCustomer(member: SoftwareDevelopmentMember) { customer = member }\n    fun changeDesigner(member: SoftwareDevelopmentMember) { designer = member }\n    fun changeProgrammer(member: SoftwareDevelopmentMember) { programmer = member }\n    fun changeTester(member: SoftwareDevelopmentMember) { tester = member }\n\n    private val stages = mutableListOf<String>()\n    val stagesAsString: String\n        get() = stages.joinToString(\"\\n\")\n\n    // members do not interact directly with each other because the mediator does it\n    // which reduces the coupling between them\n    fun nextStage(work: String, member: SoftwareDevelopmentMember) {\n        val finishedStage = when (member) {\n\n            is CustomerSoftwareDevelopmentMember -> designer.receiveWork(work)\n\n            is DesignerSoftwareDevelopmentMember -> programmer.receiveWork(work)\n\n            is ProgrammerSoftwareDevelopmentMember -> tester.receiveWork(work)\n\n            is TesterSoftwareDevelopmentMember -> customer.receiveWork(work)\n\n            else -> \"\"\n        }\n\n        stages.add(finishedStage)\n    }\n\n}\n\n// SoftwareDevelopmentMember works with other members through the mediator\nabstract class SoftwareDevelopmentMember(protected val mediator: SoftwareDevelopmentManager) {\n\n    abstract fun receiveWork(work: String): String\n\n    abstract fun finishWork()\n\n}\n\nclass CustomerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) {\n    override fun receiveWork(work: String) = \"Customer accepted the work: $work\"\n\n    override fun finishWork() {\n        mediator.nextStage(\"design development\", this)\n    }\n}\n\nclass DesignerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) {\n    override fun receiveWork(work: String) = \"Designer accepted the work: $work\"\n\n    override fun finishWork() {\n        mediator.nextStage(\"writing code\", this)\n    }\n}\n\nclass ProgrammerSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) {\n    override fun receiveWork(work: String) = \"Programmer accepted the work: $work\"\n\n    override fun finishWork() {\n        mediator.nextStage(\"application testing\", this)\n    }\n}\n\nclass TesterSoftwareDevelopmentMember(mediator: SoftwareDevelopmentManager) : SoftwareDevelopmentMember(mediator) {\n    override fun receiveWork(work: String) = \"Tester accepted the work: $work\"\n\n    override fun finishWork() {\n        mediator.nextStage(\"business valuation\", this)\n    }\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Memento.kt",
    "content": "package design_patterns\n\n/**\n *\n * Memento is a behavioral design pattern that allows without violating encapsulation to capture\n *\n * and save the internal state of an object so that it can be restored to this state later\n *\n */\n\n\nclass Bundle(val str: String)\n\n// Android system saves the application state in special bundles\n// I gave this as an example, Android system’s saving mechanism is much more complicated\nclass AndroidSystem {\n\n    private var savedBundle: Bundle = Bundle(\"\")\n\n    fun saveBundle(bundle: Bundle) {\n        savedBundle = bundle\n    }\n\n    fun restoreBundle() = savedBundle\n}\n\n// TextView is an Android component that draws text on the screen\nclass TextView {\n\n    private var currentText: String = \"\"\n\n    fun setText(text: String) {\n        currentText = text\n    }\n\n    fun text() = currentText\n\n    fun draw() {\n        println(currentText)\n    }\n\n    // saves the current state of TextView before re-creating it\n    fun onSaveInstanceState(): Bundle {\n        return Bundle(currentText)\n    }\n\n    // restores the current state after TextView is recreated\n    fun onRestoreInstanceState(bundle: Bundle) {\n        currentText = bundle.str\n    }\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Observer.kt",
    "content": "package design_patterns\n\n/**\n *\n * Observer is is a behavioral design pattern that defines a one-to-many relationship between objects\n *\n * such that when the state of one object changes all dependent objects are automatically notified and updated\n *\n */\n\nfun interface PonyObserver {\n    fun update(item: List<String>)\n}\n\ninterface PonyObservable {\n    fun addObserver(observer: PonyObserver)\n    fun removeObserver(observer: PonyObserver)\n    fun notifyObservers()\n}\n\n// PonyList contains some data and when it changes we will notify observers\nclass PonyList : PonyObservable {\n\n    private val ponies = mutableListOf<String>()\n\n    private val observers = mutableSetOf<PonyObserver>()\n\n    fun add(pony: String) {\n        ponies.add(pony)\n        // notify observers that the data has changed\n        notifyObservers()\n    }\n\n    override fun addObserver(observer: PonyObserver) {\n        observers.add(observer)\n    }\n\n    override fun removeObserver(observer: PonyObserver) {\n        observers.remove(observer)\n    }\n\n    override fun notifyObservers() {\n        observers.forEach { observer -> observer.update(ponies) }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Prototype.kt",
    "content": "package design_patterns\n\n/**\n *\n * Prototype is a generative design pattern that allows you to copy objects\n *\n * without going into the details of their implementation.\n *\n */\n\nabstract class Sweets(\n    protected val title: String,\n    protected val description: String,\n    protected val price: Int\n) {\n\n    // we only have a copy interface and don't know about its implementation\n    abstract fun copy(): Sweets\n\n}\n\nclass OreoCookies(\n    title: String,\n    private val flavor: String,\n    price: Int\n) : Sweets(\n    title = title,\n    price = price,\n    description = \"Take a delicious break with OREO Chocolate Sandwich Cookies, America's favorite sandwich cookie for over 100 years...\"\n) {\n\n    // each implementation creates its own copy\n    override fun copy(): Sweets {\n        return OreoCookies(title, flavor, price)\n    }\n\n    override fun equals(other: Any?): Boolean {\n        if (other == null) return false\n        if (this === other) return true\n        if (other !is OreoCookies) return false\n\n        return title == other.title && description == other.description &&\n                flavor == other.flavor && price == other.price\n    }\n\n}\n\nclass `M&MsChocolate`(\n    private val taste: String,\n    price: Int,\n) : Sweets(\n    title = \"M&M's chocolate\",\n    price = price,\n    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...\"\n) {\n\n    override fun copy(): Sweets {\n        return `M&MsChocolate`(taste, price)\n    }\n\n    override fun equals(other: Any?): Boolean {\n        if (other == null) return false\n        if (this === other) return true\n        if (other !is `M&MsChocolate`) return false\n\n        return title == other.title && description == other.description &&\n                taste == other.taste && price == other.price\n    }\n\n}\n\n"
  },
  {
    "path": "src/main/kotlin/design_patterns/Proxy.kt",
    "content": "package design_patterns\n\n/**\n *\n * Proxy is a structural design pattern that provides an object\n *\n * that controls access to another object by intercepting all calls.\n *\n * There are several types of this pattern:\n *\n * 1) Logging proxy - saves all calls to a real object with their parameters to the log (shown in this example)\n * 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)\n * 3) Virtual proxy - ensures that a real object is created only when it is actually needed (shown in this example)\n * 4) Protection proxy - checks whether the caller has the necessary rights to execute the request\n * 5) Caching proxy - provides temporary storage of calculation results\n * 6) Synchronizing proxy - performs synchronized access control to an object in a multi-threaded environment (Collections.synchronized** methods)\n * 7) Smart reference proxy - performs additional actions when a link is created to an object\n *\n */\n\ninterface AudioPlayer {\n    val currentState: String\n\n    fun play(audio: String)\n    fun pause()\n    fun resume()\n    fun stop()\n}\n\n// we have the simple player simulation\nclass AudioPlayerImpl : AudioPlayer {\n\n    private var currentAudio: String = \"\"\n    private var currentStatus = MediaPlayerStatus.NOT_INITIALIZED\n\n    override val currentState: String\n        get() = \"\"\"\n            current audio: $currentAudio\n            current status: $currentStatus\n        \"\"\".trimIndent()\n\n    override fun play(audio: String) {\n        if (audio.isNotBlank()) {\n            currentAudio = audio\n            currentStatus = MediaPlayerStatus.RUNNING\n        }\n    }\n    override fun pause() {\n        if (currentStatus == MediaPlayerStatus.RUNNING) {\n            currentStatus = MediaPlayerStatus.PAUSED\n        }\n    }\n\n    override fun resume() {\n        if (currentStatus == MediaPlayerStatus.PAUSED) {\n            currentStatus = MediaPlayerStatus.RUNNING\n        }\n    }\n\n    override fun stop() {\n        if (currentStatus != MediaPlayerStatus.NOT_INITIALIZED) {\n            currentAudio = \"\"\n            currentStatus = MediaPlayerStatus.NOT_INITIALIZED\n        }\n    }\n\n    enum class MediaPlayerStatus {\n        NOT_INITIALIZED, PAUSED, RUNNING\n    }\n\n}\n\n// MediaPlayerProxy defers the creation of a real object (virtual proxy) and logs all its calls (logging proxy)\nclass AudioPlayerProxy : AudioPlayer {\n\n    // deferred creation of the real player\n    private val player: AudioPlayer by lazy { AudioPlayerImpl() }\n\n    override val currentState: String\n        get() = player.currentState\n\n    override fun play(audio: String) {\n        player.play(audio)\n        // logs real player calls\n        println(\"play audio: $audio\")\n    }\n\n    override fun pause() {\n        player.pause()\n        println(\"pause\")\n    }\n\n    override fun resume() {\n        player.resume()\n        println(\"resume\")\n    }\n\n    override fun stop() {\n        player.stop()\n        println(\"stop\")\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Singleton.kt",
    "content": "package design_patterns\n\n/**\n *\n * Singleton is a generative design pattern that guarantees the existence of one instance of a class\n *\n * and provides a global access point to it\n *\n */\n\nobject SQLiteDatabase {\n\n    // SQLiteDatabase instance state\n    private var connectionId = -1\n\n    // These methods provide a global access point to SQLiteDatabase instance state\n    fun openConnection() {\n        if (connectionId < 0) {\n            // open connection...\n            connectionId = 1\n        }\n    }\n\n    fun execSQL(sql: String): List<String> {\n        if (connectionId < 0) return emptyList()\n        return when (sql) {\n            \"select * from names\" -> listOf(\"Rick\", \"Morty\", \"Jerry\", \"Beth\")\n            else -> emptyList()\n        }\n    }\n\n    fun closeConnection() {\n        if (connectionId > 0) {\n            // close connection...\n            connectionId = -1\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/State.kt",
    "content": "package design_patterns\n\n/**\n *\n * State is a behavioral design pattern that controls changes in the behavior of an object\n *\n * when its internal state changes\n *\n */\n\n// the common interface for all states\ninterface CocaColaState {\n    fun insertDollar() : Boolean\n    fun takeBackDollar() : Boolean\n    fun pressButton(numberOfDrinks: Int) : Boolean\n}\n\n// we don't have drinks in the machine\nclass EmptyCocaColaState : CocaColaState {\n    override fun insertDollar() = false\n    override fun takeBackDollar() = false\n    override fun pressButton(numberOfDrinks: Int) = false\n    override fun toString(): String = \"EmptyCocaColaState\"\n}\n\n// we have drinks, but we don't have a dollar in the machine\nclass NoDollarCocaColaState(private val machine: CocaColaMachine) : CocaColaState {\n    override fun insertDollar(): Boolean {\n        machine.setState(HaveDollarCocaColaState(machine))\n        return true\n    }\n\n    override fun takeBackDollar() = false\n    override fun pressButton(numberOfDrinks: Int) = false\n    override fun toString(): String = \"NoDollarCocaColaState\"\n}\n\n// we have a dollar in the machine\nclass HaveDollarCocaColaState(private val machine: CocaColaMachine) : CocaColaState {\n    override fun insertDollar() = false\n    override fun takeBackDollar(): Boolean {\n        machine.setState(NoDollarCocaColaState(machine))\n        return true\n    }\n    override fun pressButton(numberOfDrinks: Int): Boolean {\n        if (numberOfDrinks == 1) {\n            machine.setState(EmptyCocaColaState())\n        } else {\n            machine.setState(NoDollarCocaColaState(machine))\n        }\n        return true\n    }\n    override fun toString(): String = \"HaveDollarCocaColaState\"\n}\n\n// CocaColaMachine switches between states\nclass CocaColaMachine {\n\n    private var numberOfDrinks = 3\n    private var state: CocaColaState = NoDollarCocaColaState(this)\n\n    val currentState: String\n        get() = state.toString()\n\n    fun insertDollar() = state.insertDollar()\n\n    fun takeBackDollar() = state.takeBackDollar()\n\n    fun pressButton(): Boolean {\n        val isSuccess = state.pressButton(numberOfDrinks)\n        if (isSuccess) {\n            numberOfDrinks -= 1\n        }\n        return isSuccess\n    }\n\n    fun loadDrinks(count: Int) {\n        numberOfDrinks += count\n        if (numberOfDrinks > 0) {\n            setState(NoDollarCocaColaState(this))\n        } else {\n            setState(EmptyCocaColaState())\n        }\n    }\n\n    fun setState(newState: CocaColaState) {\n        state = newState\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Strategy.kt",
    "content": "package design_patterns\n\n/**\n *\n * Strategy is a behavioral design pattern used to define a family of algorithms,\n *\n * encapsulate each one and make them interchangeable\n *\n */\n\n// encapsulates the filtering algorithm\ninterface FoodFilterStrategy {\n    fun filter(items: List<FoodEntity>): List<FoodEntity>\n}\n\nclass OnlyChipsFilterStrategy : FoodFilterStrategy {\n    override fun filter(items: List<FoodEntity>): List<FoodEntity> {\n        return items.filter { it.category == \"chips\" }\n    }\n}\n\nclass OnlyChocolateFilterStrategy : FoodFilterStrategy {\n    override fun filter(items: List<FoodEntity>): List<FoodEntity> {\n        return items.filter { it.category == \"chocolate\" }\n    }\n}\n\nclass PriceFilterStrategy(private val price: Int) : FoodFilterStrategy {\n    override fun filter(items: List<FoodEntity>): List<FoodEntity> {\n        return items.filter { it.price >= price }\n    }\n}\n\nclass SearchWordFilterStrategy(private val search: String) : FoodFilterStrategy {\n    override fun filter(items: List<FoodEntity>): List<FoodEntity> {\n        return items.filter { it.title.contains(search, ignoreCase = true) }\n    }\n}\n\ndata class FoodEntity(\n    val title: String,\n    val price: Int,\n    val category: String\n)\n\n// FoodStore returns a list of food filtered by strategy\nclass FoodStore(private var filterStrategy: FoodFilterStrategy) {\n\n    // we can change strategy\n    fun changeStrategy(strategy: FoodFilterStrategy) {\n        filterStrategy = strategy\n    }\n\n    fun foodItems(): List<FoodEntity> {\n        val foodItems = fetchFoodItems()\n        return filterStrategy.filter(foodItems)\n    }\n\n    private fun fetchFoodItems() =\n        listOf(\n            FoodEntity(\n                \"Lays Potato Chips Fried Crab Flavor\",\n                2,\n                \"chips\"\n            ),\n            FoodEntity(\n                \"Lay's Potato Chips, Classic\",\n                3,\n                \"chips\"\n            ),\n            FoodEntity(\n                \"Dove Chocolate\",\n                3,\n                \"chocolate\"\n            ),\n            FoodEntity(\n                \"Ritter Sport Chocolate\",\n                4,\n                \"chocolate\"\n            )\n        )\n\n}\n\n"
  },
  {
    "path": "src/main/kotlin/design_patterns/Template Method.kt",
    "content": "package design_patterns\n\n/**\n *\n * Template method a behavioral design pattern that defines the basis of an algorithm\n *\n * and allows subclasses to redefine some steps of the algorithm without changing its overall structure\n *\n */\n\ndata class Cake(\n    val layers: List<String>,\n    val cream: String,\n    val sprinkles: String\n)\n\nabstract class CakeBaker {\n\n    protected abstract fun layer(): String\n\n    protected abstract fun cream(): String\n\n    protected abstract fun sprinkles(): String\n\n    // we have the basis of an algorithm\n    fun makeCake(numberOfLayers: Int): Cake {\n        return Cake(\n            layers = List(numberOfLayers) { layer() },\n            cream = cream(),\n            sprinkles = sprinkles()\n        )\n    }\n\n}\n\nclass ChocolateCakeBaker : CakeBaker() {\n\n    // subclasses redefines some steps of the algorithm\n    override fun cream(): String = \"chocolate cream\"\n\n    override fun layer(): String = \"chocolate cake layer\"\n\n    override fun sprinkles(): String = \"chocolate chips\"\n\n}\n\nclass WaffleCakeBaker : CakeBaker() {\n\n    override fun cream(): String = \"custard cream\"\n\n    override fun layer(): String = \"waffle cake layer\"\n\n    override fun sprinkles(): String = \"coconut flakes\"\n\n}"
  },
  {
    "path": "src/main/kotlin/design_patterns/Visitor.kt",
    "content": "package design_patterns\n\n/**\n *\n * Visitor is a behavioral design pattern that allows you to add a new operation\n *\n * to an entire class hierarchy without changing the code of these classes.\n *\n */\n\ninterface PonyVisitor {\n    fun visitPonies(vararg ponies: LittlePony) : String\n    fun visitEarthPony(pony: EarthPony) : String\n    fun visitUnicorn(pony: Unicorn) : String\n    fun visitPegasus(pony: Pegasus) : String\n}\n\nclass JsonVisitor : PonyVisitor {\n\n    override fun visitPonies(vararg ponies: LittlePony) : String {\n        val poniesString = ponies.joinToString(\",\\n\") { pony -> pony.accept(this) }\n        return \"[$poniesString]\"\n    }\n\n    override fun visitEarthPony(pony: EarthPony): String {\n        return \"\"\"\n            {\n                \"what\" : \"earth pony\",\n                \"name\" : \"${pony.name()}\",\n                \"cutie_mark\" : \"${pony.cutie()}\n            }\n        \"\"\".trimIndent()\n    }\n\n    override fun visitUnicorn(pony: Unicorn): String {\n        return \"\"\"\n            {\n                \"what\" : \"unicorn\",\n                \"name\" : \"${pony.name()}\",\n                \"cutie_mark\" : \"${pony.cutie()}\n            }\n        \"\"\".trimIndent()\n    }\n\n    override fun visitPegasus(pony: Pegasus): String {\n        return \"\"\"\n            {\n                \"what\" : \"pegasus\",\n                \"name\" : \"${pony.name()}\",\n                \"cutie_mark\" : \"${pony.cutie()}\n            }\n        \"\"\".trimIndent()\n    }\n\n}\n\nclass XmlVisitor : PonyVisitor {\n\n    override fun visitPonies(vararg ponies: LittlePony) : String {\n        val poniesString = ponies.joinToString(\"\\n\") { pony -> pony.accept(this) }\n        return \"<ponies>\\n$poniesString\\n</ponies>\"\n    }\n\n    override fun visitEarthPony(pony: EarthPony): String {\n        return \"\"\"\n            <pony>\n                <what>earth pony</what>\n                <name>${pony.name()}</name>\n                <cutie_mark>${pony.cutie()}</cutie_mark>\n            </pony>\n        \"\"\".trimIndent()\n    }\n\n    override fun visitUnicorn(pony: Unicorn): String {\n        return \"\"\"\n            <pony>\n                <what>unicorn</what>\n                <name>${pony.name()}</name>\n                <cutie_mark>${pony.cutie()}</cutie_mark>\n            </pony>\n        \"\"\".trimIndent()\n    }\n\n    override fun visitPegasus(pony: Pegasus): String {\n        return \"\"\"\n            <pony>\n                <what>pegasus</what>\n                <name>${pony.name()}</name>\n                <cutie_mark>${pony.cutie()}</cutie_mark>\n            </pony>\n        \"\"\".trimIndent()\n    }\n\n}\n\nabstract class LittlePony(private val name: String, private val cutieMark: String) {\n\n    fun name() = name\n    fun cutie() = cutieMark\n\n    abstract fun accept(visitor: PonyVisitor) : String\n}\n\nclass EarthPony(name: String, cutieMark: String) : LittlePony(name, cutieMark) {\n    override fun accept(visitor: PonyVisitor) = visitor.visitEarthPony(this)\n}\n\nclass Unicorn(name: String, cutieMark: String) : LittlePony(name, cutieMark) {\n    override fun accept(visitor: PonyVisitor) = visitor.visitUnicorn(this)\n\n}\n\nclass Pegasus(name: String, cutieMark: String) : LittlePony(name, cutieMark) {\n    override fun accept(visitor: PonyVisitor) = visitor.visitPegasus(this)\n}\n\n"
  },
  {
    "path": "src/main/kotlin/design_patterns/Сhain Of Responsibilities.kt",
    "content": "package design_patterns\n\n/**\n *\n * Chain of responsibility is a behavioral design pattern that allows requests to be sent sequentially\n *\n * through a chain of handlers\n *\n */\n\nenum class BlockFactor { ONE, TWO, THREE }\n\n// I decided to give an analogy from the Minecraft game.\n// In this game there are blocks that can be broken with a stone pickaxe, iron and diamond.\n// For example: diamond may mine by iron and diamond pickaxes unlike cobblestone, which is mined by any pickaxe\nabstract class Block(private val factor: BlockFactor) {\n    fun mayMine(factor: BlockFactor) = this.factor.ordinal <= factor.ordinal\n}\n\n// the blocks are from the game\nclass StoneBlock: Block(BlockFactor.ONE)\nclass DiamondBlock: Block(BlockFactor.TWO)\nclass ObsidianBlock: Block(BlockFactor.THREE)\n\nabstract class Pickaxe(private val factor: BlockFactor) {\n\n    private var nextPickaxe: Pickaxe? = null\n\n    fun changeNextPickaxe(pickaxe: Pickaxe) {\n        nextPickaxe = pickaxe\n    }\n\n    // we mine the block, if it doesn't work, we take another pickaxe, if there is one, returns true if a pickaxe can mine\n    fun mine(block: Block): Boolean {\n        if (block.mayMine(factor)) return true\n\n        return nextPickaxe?.mine(block) ?: false\n    }\n\n}\n\n// the pickaxes are from the game\nclass StonePickaxe: Pickaxe(BlockFactor.ONE)\n\nclass IronPickaxe: Pickaxe(BlockFactor.TWO)\n\nclass DiamondPickaxe: Pickaxe(BlockFactor.THREE)"
  },
  {
    "path": "src/main/kotlin/other/BinaryDigitsCounter.kt",
    "content": "package other\n\n/**\n *\n * This algorithm counts the number of ones and zeros in a binary string\n *\n * and implemented on a finite state machine\n *\n */\n\nclass BinaryDigitsCounter {\n    \n    data class Result(private val ones: Int = 0, private val zeros: Int = 0)\n\n    // represents two states\n    private enum class State { \n        ONE, ZERO \n    }\n\n    fun compute(binaryString: String): Result { // 1010010011\n        if (binaryString.isEmpty()) {\n            return Result()\n        }\n\n        // define initial state\n        var currentState = if (binaryString.first() == '1') State.ONE else State.ZERO\n\n        var onesCount = 0\n        var zerosCount = 0\n\n        binaryString.forEach { symbol ->\n            // we use 'when' statement to toggle the state\n            when (currentState) {\n                State.ONE -> {\n                    if (symbol == '0') {\n                        zerosCount++\n                        // move to another state\n                        currentState = State.ZERO\n                    } else {\n                        onesCount++\n                    }\n                }\n                State.ZERO -> {\n                    if (symbol == '1') {\n                        onesCount++\n                        // move to another state\n                        currentState = State.ONE\n                    } else {\n                        zerosCount++\n                    }\n                }\n            }\n        }\n\n        return Result(onesCount, zerosCount)\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/EuclidAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Euclid's algorithm for finding the greatest common divisor\n *\n */\n\nclass EuclidAlgorithm {\n\n    fun computeByDivisionWithRemainder(number1: Int, number2: Int) : Int {\n        var copyNumber1 = number1\n        var copyNumber2 = number2\n        while (copyNumber1 != 0 && copyNumber2 != 0) {\n            if (copyNumber1 > copyNumber2) {\n                copyNumber1 %= copyNumber2\n            } else {\n                copyNumber2 %= copyNumber1\n            }\n        }\n        return copyNumber1 + copyNumber2\n    }\n\n    fun computeBySubtraction(number1: Int, number2: Int): Int {\n        var copyNumber1 = number1\n        var copyNumber2 = number2\n        while (copyNumber1 != copyNumber2) {\n            if (copyNumber1 > copyNumber2) {\n                copyNumber1 -= copyNumber2\n            } else {\n                copyNumber2 -= copyNumber1\n            }\n        }\n        return copyNumber1\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/Factorial.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n */\n\nclass Factorial {\n\n    /**\n     * iterative method\n     * worst time: O(n)\n     * amount of memory: O(1)\n     */\n    fun compute(number: Int) : Int {\n        if (number <= 1) {\n            return 1\n        }\n\n        var result = 1\n        for (i in 2..number) {\n           result *= i\n        }\n        return result\n    }\n\n    /**\n     * recursive method\n     * worst time: O(n)\n     * amount of memory: O(n) - stack for recursion\n     */\n    fun computeRecursive(number: Int) : Int {\n        return if (number <= 1) {\n            1\n        } else {\n            number * computeRecursive(number - 1)\n        }\n    }\n\n    // read more: https://kotlinlang.org/docs/functions.html#tail-recursive-functions\n    tailrec fun computeRecursiveWithKotlinOptimization(number: Int, result: Int = 1) : Int =\n        if (number <= 1) result else computeRecursiveWithKotlinOptimization(number - 1, result * number)\n\n}"
  },
  {
    "path": "src/main/kotlin/other/FactorialAdvanced.kt",
    "content": "package other\n\nimport java.math.BigInteger\n\n/**\n *\n * This algorithm is taken from Google Guava library\n *\n */\n\nclass FactorialAdvanced {\n\n    // precomputed factorials\n    private val factorials = longArrayOf(\n        1L,\n        1L,\n        1L * 2,\n        1L * 2 * 3,\n        1L * 2 * 3 * 4,\n        1L * 2 * 3 * 4 * 5,\n        1L * 2 * 3 * 4 * 5 * 6,\n        1L * 2 * 3 * 4 * 5 * 6 * 7,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19,\n        1L * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20\n    )\n\n    fun compute(n: Int): BigInteger {\n        if (n <= 0) {\n            return BigInteger.ZERO\n        }\n\n        if (n < factorials.size) {\n            return BigInteger.valueOf(factorials[n])\n        }\n\n        // pre-allocate space for our list of intermediate BigIntegers.\n        val approxSize = divide(n * log2Celling(n), Long.SIZE_BITS)\n        val bigNumbers = ArrayList<BigInteger>(approxSize)\n\n        // start from the pre-computed maximum long factorial.\n        val startingNumber = factorials.size\n        var number = factorials[startingNumber - 1]\n        // strip off 2s from this value.\n        var shift = number.countTrailingZeroBits()\n        number = number shr shift\n\n        // use floor(log2(num)) + 1 to prevent overflow of multiplication.\n        var numberBits = log2Floor(number) + 1\n        var bits = log2Floor(startingNumber.toLong()) + 1\n        // check for the next power of two boundary, to save us a CLZ operation.\n        var nextPowerOfTwo = 1 shl bits - 1\n\n        // iteratively multiply the longs as big as they can go.\n        for (num in startingNumber..n) {\n            // check to see if the floor(log2(num)) + 1 has changed.\n            if ((num and nextPowerOfTwo) != 0) {\n                nextPowerOfTwo = nextPowerOfTwo shl 1\n                bits++\n            }\n            // get rid of the 2s in num.\n            val tz = num.toLong().countTrailingZeroBits()\n            val normalizedNum = (num shr tz).toLong()\n            shift += tz\n            // adjust floor(log2(num)) + 1.\n            val normalizedBits = bits - tz\n            // if it won't fit in a long, then we store off the intermediate product.\n            if (normalizedBits + numberBits >= Long.SIZE_BITS) {\n                bigNumbers.add(BigInteger.valueOf(number))\n                number = 1\n                numberBits = 0\n            }\n            number *= normalizedNum\n            numberBits = log2Floor(number) + 1\n        }\n        // check for leftovers.\n        if (number > 1) {\n            bigNumbers.add(BigInteger.valueOf(number))\n        }\n        // efficiently multiply all the intermediate products together.\n        return listNumbers(bigNumbers).shiftLeft(shift)\n    }\n\n    /**\n     * Returns the result of dividing p by q, rounding using the celling\n     *\n     * @throws ArithmeticException if q == 0\n     */\n    private fun divide(number: Int, divider: Int): Int {\n        if (divider == 0) {\n            throw ArithmeticException(\"/ by zero\") // for GWT\n        }\n        val div = number / divider\n        val rem = number - divider * div // equal to number % divider\n        if (rem == 0) {\n            return div\n        }\n        val signedNumber = 1 or (number xor divider shr Int.SIZE_BITS - 1)\n        val increment = signedNumber > 0\n        return if (increment) div + signedNumber else div\n    }\n\n    private fun listNumbers(numbers: List<BigInteger>, start: Int = 0, end: Int = numbers.size): BigInteger {\n        return when (end - start) {\n            0 -> BigInteger.ONE\n            1 -> numbers[start]\n            2 -> numbers[start].multiply(numbers[start + 1])\n            3 -> numbers[start].multiply(numbers[start + 1]).multiply(numbers[start + 2])\n            else -> {\n                // otherwise, split the list in half and recursively do this.\n                val m = end + start ushr 1\n                listNumbers(numbers, start, m).multiply(listNumbers(numbers, m, end))\n            }\n        }\n    }\n\n    // returns the base-2 logarithm of number, rounded according to the celling.\n    private fun log2Celling(number: Int): Int {\n        return Int.SIZE_BITS - (number - 1).countLeadingZeroBits()\n    }\n\n    // returns the base-2 logarithm of number rounded according to the floor.\n    private fun log2Floor(number: Long): Int {\n        return Long.SIZE_BITS - 1 - number.countLeadingZeroBits()\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/FactorialBigWithCache.kt",
    "content": "package other\n\nimport java.math.BigInteger\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n * optimization: caching previous factorial values\n *\n * also adding large numbers\n *\n * worst time: O(n)\n * the best time: O(1)\n * amount of memory: O(n)\n * problem: creating a huge number of BigInteger objects\n *\n */\n\nclass FactorialBigWithCache {\n\n    private val cache = hashMapOf<Int, BigInteger>()\n\n    fun compute(number: Int) : BigInteger {\n        if (number <= 1) {\n            return BigInteger.ONE\n        }\n\n        val cachedResult = cache[number]\n        if (cachedResult != null) {\n            return cachedResult\n        }\n\n        var result = BigInteger.ONE\n        for (i in 2..number) {\n            result = result.multiply(i.toBigInteger())\n            cache[i] = result\n        }\n        return result\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/FactorialWithCache.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for finding the factorial of a positive number n\n *\n * optimization: caching previous factorial values\n *\n * worst time: O(n)\n * the best time: O(1)\n * amount of memory: O(n)\n *\n */\n\nclass FactorialWithCache {\n\n    private val cache = hashMapOf<Int, Int>()\n\n    fun compute(number: Int) : Int {\n        if (number <= 1) {\n            return 1\n        }\n\n        val cachedResult = cache[number]\n        if (cachedResult != null) {\n            return cachedResult\n        }\n\n        var result = 1\n        for (i in 2..number) {\n            result *= i\n            cache[i] = result\n        }\n        return result\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/FizzBuzz.kt",
    "content": "package other\n\n/**\n * The simplest FizzBuzz game\n *\n * description: the player says numbers in sequence, provided:\n *  - if the number is divisible by 3 it says fizz\n *  - if the number is divisible by 5 it says buzz\n *  - if the number is divisible by both 3 and 5, it says FizzBuzz\n *  - otherwise, the player calls the number itself\n */\n\nclass FizzBuzz {\n\n    // determines what to say for a number in the FizzBuzz game and returns Fizz, Buzz, FizzBuzz or number\n    fun compute(number: Int) : String {\n        return when {\n            number % 3 == 0 && number % 5 == 0 -> \"FizzBuzz\"\n            number % 3 == 0 -> \"Fizz\"\n            number % 5 == 0 -> \"Buzz\"\n            else -> number.toString()\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/KnuthMorrisPrattAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Knut Morris Pratt's Algorithm for finding a substring in a string\n *\n */\n\nclass KnuthMorrisPrattAlgorithm {\n    \n    // returns true if the substring is in the string\n    fun contains(sub: String, str: String) : Boolean {\n        val summary = \"$sub$SEPARATOR$str\"\n        val prefixFunctionValue = prefixFunction(summary)\n        return prefixFunctionValue.any { value -> value == sub.length }\n    }\n\n    // returns the number of occurrences of a substring in a string\n    fun count(sub: String, str: String) : Int {\n        val summary = \"$sub$SEPARATOR$str\"\n        return prefixFunction(summary).count { value -> value == sub.length }\n    }\n\n    // returns an array of prefix functions for a string\n    private fun prefixFunction(str: String) : Array<Int> {\n        val prefixFunctionsValues = Array(str.length) { 0 }\n        for (index in 1 until str.length) {\n            var prefixFunctionValue = prefixFunctionsValues[index - 1]\n            while (prefixFunctionValue > 0 && str[index] != str[prefixFunctionValue]) {\n                prefixFunctionValue = prefixFunctionsValues[prefixFunctionValue - 1]\n            }\n            if (str[index] == str[prefixFunctionValue]) {\n                prefixFunctionValue++\n            }\n            prefixFunctionsValues[index] = prefixFunctionValue\n        }\n        return prefixFunctionsValues\n    }\n\n    companion object {\n        // delimiter must not occur in source strings\n        private const val SEPARATOR = \"#\"\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/LevenshteinLengthAlgorithm.kt",
    "content": "package other\n\nimport java.lang.Integer.min\n\n/**\n *\n * Algorithm for determining the Levenshtein distance\n *\n */\n\nclass LevenshteinLengthAlgorithm {\n\n    fun compute(str1: String, str2: String) : Int {\n        val matrix = Array(str1.length + 1) {\n            Array(str2.length + 1) { 0 }\n        }\n\n        for (i in 0..str1.length) {\n            matrix[i][0] = i\n        }\n\n        for (i in 0..str2.length) {\n            matrix[0][i] = i\n        }\n\n        for (i in 1..str1.length) {\n            for (j in 1..str2.length) {\n                if (str1[i - 1] == str2[j - 1]) {\n                    matrix[i][j] = matrix[i - 1][j - 1]\n                } else {\n                    matrix[i][j] = min(min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i - 1][j - 1]) + 1\n                }\n            }\n        }\n\n        return matrix[str1.length][str2.length]\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/MaxAlgorithm.kt",
    "content": "package other\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Algorithm for finding the maximum value from a list\n *\n */\n\nclass MaxAlgorithm {\n\n    fun <T : Comparable<T>> compute(items: List<T>) : T {\n        if (items.isEmpty()) {\n            throw IllegalArgumentException(\"items list is empty!\")\n        }\n        var max = items[0]\n        for (i in 1 until items.size) {\n            if (max < items[i]) {\n                max = items[i]\n            }\n        }\n        return max\n    }\n\n    /**\n     * returns the maximum element from the list recursively\n     */\n    fun <T : Comparable<T>> computeRecursive(items: List<T>) : T {\n        if (items.isEmpty()) {\n            throw IllegalArgumentException(\"items list is empty!\")\n        }\n        if (items.size == 1) {\n            return items.first()\n        }\n        val first = items.first()\n        val others = items.subList(1, items.size)\n\n        val max = computeRecursive(others)\n\n        return if (first > max) first else max\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/MinAlgorithm.kt",
    "content": "package other\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Algorithm for finding the minimum value from a list\n *\n */\n\nclass MinAlgorithm {\n\n    fun <T : Comparable<T>> compute(items: List<T>) : T {\n        if (items.isEmpty()) {\n            throw IllegalArgumentException(\"items list is empty!\")\n        }\n        var min = items[0]\n        for (i in 1 until items.size) {\n            if (min > items[i]) {\n                min = items[i]\n            }\n        }\n        return min\n    }\n\n    fun <T : Comparable<T>> computeRecursive(items: List<T>) : T {\n        if (items.isEmpty()) {\n            throw IllegalArgumentException(\"items list is empty!\")\n        }\n        if (items.size == 1) {\n            return items.first()\n        }\n        val first = items.first()\n        val others = items.subList(1, items.size)\n\n        val min = computeRecursive(others)\n\n        return if (first < min) first else min\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/PalindromeAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for checking a string for a palindrome\n *\n * P.S. A palindrome is a word, number, phrase, or other sequence of symbols\n * that reads the same backwards as forwards, such as \"madam\"\n */\n\nclass PalindromeAlgorithm {\n\n    // checks a string for a palindrome and returns true if the string is a palindrome\n    fun isPalindrome(text: String): Boolean {\n        if (text.length <= 1) {\n            return true\n        }\n\n        val length = text.length\n        for (index in 0 until length / 2) {\n            if (text[index] != text[length - index - 1]) {\n                return false\n            }\n        }\n\n        return true\n    }\n\n    fun isPalindromeSimplifiedVersion(text: String): Boolean {\n        return text == text.reversed()\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/ParenthesisCheckAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for checking a string for correct placement of parentheses using stack\n *\n * ([]) - correctly\n * ()(){} - correctly\n * (() - incorrectly\n * (())[][]}{ - incorrectly\n *\n */\n\nclass ParenthesisCheckAlgorithm {\n\n    fun check(code: String = DEFAULT_CODE): Boolean {\n        // we use a regular kotlin list to create a stack\n        val stack = mutableListOf<Char>()\n\n        var index = 0\n        while (index < code.length) {\n\n            when (val symbol = code[index]) {\n                '(', '{', '[' -> stack.add(symbol)\n                ')', '}', ']' -> {\n                    val value = bracketRelations[stack.removeLastOrNull()]\n                    if (symbol != value) {\n                        return false\n                    }\n                }\n            }\n\n            index++\n        }\n\n        return stack.isEmpty()\n    }\n\n    companion object {\n        // the correct C program\n        private const val DEFAULT_CODE = \"\"\"\n            void main() {\n                printf(\"Hello, World!\");\n            }\n        \"\"\"\n\n        private val bracketRelations = mapOf('(' to ')', '{' to '}', '[' to ']')\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/ReverseArrayAlgorithm.kt",
    "content": "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 ReverseArrayAlgorithm {\n\n    fun <T> compute(array: Array<T>) {\n        val size = array.size\n        for (index in 0 until size / 2) {\n            array[index] = array[size - index - 1].apply {\n                array[size - index - 1] = array[index]\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/SieveOfEratosthenesAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * The sieve of Eratosthenes allows you to efficiently calculate a series of prime numbers\n *\n * algorithm complexity: nlog(logn) operations\n *\n */\n\nclass SieveOfEratosthenesAlgorithm {\n\n    // computes a series of primes up to the maximum value and returns a list of prime numbers\n    fun compute(maxNumber: Int) : List<Int> {\n        val numbers = Array(maxNumber + 1) { index -> index >= 2 }\n\n        var x = 2\n        while (x * x <= maxNumber) {\n            if (numbers[x]) {\n                for (y in x * x..maxNumber step x) {\n                    numbers[y] = false\n                }\n            }\n            x++\n        }\n\n        val primes = mutableListOf<Int>()\n\n        numbers.forEachIndexed { number, isPrime ->\n            if (isPrime) {\n                primes.add(number)\n            }\n        }\n\n        return primes\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/Sqrt.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for finding the square root of a number\n *\n * read the wikipedia article: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Heron's_method\n *\n */\n\nclass Sqrt {\n\n    // calculates the root of a number and returns result\n    fun compute(number: Double) : Double {\n        var value = number / 2\n        // the number of loop iterations is selected depending on the required accuracy\n        for (i in 1..100) {\n            value = (value + number / value) / 2\n        }\n        return value\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/other/StringEqualsHashAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for comparing two strings with a hash\n *\n */\n\nclass StringEqualsHashAlgorithm {\n\n    fun equals(source: String, pattern: String) : Boolean =\n        if (source.length != pattern.length) false else source.hash() == pattern.hash()\n\n    /**\n     *\n     * computes the hash of a string according to the formula:\n     *\n     * hash(abc) = a.code * primeCoefficient⁰ + b.code * primeCoefficient¹ + c.code * primeCoefficient²\n     *\n     */\n    private fun String.hash() : Int {\n        var result = 0\n        var factor = 1\n        forEach { symbol ->\n            result += symbol.code * factor\n            factor *= PRIME_COEFFICIENT\n        }\n        // the hash can exceed the maximum Int value, so we limit it\n        return result.mod(Int.MAX_VALUE)\n    }\n\n    companion object {\n        /**\n         *\n         * I chose the nearest prime number for the size of the alphabet\n         *\n         * my alphabet is [a-z] [A-Z] ! , .\n         *\n         * size of the alphabet = 26 + 26 + 3 = 55 (is not prime)\n         *\n         */\n        private const val PRIME_COEFFICIENT = 53\n    }\n}"
  },
  {
    "path": "src/main/kotlin/other/SwapAlgorithm.kt",
    "content": "package other\n\n/**\n *\n * Algorithm for exchanging two variables without a third additional\n *\n */\n\nclass SwapAlgorithm {\n\n    // swaps two list values at the specified indexes\n    fun swap(list: MutableList<Int>, oldIndex: Int, newIndex: Int) {\n        if (oldIndex in list.indices && newIndex in list.indices) {\n            list[oldIndex] = list[oldIndex] + list[newIndex]\n            list[newIndex] = list[oldIndex] - list[newIndex]\n            list[oldIndex] = list[oldIndex] - list[newIndex]\n        }\n    }\n\n    // swaps two array values at the specified indexes\n    fun swap(array: Array<Int>, oldIndex: Int, newIndex: Int) {\n        if (oldIndex in array.indices && newIndex in array.indices) {\n            array[oldIndex] = array[oldIndex] + array[newIndex]\n            array[newIndex] = array[oldIndex] - array[newIndex]\n            array[oldIndex] = array[oldIndex] - array[newIndex]\n        }\n    }\n\n    // swaps two list values using Kotlin language features\n    fun swapKotlin(list: MutableList<Int>, oldIndex: Int, newIndex: Int) {\n        if (oldIndex in list.indices && newIndex in list.indices) {\n            list[oldIndex] = list[newIndex].apply {\n                list[newIndex] = list[oldIndex]\n            }\n        }\n    }\n\n    // swaps two array values using Kotlin language features\n    fun swapKotlin(array: Array<Int>, oldIndex: Int, newIndex: Int) {\n        if (oldIndex in array.indices && newIndex in array.indices) {\n            array[oldIndex] = array[newIndex].apply {\n                array[newIndex] = array[oldIndex]\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/search/BinarySearch.kt",
    "content": "package search\n\n/**\n *\n * Binary search algorithm only works for sorted lists and arrays\n *\n * best time: 1\n * worst time: log(n)\n * amount of memory: 1\n *\n */\n\nclass BinarySearch {\n\n    // searches for an element in the array and returns the index of the searched element or -1\n    fun <T : Comparable<T>> search(array: Array<T>, element: T) : Int {\n        if (array.isEmpty()) return -1\n\n        var left = 0\n        var right = array.size\n        while (left < right) {\n            val middle = left + (right - left) / 2\n            if (array[middle] < element) {\n                left = middle + 1\n            } else if (array[middle] > element) {\n                right = middle\n            } else {\n                return middle\n            }\n        }\n        return -1\n    }\n\n    // recursive method\n    // P.S. The tailrec modifier tells the compiler to optimize the recursion and turn it into an iterative version\n    tailrec fun <T : Comparable<T>> searchRecursive(array: Array<T>, element: T, left: Int = 0, right: Int = array.size - 1): Int {\n        if (left <= right) {\n            val middle = left + (right - left) / 2\n            if (array[middle] == element) {\n                return middle\n            }\n            return if (array[middle] > element) {\n                searchRecursive(array, element, left, middle - 1)\n            } else {\n                searchRecursive(array, element, middle + 1, right)\n            }\n        }\n        return -1\n    }\n\n    // finds the left border index to insert an element into a sorted array\n    fun <T : Comparable<T>> leftBound(array: Array<T>, element: T) : Int {\n        if (array.isEmpty()) return 0\n\n        var left = -1\n        var right = array.size\n        while ((right - left) > 1) {\n            val middle = left + (right - left) / 2\n            if (element > array[middle]) {\n                left = middle\n            } else {\n                right = middle\n            }\n        }\n        return left\n    }\n\n    // finds the right border index to insert an element into a sorted array\n    fun <T : Comparable<T>> rightBound(array: Array<T>, element: T) : Int {\n        if (array.isEmpty()) return -1\n\n        var left = -1\n        var right = array.size\n        while ((right - left) > 1) {\n            val middle = (right + left) / 2\n            if (element > array[middle]) {\n                left = middle\n            } else {\n                right = middle\n            }\n        }\n        return right\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/search/LinearSearch.kt",
    "content": "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\nclass LinearSearch {\n\n    fun <T : Comparable<T>> search(array: Array<T>, element: T) : Int {\n        var index = 0\n        while (index < array.size) {\n            if (element == array[index]) {\n                return index\n            }\n            index++\n        }\n        return -1\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/sorting/BubbleSort.kt",
    "content": "package sorting\n\n/**\n *\n * Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm\n *\n * that repeatedly steps through the input list element by element, comparing the current element\n *\n * with the one after it, swapping their values if needed\n *\n */\n\nclass BubbleSort {\n\n    /**\n     * worst time: n²\n     * best time: n²\n     * average time: n²\n     *\n     * amount of memory: 1\n     */\n    fun <T : Comparable<T>> sort(array: Array<T>) {\n        val arraySize = array.size\n        for (i in 0 until arraySize - 1) {\n            for (j in 0 until arraySize - 1 - i) {\n                if (array[j] > array[j + 1]) {\n                    val tmp = array[j + 1]\n                    array[j + 1] = array[j]\n                    array[j] = tmp\n                }\n            }\n        }\n    }\n\n    /**\n     * worst time: n²\n     * best time: n\n     * average time: n²\n     *\n     * amount of memory: 1\n     */\n    fun <T : Comparable<T>> sortImproved(array: Array<T>) {\n        val arraySize = array.size\n        var isSorted = true\n        for (i in 0 until arraySize - 1) {\n            for (j in 0 until arraySize - 1 - i) {\n                if (array[j] > array[j + 1]) {\n                    val tmp = array[j + 1]\n                    array[j + 1] = array[j]\n                    array[j] = tmp\n\n                    isSorted = false\n                }\n            }\n            if (isSorted) break\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/sorting/CountingSort.kt",
    "content": "package sorting\n\n/**\n *\n * Counting sort is a sorting technique based on keys between a specific range\n *\n * worst time: n\n * best time: n\n * average time: n\n *\n * amount of memory: equals to the size of the range of numbers plus 1 (for example: 1001 for numbers from 0 to 1000)\n *\n * P.S. The use of counting sort is useful only when the sorted numbers have (or can be mapped to) a range of possible\n * values that is small enough compared to the sorted set, for example, a million natural numbers less than 1000\n *\n */\n\nclass CountingSort {\n\n    // sorts numbers in the range from start to end\n    fun sort(array: Array<Int>, start: Int, end: Int) {\n        val arraySize = array.size\n        val countedNumbers = Array(end + 1) { 0 }\n\n        var index = 0\n        while (index < arraySize) {\n            countedNumbers[array[index]]++\n            index++\n        }\n\n        index = 0\n        var currentNumber = start\n        while (currentNumber < countedNumbers.size) {\n            var frequency = countedNumbers[currentNumber]\n            while (frequency > 0) {\n                array[index++] = currentNumber\n                frequency--\n            }\n            currentNumber++\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/sorting/InsertionSort.kt",
    "content": "package sorting\n\n/**\n *\n * Insertion sort is a simple sorting algorithm that works similar to the way you sort playing cards in your hands.\n *\n * The array is virtually split into a sorted and an unsorted part.\n *\n * Values from the unsorted part are picked and placed at the correct position in the sorted part.\n *\n * worst time: n²\n * best time: n\n * average time: n²\n *\n * amount of time: 1\n *\n */\n\nclass InsertionSort {\n\n    fun <T : Comparable<T>> sort(array: Array<T>) {\n        val arraySize = array.size\n        for (i in 1 until arraySize) {\n            val current = array[i]\n            var j = i - 1\n            while (j >= 0 && array[j] > current) {\n                array[j + 1] = array[j]\n                j--\n            }\n            array[j + 1] = current\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/sorting/MergeSort.kt",
    "content": "package sorting\n\n/**\n *\n * Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945\n *\n * Conceptually, a merge sort works as follows:\n *\n * 1) Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted).\n *\n * 2) Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining.\n * This will be the sorted list.\n *\n */\n\nclass MergeSort {\n\n    /**\n     * worst time: n * log(n)\n     * best time: n * log(n)\n     * average time: n * log(n)\n     *\n     * amount of memory: n\n     */\n    fun <T : Comparable<T>> sort(array: Array<T>) {\n        val arraySize = array.size\n        val temporaryArray = array.copyOf()\n\n        var windowSize = 1\n        while (windowSize < arraySize) {\n\n            var left = 0\n            while (left + windowSize < arraySize) {\n\n                val middle = left + windowSize\n                var right = middle + windowSize\n                if (right > arraySize) right = arraySize\n\n                var i = left\n                var k = left\n                var j = middle\n                while (i < middle && j < right) {\n                    if (array[i] <= array[j]) {\n                        temporaryArray[k] = array[i]\n                        i++\n                    } else {\n                        temporaryArray[k] = array[j]\n                        j++\n                    }\n                    k++\n                }\n\n                while (i < middle) {\n                    temporaryArray[k] = array[i]\n                    i++\n                    k++\n                }\n\n                while (j < right) {\n                    temporaryArray[k] = array[j]\n                    j++\n                    k++\n                }\n\n                i = left\n                while (i < right) {\n                    array[i] = temporaryArray[i]\n                    i++\n                }\n\n                left += windowSize * 2\n            }\n\n            windowSize *= 2\n        }\n    }\n\n    /**\n     * worst time: n * log(n)\n     * best time: n * log(n)\n     * average time: n * log(n)\n     *\n     * amount of memory: n * log(n)\n     */\n    fun sortRecursive(array: Array<Int>) {\n        val arraySize = array.size\n\n        if (arraySize < 2)\n            return\n\n        val middle = arraySize / 2\n\n        val left = Array(middle) { 0 }\n        val right = Array(arraySize - middle) { 0 }\n\n        var i = 0\n        while (i < middle) {\n            left[i] = array[i]\n            i++\n        }\n\n        while (i < arraySize) {\n            right[i - middle] = array[i]\n            i++\n        }\n\n        sortRecursive(left)\n        sortRecursive(right)\n\n        val leftSize = left.size\n        val rightSize = right.size\n\n        i = 0\n        var j = 0\n        var k = 0\n        while (i < leftSize && j < rightSize) {\n            if (left[i]  <= right[j]) {\n                array[k] = left[i]\n                i++\n            } else {\n                array[k] = right[j]\n                j++\n            }\n            k++\n        }\n\n        while (i < leftSize) {\n            array[k] = left[i]\n            i++\n            k++\n        }\n\n        while (j < rightSize) {\n            array[k] = right[j]\n            j++\n            k++\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/sorting/QuickSort.kt",
    "content": "package sorting\n\nimport kotlin.random.Random\n\n/**\n *\n * QuickSort is a sorting algorithm based on the Divide and Conquer algorithm\n *\n * that picks an element as a pivot and partitions the given array around the picked pivot\n *\n * by placing the pivot in its correct position in the sorted array.\n *\n *\n * worst time: n²\n * best time: n * log(n)\n * average time: n * log(n)\n *\n * amount of memory: n\n *\n */\n\nclass QuickSort {\n\n    fun <T : Comparable<T>> sort(array: Array<T>, start: Int = 0, end: Int = array.size - 1) {\n        if (array.isEmpty()) return\n        if (start >= end) return\n\n        val pivotIndex = Random.nextInt(start, end + 1)\n        val pivot = array[pivotIndex]\n\n        var i = start\n        var j = end\n        while (i <= j) {\n            while (array[i] < pivot) {\n                i++\n            }\n            while (array[j] > pivot) {\n                j--\n            }\n            if (i <= j) {\n                val tmp = array[i]\n                array[i] = array[j]\n                array[j] = tmp\n                i++\n                j--\n            }\n        }\n\n        if (i < end) sort(array, i, end)\n        if (0 < j) sort(array, start, j)\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/sorting/RadixSort.kt",
    "content": "package sorting\n\n/**\n *\n * Radix Sort is a linear sorting algorithm that sorts elements by processing them digit by digit.\n *\n * It is an efficient sorting algorithm for integers or strings with fixed-size keys.\n *\n * worst time: <number of bits of an integer> * n\n *\n * amount of memory: 2 * n\n */\n\nclass RadixSort {\n\n    fun sort(array: Array<Int>) {\n        val arraySize = array.size\n        val arrayOfZeroBits = Array(arraySize) { 0 }\n        val arrayOfOneBits = Array(arraySize) { 0 }\n\n        val size = Int.SIZE_BITS\n\n        for (radix in 0 until size) {\n            var size1 = 0\n            var size2 = 0\n            for (index in array.indices) {\n                if (array[index].and(1 shl radix) == 0) {\n                    arrayOfZeroBits[size1++] = array[index]\n                } else {\n                    arrayOfOneBits[size2++] = array[index]\n                }\n            }\n\n            for (index in 0 until size1) {\n                array[index] = arrayOfZeroBits[index]\n            }\n\n            for (index in 0 until size2) {\n                array[size1 + index] = arrayOfOneBits[index]\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/sorting/SelectionSort.kt",
    "content": "package sorting\n\n/**\n *\n * Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting\n *\n * the smallest (or largest) element from the unsorted portion of the list and\n *\n * moving it to the sorted portion of the list.\n *\n * worst time: n²\n * best time: n²\n * average time: n²\n *\n * amount of memory: 1\n *\n */\n\nclass SelectionSort {\n\n    fun <T : Comparable<T>> sort(array: Array<T>) {\n        val arraySize = array.size\n        for (i in 0 until arraySize - 1) {\n            var min = i\n            for (j in i + 1 until arraySize) {\n                if (array[min] > array[j]) {\n                    min = j\n                }\n            }\n            if (min != i) {\n                val tmp = array[i]\n                array[i] = array[min]\n                array[min] = tmp\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/sorting/TimSort.kt",
    "content": "package sorting\n\nimport kotlin.math.min\n\n/**\n *\n * Tim Sort is a hybrid sorting algorithm derived from merge sort and insertion sort\n *\n * used by Python’s sorted() and list.sort() functions, which was designed to perform well on\n *\n * many kinds of real-world data.\n *\n * worst time: n * log(n)\n * best time: n\n * average time: n * log(n)\n *\n * amount of memory: n\n *\n */\n\nclass TimSort {\n\n    fun sort(array: Array<Int>) {\n        val arraySize = array.size\n        val minRunSize = minRunSize(arraySize)\n\n        var i = 0\n        while (i < arraySize) {\n            insertionSort(array, i, min(i + minRunSize - 1, arraySize - 1))\n            i += minRunSize\n        }\n\n        var mergingSize = minRunSize\n        while (mergingSize < arraySize) {\n            var start = 0\n            while (start < arraySize) {\n                val middle = start + mergingSize - 1\n                val end = min(start + 2 * mergingSize - 1, arraySize - 1)\n                if (middle < end) {\n                    merge(array, start, middle, end)\n                }\n                start += mergingSize * 2\n            }\n            mergingSize *= 2\n        }\n    }\n\n    /**\n     * Minrun is chosen from the range 32 to 64 inclusive, such that the size of the data, divided by minrun, is equal to,\n     * or slightly less than, a power of two. The final algorithm takes the six most significant bits of the size of the array,\n     * adds one if any of the remaining bits are set, and uses that result as the minrun.\n     * This algorithm works for all arrays, including those smaller than 64; for arrays of size 63 or less,\n     * this sets minrun equal to the array size and Timsort reduces to an insertion sort\n     */\n    private fun minRunSize(arraySize: Int) : Int {\n        var result = 0\n        var size = arraySize\n        while (size >= 64) {\n            result = result or (size and 1)\n            // shift one bit to the right until 6 significant bits remain\n            size = size shr 1\n        }\n\n        return size + result\n    }\n\n    private fun insertionSort(array: Array<Int>, start: Int, end: Int) {\n        var i = start + 1\n        while (i <= end) {\n            val current = array[i]\n            var j = i - 1\n            while (j >= start && array[j] > current) {\n                array[j + 1] = array[j]\n                j--\n            }\n            array[j + 1] = current\n            i++\n        }\n    }\n\n    private fun merge(array: Array<Int>, start: Int, middle: Int, end: Int) {\n        val leftSize = middle - start + 1\n        val rightSize = end - middle\n\n        var i = 0\n        val leftArray = Array(leftSize) { 0 }\n        while (i < leftSize) {\n            leftArray[i] = array[start + i]\n            i++\n        }\n\n        i = 0\n        val rightArray = Array(rightSize) { 0 }\n        while (i < rightSize) {\n            rightArray[i] = array[middle + i + 1]\n            i++\n        }\n\n        i = 0\n        var j = 0\n        var k = start\n        while (i < leftSize && j < rightSize) {\n            if (leftArray[i] <= rightArray[j]) {\n                array[k] = leftArray[i]\n                i++\n            } else {\n                array[k] = rightArray[j]\n                j++\n            }\n            k++\n        }\n\n        while (i < leftSize) {\n            array[k] = leftArray[i]\n            i++\n            k++\n        }\n\n        while (j < rightSize) {\n            array[k] = rightArray[j]\n            j++\n            k++\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/BinaryTree.kt",
    "content": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Binary tree consists of nodes each of which has a maximum of two children.\n *\n * Child nodes satisfy the following requirements:\n *\n *  - the left child is less than the parent\n *  - right child is larger than parent\n *\n * Hint: the worst time may be O(n) because the situation is possible when the elements follow each other 1,2,3,4...\n * and the tree takes the following form:\n *\n *  1\n *   \\\n *    2\n *     \\\n *      3\n *       \\\n *        4\n *\n */\n\nclass BinaryTree<T : Comparable<T>> {\n\n    private var root: Node<T>? = null\n\n    val isEmpty: Boolean\n        get() = root == null\n\n    /**\n     * Complexity:\n     * worst time: O(n), read the hint in the description\n     * best time: O(log(n))\n     * average time: O(log(n))\n     */\n    fun add(value: T) {\n        fun addRecursive(current: Node<T>?, value: T): Node<T> {\n            if (current == null) {\n                return Node(value)\n            }\n            if (value < current.value()) {\n                current.changeLeft(addRecursive(current.leftNode(), value))\n            } else if (value > current.value()) {\n                current.changeRight(addRecursive(current.rightNode(), value))\n            }\n            return current\n        }\n\n        root = addRecursive(root, value)\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n), read the hint in the description\n     * best time: O(1)\n     * average time: O(log(n))\n     */\n    fun remove(value: T) {\n        fun smallestValue(root: Node<T>): T {\n            val leftNode = root.leftNode()\n            if (leftNode === null) return root.value()\n            return smallestValue(leftNode)\n        }\n\n        fun removeRecursive(current: Node<T>?, value: T): Node<T>? {\n            if (current == null) {\n                return null\n            }\n\n            if (value == current.value()) {\n                if (current.leftNode() == null && current.rightNode() == null) {\n                    return null\n                }\n                if (current.leftNode() == null) {\n                    return current.rightNode()\n                }\n                if (current.rightNode() == null) {\n                    return current.leftNode()\n                }\n\n                val smallestValue = smallestValue(current.rightNode()!!)\n                current.changeValue(smallestValue)\n                current.changeRight(removeRecursive(current.rightNode(), smallestValue))\n                return current\n            }\n\n            if (value < current.value()) {\n                current.changeLeft(removeRecursive(current.leftNode(), value))\n            } else {\n                current.changeRight(removeRecursive(current.rightNode(), value))\n            }\n\n            return current\n        }\n\n        root = removeRecursive(root, value)\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n), read the hint in the description\n     * best time: O(1)\n     * average time: O(log(n))\n     */\n    fun contains(value: T): Boolean {\n        fun containsRecursive(current: Node<T>?, value: T): Boolean {\n            if (current == null) {\n                return false\n            }\n            if (value == current.value()) {\n                return true\n            }\n            return if (value < current.value()) {\n                containsRecursive(current.leftNode(), value)\n            } else {\n                containsRecursive(current.rightNode(), value)\n            }\n        }\n\n        return containsRecursive(root, value)\n    }\n\n    /**\n     *\n     * Traversal of the binary tree in depth\n     *\n     * order: the left child, the parent, the right child\n     *\n     */\n    fun traverseInOrder(): List<T> {\n        fun traverseInOrderRecursive(node: Node<T>?, nodes: MutableList<T>) {\n            if (node != null) {\n                traverseInOrderRecursive(node.leftNode(), nodes)\n                nodes.add(node.value())\n                traverseInOrderRecursive(node.rightNode(), nodes)\n            }\n        }\n\n        val nodes = mutableListOf<T>()\n        traverseInOrderRecursive(root, nodes)\n        return nodes\n    }\n\n    /**\n     *\n     * Traversal of the binary tree in depth\n     *\n     * order: the parent, the left child, the right child\n     *\n     */\n    fun traversePreOrder(): List<T> {\n        fun traversePreOrderRecursive(node: Node<T>?, nodes: MutableList<T>) {\n            if (node != null) {\n                nodes.add(node.value())\n                traversePreOrderRecursive(node.leftNode(), nodes)\n                traversePreOrderRecursive(node.rightNode(), nodes)\n            }\n        }\n\n        val nodes = mutableListOf<T>()\n        traversePreOrderRecursive(root, nodes)\n        return nodes\n    }\n\n    /**\n     *\n     * Traversal of the binary tree in depth\n     *\n     * order: the left child, the right child, the parent\n     *\n     */\n    fun traversePostOrder(): List<T> {\n        fun traversePostOrderRec(node: Node<T>?, nodes: MutableList<T>) {\n            if (node != null) {\n                traversePostOrderRec(node.leftNode(), nodes)\n                traversePostOrderRec(node.rightNode(), nodes)\n                nodes.add(node.value())\n            }\n        }\n\n        val nodes = mutableListOf<T>()\n        traversePostOrderRec(root, nodes)\n        return nodes\n    }\n\n    /**\n     *\n     * Traversal of the binary tree in breadth uses an additional data structure - a queue into which new tree\n     *\n     * nodes are added until the last node is added\n     *\n     */\n    fun traverseLevelOrder(): List<T> {\n        val current = root ?: return emptyList()\n\n        val queue = LinkedList<Node<T>>()\n        queue.add(current)\n\n        val nodeValues = mutableListOf<T>()\n\n        while (queue.isNotEmpty()) {\n            val node = queue.removeFirst()\n\n            nodeValues.add(node.value())\n\n            val leftNode = node.leftNode()\n            if (leftNode != null) {\n                queue.add(leftNode)\n            }\n\n            val rightNode = node.rightNode()\n            if (rightNode != null) {\n                queue.add(rightNode)\n            }\n        }\n\n        return nodeValues\n    }\n\n    class Node<T>(\n        private var value: T,\n        private var left: Node<T>? = null,\n        private var right: Node<T>? = null\n    ) {\n\n        fun value() = value\n        fun changeValue(newValue: T) {\n            value = newValue\n        }\n\n        fun leftNode() = left\n        fun changeLeft(node: Node<T>?) {\n            left = node\n        }\n\n        fun rightNode() = right\n        fun changeRight(node: Node<T>?) {\n            right = node\n        }\n\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/CircularLinkedList.kt",
    "content": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.\n *\n * In the single LinkedList with circular reference each node contains a link to the next element,\n * the last one refers to the first\n *\n */\n\nclass CircularLinkedList<T> {\n\n    private var head: Node<T>? = null\n    private var tail: Node<T>? = null\n\n    private var size: Int = 0\n\n    val isEmpty: Boolean\n        get() = head == null\n\n    /**\n     * The simple method to test functionality of the LinkedList with circular reference\n     *\n     * Complexity: O(n * cycleNumber)\n     */\n    fun cyclingList(cycleNumber: Int = 1): List<T> {\n        val nodeList = mutableListOf<T>()\n        var currentCycle = 0\n\n        if (isEmpty) return nodeList\n\n        while (currentCycle < cycleNumber) {\n\n            var node = head\n            while (node != null) {\n                val nodeValue = node.value()\n                if (nodeValue != null) {\n                    nodeList.add(nodeValue)\n                }\n\n                if (node === tail) {\n                    currentCycle++\n                    break\n                }\n\n                node = node.next()\n            }\n\n        }\n\n        return nodeList\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun add(index: Int, value: T) : Boolean {\n        if (head == null) return false\n\n        var i = 0\n        var node = head\n        var prevNode = head\n        while (prevNode != null && node != null) {\n            if (i == index) {\n                val newNode = Node(value)\n                newNode.changeNext(node)\n                prevNode.changeNext(newNode)\n                size++\n                return true\n            }\n            i++\n\n            if (node === tail) {\n                break\n            }\n\n            prevNode = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    fun add(value: T) = addLast(value)\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addFirst(value: T) {\n        val node = Node(value)\n        if (head == null) {\n            head = node\n            tail = node\n        } else {\n            node.changeNext(head)\n            head = node\n        }\n        tail?.changeNext(head)\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addLast(value: T) {\n        val node = Node(value)\n        if (head == null) {\n            head = node\n            tail = node\n        } else {\n            tail?.changeNext(node)\n            tail = node\n        }\n        tail?.changeNext(head)\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun contains(value: T) : Boolean {\n        if (head == null) return false\n\n        var node = head\n        while (node != null) {\n            if (node.value() == value) {\n                return true\n            }\n\n            if (node === tail) {\n                break\n            }\n\n            node = node.next()\n        }\n\n        return false\n    }\n\n    // Complexity: O(n)\n    fun clear() {\n        var node = head\n        while (node != null) {\n            val currentNode = node\n\n            node = node.next()\n\n            currentNode.changeNext(null)\n            currentNode.changeValue(null)\n\n            if (currentNode === tail) {\n                break\n            }\n        }\n\n        head = null\n        tail = null\n        size = 0\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun remove(value: T) : Boolean {\n        if (head == null) return false\n\n        var previous: Node<T>? = null\n        var node = head\n\n        while (node != null) {\n            if (node.value() == value) {\n                var nextNode = node.next()\n                if (nextNode === head) {\n                    nextNode = null\n                }\n                previous?.changeNext(nextNode)\n\n                if (head === node) {\n                    head = nextNode\n                }\n\n                if (tail === node) {\n                    tail = previous\n                }\n\n                node.changeNext(null)\n                node.changeValue(null)\n\n                tail?.changeNext(head)\n\n                size--\n\n                return true\n            }\n\n            if (node === tail) {\n                break\n            }\n\n            previous = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    override fun toString(): String {\n        val builder = StringBuilder()\n        builder.append(\"size: $size\\n\")\n        builder.append(\"elements: \")\n\n        var node = head\n        while (node != null) {\n            builder.append(node.value())\n\n            // it's necessary to see the correct node connections\n            if (node.next() != null) {\n                builder.append(\" - \")\n            }\n\n            if (node === tail) {\n                break\n            }\n\n            node = node.next()\n        }\n\n        return builder.toString()\n    }\n\n    class Node<T>(\n        private var value: T? = null,\n        private var next: Node<T>? = null\n    ) {\n\n        fun next() = next\n        fun changeNext(node: Node<T>? = null) {\n            next = node\n        }\n\n        fun value() = value\n        fun changeValue(newValue: T?) {\n            value = newValue\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/DoubleLinkedList.kt",
    "content": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.\n *\n * In the double LinkedList each node contains a link to the previous and next elements\n *\n */\n\nclass DoubleLinkedList<T> {\n\n    private var head: Node<T>? = null\n    private var tail: Node<T>? = null\n\n    private var size: Int = 0\n\n    val isEmpty: Boolean\n        get() = head == null\n\n    // Complexity: O(n)\n    val list: List<T>\n        get() {\n            val nodes = mutableListOf<T>()\n            var node = head\n            while (node != null) {\n                val nodeValue = node.value()\n                if (nodeValue != null) {\n                    nodes.add(nodeValue)\n                }\n                node = node.next()\n            }\n            return nodes\n        }\n\n    // Complexity: O(n)\n    val reversedList: List<T>\n        get() {\n            val nodes = mutableListOf<T>()\n            var node = tail\n            while (node != null) {\n                val nodeValue = node.value()\n                if (nodeValue != null) {\n                    nodes.add(nodeValue)\n                }\n                node = node.previous()\n            }\n            return nodes\n        }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun add(index: Int, value: T) : Boolean {\n        if (head == null) return false\n\n        var i = 0\n        var node = head\n        var prevNode = head\n        while (prevNode != null && node != null) {\n            if (i == index) {\n                val newNode = Node(value)\n                newNode.changeNext(node)\n                newNode.changePrevious(prevNode)\n                prevNode.changeNext(newNode)\n                size++\n                return true\n            }\n            i++\n            prevNode = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    fun add(value: T) = addLast(value)\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addFirst(value: T) {\n        val headNode = head\n        head = if (headNode == null) {\n            Node(value)\n        } else {\n            val newNode = Node(value = value, next = headNode)\n            headNode.changePrevious(newNode)\n            newNode\n        }\n        if (tail == null) {\n            tail = head\n        }\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addLast(value: T) {\n        val tailNode = tail\n        tail = if (tailNode == null) {\n            Node(value)\n        } else {\n            val newNode = Node(value = value, previous = tailNode)\n            tailNode.changeNext(newNode)\n            newNode\n        }\n        if (head == null) {\n            head = tail\n        }\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun contains(value: T) : Boolean {\n        if (head == null) return false\n\n        var node = head\n        while (node != null) {\n            if (node.value() == value) {\n                return true\n            }\n            node = node.next()\n        }\n        return false\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun remove(value: T) : Boolean {\n        if (head == null) return false\n\n        var previous: Node<T>? = null\n        var node = head\n\n        while (node != null) {\n            if (node.value() == value) {\n                val nextNode = node.next()\n                previous?.changeNext(nextNode)\n                nextNode?.changePrevious(previous)\n\n                if (node === head) {\n                    head = nextNode\n                }\n\n                if (node === tail) {\n                    tail = previous\n                }\n\n                node.changePrevious(null)\n                node.changeNext(null)\n                node.changeValue(null)\n\n                size--\n                return true\n            }\n            previous = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    // Complexity: O(n)\n    fun clear() {\n        var node = head\n        while (node != null) {\n            val currentNode = node\n\n            node = node.next()\n\n            currentNode.changeNext(null)\n            currentNode.changePrevious(null)\n            currentNode.changeValue(null)\n        }\n\n        head = null\n        tail = null\n        size = 0\n    }\n\n    override fun toString(): String {\n        val builder = StringBuilder()\n        builder.append(\"size: $size\\n\")\n        builder.append(\"elements: \")\n\n        var node = head\n        while (node != null) {\n\n            // it's necessary to see the correct node connections\n            if (node.previous() != null) {\n                builder.append(\"- \")\n            }\n\n            builder.append(node.value())\n\n            // it's necessary to see the correct node connections\n            if (node.next() != null) {\n                builder.append(\" -\")\n            }\n\n            node = node.next()\n        }\n\n        return builder.toString()\n    }\n\n    class Node<T>(\n        private var value: T? = null,\n        private var previous: Node<T>? = null,\n        private var next: Node<T>? = null\n    ) {\n\n        fun next() = next\n        fun changeNext(node: Node<T>? = null) {\n            next = node\n        }\n\n        fun previous() = previous\n        fun changePrevious(node: Node<T>? = null) {\n            previous = node\n        }\n\n        fun value() = value\n        fun changeValue(newValue: T?) {\n            value = newValue\n        }\n\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/DynamicArray.kt",
    "content": "package structures\n\nimport java.lang.IllegalStateException\n\n/**\n *\n * Dynamic array or array list is a random access, variable-size list data structure\n *\n * that allows elements to be added or removed, in Java this is java.util.ArrayList\n *\n * P.S. Kotlin lists use under the hood java.util.ArrayList on the JVM\n * \n * Example:\n *\n * 1) val numbers = listOf(1, 2, 3) // java.util.ArrayList\n *\n * 2) val symbols = mutableListOf('a', 'b', 'c') // also java.util.ArrayList\n *     \n */\n\nclass DynamicArray<T>(private var capacity: Int = 10) {\n\n    private var data = arrayOfNulls<Any>(capacity)\n    private var size = 0\n\n    /**\n     * Complexity:\n     * worst time - O(n) because increaseSize() is called\n     * best time - O(1)\n     * average time - O(1)\n     */\n    fun add(value: T) {\n        if (size <= data.size - 1) {\n            data[size] = value\n        } else {\n            increaseSize()\n            data[size] = value\n        }\n        size += 1\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(n)\n     * average time: O(n)\n     */\n    fun remove(value: T) : Boolean {\n        var foundedIndex = -1\n\n        for (i in data.indices) {\n            if (data[i] == value) {\n                foundedIndex = i\n                break\n            }\n        }\n\n        if (foundedIndex == -1) return false\n\n        for (i in foundedIndex until data.size - 1) {\n            data[i] = data[i + 1]\n        }\n\n        size -= 1\n\n        return true\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun contains(value: T): Boolean {\n        for (i in data.indices) {\n            if (data[i] == value) {\n                return true\n            }\n        }\n\n        return false\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun set(index: Int, value: T): T? {\n        if (index !in 0 until size) throw IllegalStateException(\"The index $index is out of bounds!\")\n\n        val oldValue = data[index]\n\n        data[index] = value\n\n        return oldValue as? T\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun get(index: Int) : T {\n        if (index !in data.indices) throw IllegalStateException(\"The index $index is out of bounds!\")\n\n        return data[index] as T\n    }\n\n    override fun toString(): String {\n        val builder = StringBuilder()\n        builder.append(\"capacity: $capacity\\n\")\n        builder.append(\"size: $size\\n\")\n\n        builder.append(\"elements: \")\n        for (i in 0 until size - 1) {\n            builder.append(\"${data[i]}, \")\n        }\n        builder.append(data[size - 1])\n\n        return builder.toString()\n    }\n\n    private fun increaseSize() {\n        capacity = (capacity * INCREASE_SIZE_COEFFICIENT).toInt()\n        val newArray = arrayOfNulls<Any>(capacity)\n        for (i in data.indices) {\n            newArray[i] = data[i]\n        }\n        data = newArray\n    }\n\n    companion object {\n        private const val INCREASE_SIZE_COEFFICIENT = 1.5f\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/Graph.kt",
    "content": "package structures\n\nimport java.util.LinkedList\nimport kotlin.collections.LinkedHashSet\n\n/**\n *\n * Graph is a non-linear data structure consisting of vertices and edges. \n * \n * The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph.\n * \n * 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). \n *\n * Undirected graph is a type of graph where the edges have no specified direction assigned to the them.\n *\n */\n\nclass Graph<T> {\n\n    private val data = linkedMapOf<Vertex<T>, MutableList<Vertex<T>>>()\n\n    // Complexity: O(1)\n    fun addVertex(value: T) {\n        data.putIfAbsent(Vertex(value), mutableListOf())\n    }\n\n    // Complexity: O(n)\n    fun removeVertex(value: T) {\n        val removingVertex = Vertex(value)\n        data.values.forEach { list ->\n            list.remove(removingVertex)\n        }\n        data.remove(removingVertex)\n    }\n\n    // Complexity: O(1)\n    fun addEdge(value1: T, value2: T) {\n        val vertex1 = Vertex(value1)\n        val vertex2 = Vertex(value2)\n        data[vertex1]?.add(vertex2)\n        data[vertex2]?.add(vertex1)\n    }\n\n    // Complexity: O(1)\n    fun removeEdge(value1: T, value2: T) {\n        val vertex1 = Vertex(value1)\n        val vertex2 = Vertex(value2)\n        data[vertex1]?.remove(vertex2)\n        data[vertex2]?.remove(vertex1)\n    }\n\n    // returns the associated vertices with the given vertex value\n    fun connectedVertexes(value: T) = data[Vertex(value)]?.map { it.value } ?: emptyList()\n\n    /**\n     *\n     * Traversal of the graph in depth,\n     *\n     * returns all vertices of the graph\n     *\n     */\n    fun depthFirstTraversal() : List<T> {\n        val firstVertex = data.keys.firstOrNull() ?: return emptyList()\n\n        val visited = LinkedHashSet<T>()\n        val queue = LinkedList<Vertex<T>>()\n        queue.push(firstVertex)\n        while (queue.isNotEmpty()) {\n            val vertex = queue.pollFirst()\n            if (!visited.contains(vertex.value)) {\n                visited.add(vertex.value)\n                queue.addAll(data[vertex] ?: emptyList())\n            }\n        }\n        return visited.toList()\n    }\n\n    /**\n     *\n     * Traversal of the graph in breadth,\n     *\n     * returns all vertices of the graph\n     *\n     */\n    fun breadthFirstTraversal() : List<T> {\n        val firstVertex = data.keys.firstOrNull() ?: return emptyList()\n\n        val visited = LinkedHashSet<T>()\n        val queue = LinkedList<Vertex<T>>()\n        queue.add(firstVertex)\n        visited.add(firstVertex.value)\n        while (queue.isNotEmpty()) {\n            val vertex = queue.pollFirst()\n            data[vertex]?.forEach { connectedVertex ->\n                if (!visited.contains(connectedVertex.value)) {\n                    visited.add(connectedVertex.value)\n                    queue.add(connectedVertex)\n                }\n            }\n        }\n        return visited.toList()\n    }\n\n    private data class Vertex<T>(val value: T)\n\n}\n"
  },
  {
    "path": "src/main/kotlin/structures/GraphWithWeights.kt",
    "content": "package structures\n\n\n/**\n *\n * Graph is a non-linear data structure consisting of vertices and edges.\n *\n * The vertices are sometimes also referred to as nodes and the edges are lines or arcs that connect any two nodes in the graph.\n *\n * 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).\n *\n * Directed graph with weights is a type of graph where the edges have specified direction and weights assigned to the them.\n *\n */\n\nclass GraphWithWeights<T> {\n\n    private val data = linkedMapOf<Vertex<T>, MutableList<VertexConnection<T>>>()\n\n    // Complexity: O(1)\n    fun addVertex(value: T) {\n        data.putIfAbsent(Vertex(value), mutableListOf())\n    }\n\n    // Complexity: O(n)\n    fun removeVertex(value: T) {\n        val removingVertex = Vertex(value)\n        data.values.forEach { connections ->\n            connections.removeIf { it.vertex == removingVertex }\n        }\n        data.remove(removingVertex)\n    }\n\n    // Complexity: O(1)\n    fun addEdge(value1: T, value2: T, cost: Int) {\n        val vertex1 = Vertex(value1)\n        val vertex2 = Vertex(value2)\n        data[vertex1]?.add(VertexConnection(vertex2, cost))\n    }\n\n    // Complexity: O(n)\n    fun removeEdge(value1: T, value2: T) {\n        val vertex1 = Vertex(value1)\n        val vertex2 = Vertex(value2)\n        data[vertex1]?.removeIf { it.vertex == vertex2 }\n    }\n\n    // returns the associated vertices and their weights with the given vertex value\n    fun connectedVertexesWithWeights(value: T) = data[Vertex(value)]?.map { it.toString() }  ?: emptyList()\n\n    /**\n     *\n     * Dijkstra's algorithm,\n     *\n     * returns pairs of a vertex and the minimum weight needed to get to that vertex,\n     *\n     * the starting vertex is the first added\n     *\n     */\n    fun dijkstraAlgorithm(): Map<T, Int> {\n        if (data.isEmpty()) return emptyMap()\n\n        val unvisitedVertexes = linkedMapOf<Vertex<T>, Int>()\n        data.keys.forEach { vertex ->\n            unvisitedVertexes[vertex] = Int.MAX_VALUE\n        }\n\n        val visitedVertexes = linkedMapOf<T, Int>()\n        var minimumCost = 0\n\n        var currentVertex = unvisitedVertexes.keys.first()\n        while(unvisitedVertexes.isNotEmpty()) {\n            val neighbourVertexConnections = data[currentVertex] ?: emptyList()\n            for (neighbourVertexConnection in neighbourVertexConnections) {\n                val neighbourVertex = neighbourVertexConnection.vertex\n                if (!unvisitedVertexes.contains(neighbourVertex)) continue\n\n                val newCost = minimumCost + neighbourVertexConnection.cost\n                val neighbourVertexCost = unvisitedVertexes[neighbourVertex] ?: Int.MAX_VALUE\n                if (neighbourVertexCost > newCost) {\n                    unvisitedVertexes[neighbourVertex] = newCost\n                }\n            }\n            visitedVertexes[currentVertex.value] = minimumCost\n            unvisitedVertexes.remove(currentVertex)\n            val nextUnvisitedEntry = unvisitedVertexes.entries\n                .filter { it.value != Int.MAX_VALUE }\n                .minByOrNull { it.value } ?: return visitedVertexes\n            currentVertex = nextUnvisitedEntry.key\n            minimumCost = nextUnvisitedEntry.value\n        }\n        return visitedVertexes\n    }\n\n    private data class Vertex<T>(val value: T)\n\n    // helper class for defining graph weights\n    private data class VertexConnection<T>(val vertex: Vertex<T>, val cost: Int) {\n        override fun toString(): String = \"vertex -> ${vertex.value}, cost -> $cost\"\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/Matrix.kt",
    "content": "package structures\n\nimport java.lang.IllegalArgumentException\n\nfun matrix(apply: Matrix.() -> Unit): Matrix {\n    val matrix = Matrix()\n    matrix.apply()\n    return matrix\n}\n\n/**\n * Matrix is a rectangular table filled with numbers.\n *\n * For example:\n *   1, 2, 3\n *   4, 5, 6\n *   7, 8, 9\n */\nclass Matrix() {\n\n    private val elements = mutableListOf<Int>()\n    private var columnCount = 0\n    private var rowCount = 0\n\n    private constructor(elements: List<Int>, columnCount: Int, rowCount: Int) : this() {\n        this.elements.addAll(elements)\n        this.columnCount = columnCount\n        this.rowCount = rowCount\n    }\n\n    fun row(vararg rowElements: Int) {\n        if (rowElements.isEmpty()) {\n            return\n        }\n\n        if (rowCount == 0) {\n            columnCount = rowElements.size\n        }\n\n        if (columnCount != rowElements.size) {\n            throw IllegalArgumentException(\"The number of elements in each row must be the same\")\n        }\n\n        elements.addAll(rowElements.toTypedArray())\n\n        rowCount++\n    }\n\n    operator fun plus(value: Int): Matrix {\n        return Matrix(elements.map { it + value }, columnCount, rowCount)\n    }\n\n    operator fun plus(value: Matrix): Matrix {\n        if (rowCount != value.rowCount) throw IllegalArgumentException(\"The number of rows doesn't match\")\n        if (columnCount != value.columnCount) throw IllegalArgumentException(\"The number of columns doesn't match\")\n\n        return Matrix(elements.zip(value.elements) { element1, element2 -> element1 + element2 }, columnCount, rowCount)\n    }\n\n    operator fun minus(value: Int): Matrix {\n        return Matrix(elements.map { it - value }, columnCount, rowCount)\n    }\n\n    operator fun minus(value: Matrix): Matrix {\n        if (rowCount != value.rowCount) throw IllegalArgumentException(\"The number of rows doesn't match\")\n        if (columnCount != value.columnCount) throw IllegalArgumentException(\"The number of columns doesn't match\")\n\n        return Matrix(elements.zip(value.elements) { element1, element2 -> element1 - element2 }, columnCount, rowCount)\n    }\n\n    operator fun times(value: Int): Matrix {\n        return Matrix(elements.map { it * value }, columnCount, rowCount)\n    }\n\n    operator fun times(matrix: Matrix): Matrix {\n        val columnCountMatrix1 = columnCount\n        val rowCountMatrix1 = rowCount\n        val columnCountMatrix2 = matrix.columnCount\n        val rowCountMatrix2 = matrix.rowCount\n\n        if (columnCountMatrix1 != rowCountMatrix2) throw IllegalArgumentException(\"The number of columns of the first matrix doesn't match the number of rows of the second matrix\")\n\n        val newElements = mutableListOf<Int>()\n        for (rowIndexMatrix1 in 0 until rowCountMatrix1) {\n            for (columnIndexMatrix2 in 0 until columnCountMatrix2) {\n                var sum = 0\n                for (sameSizeIndex in 0 until columnCountMatrix1) {\n                    sum += elements[rowIndexMatrix1 * columnCountMatrix1 + sameSizeIndex] * matrix.elements[sameSizeIndex * columnCountMatrix2 + columnIndexMatrix2]\n                }\n                newElements.add(sum)\n            }\n        }\n\n        return Matrix(newElements, columnCountMatrix2, rowCountMatrix1)\n    }\n\n    operator fun div(value: Int): Matrix {\n        return Matrix(elements.map { it / value }, columnCount, rowCount)\n    }\n\n    override fun equals(other: Any?): Boolean {\n        if (other == null) return false\n        if (other !is Matrix) return false\n        if (this === other) return true\n\n        return columnCount == other.columnCount && rowCount == other.rowCount && elements == other.elements\n    }\n\n    override fun hashCode(): Int {\n        var result = elements.hashCode()\n        result = 31 * result + columnCount\n        result = 31 * result + rowCount\n        return result\n    }\n\n    override fun toString(): String {\n        val stringBuilder = StringBuilder(\"\\n\")\n\n        elements.forEachIndexed { index, value ->\n            val floating = if ((index + 1) % columnCount == 0) \"\" else \", \"\n            stringBuilder.append(\"$value$floating\")\n\n            if ((index + 1) % columnCount == 0) {\n                stringBuilder.append(\"\\n\")\n            }\n        }\n\n        return stringBuilder.toString()\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/MaxHeap.kt",
    "content": "package structures\n\nimport java.lang.IllegalArgumentException\n\n/**\n *\n * Max-heap is a binary tree in which each parent is greater than its children\n *\n */\n\nclass MaxHeap(private val maxSize: Int) {\n\n    private val data = IntArray(maxSize + 1) { Int.MIN_VALUE }\n\n    private val root = 1\n    private var size = 0\n\n    val isEmpty: Boolean\n        get() = size == 0\n\n    private val Int.parent\n        get() = this / 2\n\n    private val Int.leftChild\n        get() = this * 2\n\n    private val Int.rightChild\n        get() = this * 2 + 1\n\n    init {\n        if (maxSize <= 0) throw IllegalArgumentException(\"The heap must have maxSize larger than zero\")\n\n        data[0] = Int.MAX_VALUE\n    }\n\n    // Complexity: O(logn)\n    fun add(element: Int) {\n        if (size >= maxSize) throw IllegalStateException(\"The heap is full!\")\n\n        data[++size] = Int.MIN_VALUE\n        set(size, element)\n    }\n\n    // Complexity: O(logn)\n    fun set(index: Int, newValue: Int) {\n        if (index < root || index > maxSize) throw IllegalArgumentException(\"The heap doesn't have the such index: $index!\")\n        if (newValue < data[index]) throw IllegalArgumentException(\"The new value $newValue is less than the previous: ${data[index]}\")\n\n        data[index] = newValue\n\n        var current = index\n        while (current > root && data[current.parent] < data[current]) {\n            swap(current, current.parent)\n            current = current.parent\n        }\n    }\n\n    // Complexity: O(1)\n    fun peekMax() = data[root]\n\n    // Complexity: O(logn)\n    fun popMax(): Int {\n        if (size < 1) throw IllegalStateException(\"The heap is empty!\")\n\n        val max = data[root]\n        data[root] = data[size--]\n        heapify(root)\n        return max\n    }\n\n    private tailrec fun heapify(pos: Int) {\n        val leftChild = pos.leftChild\n        val rightChild = pos.rightChild\n        var largest = pos\n\n        if (leftChild <= size && data[leftChild] > data[largest]) {\n            largest = leftChild\n        }\n\n        if (rightChild <= size && data[rightChild] > data[largest]) {\n            largest = rightChild\n        }\n\n        if (largest != pos) {\n            swap(pos, largest)\n            heapify(largest)\n        }\n    }\n\n    private fun swap(index1: Int, index2: Int) {\n        val tmp = data[index1]\n        data[index1] = data[index2]\n        data[index2] = tmp\n    }\n\n    companion object {\n        fun create(intArray: IntArray): MaxHeap {\n            val arraySize = intArray.size\n            val heap = MaxHeap(arraySize)\n            heap.size = intArray.size\n\n            var index = 0\n            while (index < arraySize) {\n                heap.data[index + 1] = intArray[index]\n                index++\n            }\n\n            var pos = arraySize / 2\n            while (pos >= 0) {\n                heap.heapify(pos)\n                pos--\n            }\n            return heap\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/MinHeap.kt",
    "content": "package structures\n\nimport java.lang.IllegalArgumentException\n\n\n/**\n *\n * Min-heap is a binary tree in which each parent is smaller than its children\n *\n */\n\nclass MinHeap(private val maxSize: Int) {\n\n    private val data = IntArray(maxSize + 1) { Int.MAX_VALUE }\n\n    private val root = 1\n    private var size = 0\n\n    val isEmpty: Boolean\n        get() = size == 0\n\n    private val Int.parent\n        get() = this / 2\n\n    private val Int.leftChild\n        get() = this * 2\n\n    private val Int.rightChild\n        get() = this * 2 + 1\n\n    init {\n        if (maxSize <= 0) throw IllegalArgumentException(\"The heap must have maxSize larger than zero\")\n\n        data[0] = Int.MIN_VALUE\n    }\n\n    // Complexity: O(logn)\n    fun add(element: Int) {\n        if (size >= maxSize) throw IllegalStateException(\"The heap is full!\")\n\n        data[++size] = Int.MAX_VALUE\n        set(size, element)\n    }\n\n    // Complexity: O(logn)\n    fun set(index: Int, newValue: Int) {\n        if (index < root || index > maxSize) throw IllegalArgumentException(\"The heap doesn't have the such index: $index!\")\n        if (newValue > data[index]) throw IllegalArgumentException(\"The new value $newValue is more than the previous: ${data[index]}\")\n\n        data[index] = newValue\n\n        var current = index\n        while (current > root && data[current.parent] > data[current]) {\n            swap(current, current.parent)\n            current = current.parent\n        }\n    }\n\n    // Complexity: O(1)\n    fun peekMin() = data[root]\n\n    // Complexity: O(logn)\n    fun popMin(): Int {\n        if (size < 1) throw IllegalStateException(\"The heap is empty!\")\n\n        val max = data[root]\n        data[root] = data[size--]\n        heapify(root)\n        return max\n    }\n\n    private tailrec fun heapify(pos: Int) {\n        val leftChild = pos.leftChild\n        val rightChild = pos.rightChild\n        var minimum = pos\n\n        if (leftChild <= size && data[leftChild] < data[minimum]) {\n            minimum = leftChild\n        }\n\n        if (rightChild <= size && data[rightChild] < data[minimum]) {\n            minimum = rightChild\n        }\n\n        if (minimum != pos) {\n            swap(pos, minimum)\n            heapify(minimum)\n        }\n    }\n\n    private fun swap(index1: Int, index2: Int) {\n        val tmp = data[index1]\n        data[index1] = data[index2]\n        data[index2] = tmp\n    }\n\n    companion object {\n        fun create(intArray: IntArray): MinHeap {\n            val arraySize = intArray.size\n            val heap = MinHeap(arraySize)\n            heap.size = intArray.size\n\n            var index = 0\n            while (index < arraySize) {\n                heap.data[index + 1] = intArray[index]\n                index++\n            }\n\n            var pos = arraySize / 2\n            while (pos >= 0) {\n                heap.heapify(pos)\n                pos--\n            }\n            return heap\n        }\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/Queue.kt",
    "content": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Queue is a data structure that follows the FIFO (first in, first out) principle\n *\n * LIFO implies that the element that is inserted first, comes out first\n *\n * The main operations:\n *\n * 1) enqueue - inserts an element at the end of the queue\n * 2) dequeue - removes an element from the beginning of the queue\n *\n * All these operations performed in O(1) time.\n *\n */\nclass Queue<T> {\n\n    private val data = LinkedList<T>()\n\n    val isEmpty: Boolean\n        get() = data.isEmpty()\n\n    val size: Int\n        get() = data.size\n\n    fun enqueue(item: T) {\n        data.add(item)\n    }\n\n    fun dequeue(): T {\n        if (isEmpty) throw IllegalStateException(\"The queue is empty\")\n\n        // LinkedList under the hood stores a link to the first element\n        // this operation will be completed in time O(1)\n        return data.removeFirst()\n    }\n\n    fun peek(): T {\n        if (isEmpty) throw IllegalStateException(\"The queue is empty\")\n\n        return data.first\n    }\n\n    fun clear() {\n        data.clear()\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/SingleLinkedList.kt",
    "content": "package structures\n\n/**\n *\n * LinkedList a data structure consisting of a collection of nodes that contain a link to the next/previous node.\n *\n * In the single LinkedList each node contains a link only to the next element\n *\n */\n\nclass SingleLinkedList<T>() {\n\n    private var head: Node<T>? = null\n    private var tail: Node<T>? = null\n\n    private var size: Int = 0\n\n    val isEmpty: Boolean\n        get() = head == null\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun add(index: Int, value: T) : Boolean {\n        if (head == null) return false\n\n        var i = 0\n        var node = head\n        var prevNode = head\n        while (prevNode != null && node != null) {\n            if (i == index) {\n                val newNode = Node(value)\n                newNode.changeNext(node)\n                prevNode.changeNext(newNode)\n                size++\n                return true\n            }\n            i++\n            prevNode = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    fun add(value: T) = addLast(value)\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addFirst(value: T) {\n        val node = Node(value)\n        if (head == null) {\n            head = node\n            tail = node\n        } else {\n            node.changeNext(head)\n            head = node\n        }\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(1)\n     * best time: O(1)\n     * average time: O(1)\n     */\n    fun addLast(value: T) {\n        val node = Node(value)\n        if (head == null) {\n            head = node\n            tail = node\n        } else {\n            tail?.changeNext(node)\n            tail = node\n        }\n        size++\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun contains(value: T) : Boolean {\n        if (head == null) return false\n\n        var node = head\n        while (node != null) {\n            if (node.value() == value) {\n                return true\n            }\n            node = node.next()\n        }\n\n        return false\n    }\n\n    /**\n     * Complexity:\n     * worst time: O(n)\n     * best time: O(1)\n     * average time: O(n)\n     */\n    fun remove(value: T) : Boolean {\n        if (head == null) return false\n\n        var previous: Node<T>? = null\n        var node = head\n\n        while (node != null) {\n            if (node.value() == value) {\n                val nextNode = node.next()\n                previous?.changeNext(nextNode)\n\n                if (head === node) {\n                    head = nextNode\n                }\n\n                if (tail === node) {\n                    tail = previous\n                }\n\n                node.changeNext(null)\n                node.changeValue(null)\n\n                size--\n                return true\n            }\n            previous = node\n            node = node.next()\n        }\n\n        return false\n    }\n\n    // Complexity: O(n)\n    fun clear() {\n        var node = head\n        while (node != null) {\n            val currentNode = node\n\n            node = node.next()\n\n            currentNode.changeNext(null)\n            currentNode.changeValue(null)\n        }\n\n        head = null\n        tail = null\n        size = 0\n    }\n\n    override fun toString(): String {\n        val builder = StringBuilder()\n        builder.append(\"size: $size\\n\")\n        builder.append(\"elements: \")\n\n        var node = head\n        while (node != null) {\n            builder.append(node.value())\n\n            // it's necessary to see the correct node connections\n            if (node.next() != null) {\n                builder.append(\" - \")\n            }\n\n            node = node.next()\n        }\n\n        return builder.toString()\n    }\n\n    class Node<T>(\n        private var value: T? = null,\n        private var next: Node<T>? = null\n    ) {\n\n        fun next() = next\n        fun changeNext(node: Node<T>? = null) {\n            next = node\n        }\n\n        fun value() = value\n        fun changeValue(newValue: T?) {\n            value = newValue\n        }\n\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/Stack1.kt",
    "content": "package structures\n\nimport java.lang.IllegalArgumentException\nimport java.util.ArrayList\n\n/**\n *\n * Stack is a linear data structure that follows the LIFO (last in first out) principle\n *\n * LIFO implies that the element that is inserted last, comes out first.\n *\n * The main operations:\n *\n * 1) push() - when we insert an element in a stack then the operation is known as a push\n * 2) pop() - when we delete an element from the stack, the operation is known as a pop\n *\n * All these operations performed in O(1) time.\n *\n */\n\nclass Stack1<T> {\n    // this implementation uses ArrayList\n    private val data = ArrayList<T>()\n\n    val isEmpty: Boolean\n        get() = data.size == 0\n\n    val size: Int\n        get() = data.size\n\n    fun push(item: T) {\n        data.add(item)\n    }\n\n    fun pop() : T {\n        if (isEmpty) {\n            throw IllegalArgumentException(\"Stack is empty!\")\n        }\n        return data.removeLast()\n    }\n\n    fun peek() : T {\n        if (isEmpty) {\n            throw IllegalArgumentException(\"Stack is empty!\")\n        }\n        return data.last()\n    }\n\n    fun clear() {\n        data.clear()\n    }\n\n}"
  },
  {
    "path": "src/main/kotlin/structures/Stack2.kt",
    "content": "package structures\n\nimport java.util.LinkedList\n\n/**\n *\n * Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle\n *\n * LIFO implies that the element that is inserted last, comes out first.\n *\n * The main operations:\n *\n *     push() - when we insert an element in a stack then the operation is known as a push.\n *     pop() - when we delete an element from the stack, the operation is known as a pop.\n *     If the stack is empty means that no element exists in the stack.\n *\n * All these operations performed in O(1) time.\n *\n */\n\nclass Stack2<T> {\n    // this implementation uses LinkedList\n    private val data = LinkedList<T>()\n\n    val isEmpty: Boolean\n        get() = data.size == 0\n\n    val size: Int\n        get() = data.size\n\n    fun push(item: T) {\n        data.add(item)\n    }\n\n    fun pop(): T {\n        if (isEmpty) {\n            throw IllegalArgumentException(\"Stack is empty!\")\n        }\n        return data.removeLast()\n    }\n\n    fun peek(): T {\n        if (isEmpty) {\n            throw IllegalArgumentException(\"Stack is empty!\")\n        }\n        return data.peekLast()\n    }\n\n    fun clear() {\n        data.clear()\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/TestUtils.kt",
    "content": "\nimport kotlin.random.Random\n\nobject TestUtils {\n\n    fun randomArray(size: Int) =  List(size) { Random.nextInt(100) }.toTypedArray()\n    fun sortedArray(size: Int) = List(size) { it }.toTypedArray()\n\n    fun mutableRandomList(size: Int) = List(size) { Random.nextInt(100) }.toMutableList()\n    fun list(size: Int) = List(size) { it }\n\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/AbstractFactoryTest.kt",
    "content": "package design_patterns\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.core.IsInstanceOf.instanceOf\nimport org.junit.Test\n\ninternal class AbstractFactoryTest {\n\n    @Test\n    fun test() {\n        val iosFactory = IOSButtonFactory()\n\n        val iosButton = iosFactory.createButton()\n        val iosText = iosFactory.createText()\n\n        assertThat(iosButton, instanceOf(IOSButton::class.java))\n        assertThat(iosText, instanceOf(IOSText::class.java))\n\n        val androidFactory = AndroidButtonFactory()\n\n        val androidButton = androidFactory.createButton()\n        val androidText = androidFactory.createText()\n\n        assertThat(androidButton, instanceOf(AndroidButton::class.java))\n        assertThat(androidText, instanceOf(AndroidText::class.java))\n\n        // we can draw iOS and Android components regardless of their implementation\n        listOf(iosButton, androidButton).forEach { it.draw() }\n        listOf(iosText, androidText).forEach { it.draw() }\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/AdapterTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class AdapterTest {\n\n    @Test\n    fun test() {\n        // we don't understand EnglishSpeaker interface\n        val englishSpeaker = EnglishSpeakerImpl()\n        // but we know about SpainSpeaker interface\n        val speakerAdapter = SpainSpeakerAdapter(englishSpeaker)\n\n        // EnglishSpeaker interface was changed to SpainSpeaker interface\n        val actual = speakerAdapter.speakSpanish()\n\n        assertEquals(\"Hola, amigo!\", actual)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/BridgeTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass BridgeTest {\n\n    @Test\n    fun test() {\n        val windowsSystem = WindowsSystem()\n        val macOSSystem = MacOSSystem()\n\n        // the line doesn't know how graphics are implemented in different operating systems\n        val line = GraphicLinePrimitive(0, 0, 100, 100)\n        line.draw(windowsSystem)\n        line.draw(macOSSystem)\n\n        // the circle doesn't know how graphics are implemented in different operating systems\n        val circle = GraphicCirclePrimitive(10, 10, 6)\n        circle.draw(windowsSystem)\n        circle.draw(macOSSystem)\n\n        assertEquals(\"\"\"\n            Windows 10\n            Lines:\n            Windows graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100\n            Circles:\n            Windows graphic subsystem -> centerX: 10, centerY: 10, radius: 6\n        \"\"\".trimIndent(), windowsSystem.toString())\n\n        assertEquals(\"\"\"\n            MacOS 14\n            Lines:\n            MacOS graphic subsystem -> startX: 0, startY: 0, endX: 100, endY: 100\n            Circles:\n            MacOS graphic subsystem -> centerX: 10, centerY: 10, radius: 6\n        \"\"\".trimIndent(), macOSSystem.toString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/BuilderTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BuilderTest {\n\n    @Test\n    fun test_first_variant() {\n        val dnsServerAddress = \"8.8.8.8\"\n        val callTimeout = 500\n        val connectTimeout = 3_000\n        val writeTimeout = 3_000\n        val readTimeout = 3_000\n\n        val httpClient = HttpConnectionClient1.Builder()\n            .dnsServerAddress(dnsServerAddress)\n            .callTimeout(callTimeout)\n            .connectTimeout(connectTimeout)\n            .writeTimeout(writeTimeout)\n            .readTimeout(readTimeout)\n            .build()\n\n        val expected = \"\"\"\n            dns -> $dnsServerAddress\n            call timeout -> $callTimeout\n            connect timeout -> $connectTimeout\n            read timeout -> $readTimeout\n            write timeout -> $writeTimeout\n        \"\"\".trimIndent()\n\n        assertEquals(expected, httpClient.toString())\n    }\n\n    @Test\n    fun test_the_second_variant() {\n        val dnsServerAddress = \"8.8.8.8\"\n        val callTimeout = 500\n        val connectTimeout = 3_000\n        val writeTimeout = 3_000\n        val readTimeout = 3_000\n\n        val httpClient = HttpConnectionClient2.newBuilder()\n            .dnsServerAddress(dnsServerAddress)\n            .callTimeout(callTimeout)\n            .connectTimeout(connectTimeout)\n            .writeTimeout(writeTimeout)\n            .readTimeout(readTimeout)\n            .build()\n\n        val expected = \"\"\"\n            dns -> $dnsServerAddress\n            call timeout -> $callTimeout\n            connect timeout -> $connectTimeout\n            read timeout -> $readTimeout\n            write timeout -> $writeTimeout\n        \"\"\".trimIndent()\n\n        assertEquals(expected, httpClient.toString())\n    }\n\n    @Test\n    fun test_third_variant() {\n        val dnsServerAddress = \"8.8.8.8\"\n        val callTimeout = 500\n        val connectTimeout = 3_000\n        val writeTimeout = 3_000\n        val readTimeout = 3_000\n\n        val httpClient = HttpConnectionClient3(\n            dnsServerAddress = dnsServerAddress,\n            callTimeout = callTimeout,\n            connectTimeout = connectTimeout,\n            readTimeout = readTimeout,\n            writeTimeout = writeTimeout\n        )\n\n        val expected = \"\"\"\n            dns -> $dnsServerAddress\n            call timeout -> $callTimeout\n            connect timeout -> $connectTimeout\n            read timeout -> $readTimeout\n            write timeout -> $writeTimeout\n        \"\"\".trimIndent()\n\n        assertEquals(expected, httpClient.toString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/ChainOfResponsibilitiesTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass ChainOfResponsibilitiesTest {\n\n    @Test\n    fun test_when_we_have_only_stone_pickaxe() {\n        val pickaxe = StonePickaxe()\n\n        assertEquals(true, pickaxe.mine(StoneBlock()))\n        assertEquals(false, pickaxe.mine(DiamondBlock()))\n        assertEquals(false, pickaxe.mine(ObsidianBlock()))\n    }\n\n    @Test\n    fun test_when_we_have_stone_and_iron_pickaxes() {\n        val pickaxe = StonePickaxe()\n        pickaxe.changeNextPickaxe(IronPickaxe())\n\n        assertEquals(true, pickaxe.mine(StoneBlock()))\n        assertEquals(true, pickaxe.mine(DiamondBlock()))\n        assertEquals(false, pickaxe.mine(ObsidianBlock()))\n    }\n\n    @Test\n    fun test_when_we_have_all_three_pickaxes() {\n        val ironPickaxe = IronPickaxe()\n        ironPickaxe.changeNextPickaxe(DiamondPickaxe())\n\n        val stonePickaxe = StonePickaxe()\n        stonePickaxe.changeNextPickaxe(ironPickaxe)\n\n        assertEquals(true, stonePickaxe.mine(StoneBlock()))\n        assertEquals(true, stonePickaxe.mine(DiamondBlock()))\n        assertEquals(true, stonePickaxe.mine(ObsidianBlock()))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/CommandTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class CommandTest {\n\n    @Test\n    fun `test usual commands`() {\n        val stereoSystem = StereoSystem()\n        val remoteControl = StereoSystemRemoteControl(mapOf(\n            \"turnOn\" to TurnOnCommand(stereoSystem),\n            \"turnOff\" to TurnOffCommand(stereoSystem),\n            \"volume+\" to IncreaseVolumeCommand(stereoSystem),\n            \"volume-\" to DecreaseVolumeCommand(stereoSystem)\n        ))\n\n        remoteControl.pressButton(\"turnOn\")\n\n        assertEquals(\"\"\"\n            running status: true\n            volume value: 50\n        \"\"\".trimIndent(), stereoSystem.currentState)\n\n        remoteControl.pressButton(\"volume+\")\n        remoteControl.pressButton(\"volume+\")\n        remoteControl.pressButton(\"volume+\")\n\n        assertEquals(\"\"\"\n            running status: true\n            volume value: 80\n        \"\"\".trimIndent(), stereoSystem.currentState)\n\n        remoteControl.pressUndoButton()\n        remoteControl.pressUndoButton()\n        remoteControl.pressUndoButton()\n        remoteControl.pressUndoButton()\n\n        assertEquals(\"\"\"\n            running status: false\n            volume value: 50\n        \"\"\".trimIndent(), stereoSystem.currentState)\n    }\n\n    @Test\n    fun `test macro command`() {\n        val stereoSystem = StereoSystem()\n        val remoteControl = StereoSystemRemoteControl(mapOf(\n            \"party\" to MacroCommand(\n                TurnOnCommand(stereoSystem),\n                IncreaseVolumeCommand(stereoSystem),\n                IncreaseVolumeCommand(stereoSystem),\n                IncreaseVolumeCommand(stereoSystem),\n                IncreaseVolumeCommand(stereoSystem),\n                IncreaseVolumeCommand(stereoSystem)\n            )\n        ))\n\n        remoteControl.pressButton(\"party\")\n\n        assertEquals(\"\"\"\n            running status: true\n            volume value: 100\n        \"\"\".trimIndent(), stereoSystem.currentState)\n\n        remoteControl.pressUndoButton()\n\n        assertEquals(\"\"\"\n            running status: false\n            volume value: 50\n        \"\"\".trimIndent(), stereoSystem.currentState)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/CompositeTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass CompositeTest {\n\n    @Test\n    fun test() {\n        val menu = Menu(\"Delicious Restaurant\")\n\n        val pizzasMenu = Menu(\"Pizzas\")\n        pizzasMenu.addComponent(MenuItem(\"Cheese pizza\", 10))\n        pizzasMenu.addComponent(MenuItem(\"Pepperoni pizza\", 11))\n        menu.addComponent(pizzasMenu)\n\n        val cakesMenu = Menu(\"Cakes\")\n        cakesMenu.addComponent(MenuItem(\"Chocolate cake\", 13))\n        cakesMenu.addComponent(MenuItem(\"Cheese cake\", 13))\n        menu.addComponent(cakesMenu)\n\n        assertEquals(\"\"\"\n            Menu: Delicious Restaurant\n            Menu: Pizzas\n            title: Cheese pizza\n            price: 10\n            -------------\n            title: Pepperoni pizza\n            price: 11\n            -------------\n            Menu: Cakes\n            title: Chocolate cake\n            price: 13\n            -------------\n            title: Cheese cake\n            price: 13\n            -------------\n        \"\"\".trimIndent(), menu.fetchMenuInformation())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/DecoratorTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass DecoratorTest {\n\n    @Test\n    fun test() {\n        val printer = ExclamationPrinter(\n            WorldPrinter(\n                SpacePrinter(\n                    CommaPrinter(\n                        HelloPrinter()\n                    )\n                )\n            )\n        )\n        assertEquals(\"Hello, World!\", printer.printedText())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/FacadeTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FacadeTest {\n\n    @Test\n    fun test() {\n        val goodsRepository = GoodsRepository(\n            GoodsDatabase(),\n            GoodsNetworkService(),\n            CategoryDatabase(),\n            CategoryNetworkService()\n        )\n\n        val actual = goodsRepository.goodsAndCategories()\n\n        assertEquals(\n            GoodsResult(\n                goods = listOf(GoodsEntity(\n                    id = 1,\n                    name = \"Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software 2nd Edition\",\n                    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.\",\n                    price = 41.94\n                )),\n                categories = listOf(CategoryEntity(\n                    id = 1,\n                    name = \"Books\"\n                ))\n            ),\n            actual\n        )\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/FactoryMethodTest.kt",
    "content": "package design_patterns\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.core.IsInstanceOf.instanceOf\nimport org.junit.Assert.assertEquals\nimport org.junit.Test\n\nclass FactoryMethodTest {\n\n    @Test\n    fun `test WoodenHouseCompany`() {\n        val woodenHouseCompany = WoodenHouseCompany()\n\n        val house1 = woodenHouseCompany.orderHouse(\"77, Brook Ave\", HouseCompany.HouseCompanyCost.CHEAP)\n        assertThat(house1, instanceOf(WoodenCheapHouse::class.java))\n\n        val house2 = woodenHouseCompany.orderHouse(\"77, Brook Ave\", HouseCompany.HouseCompanyCost.AVERAGE)\n        assertThat(house2, instanceOf(WoodenAverageHouse::class.java))\n\n        val house3 = woodenHouseCompany.orderHouse(\"77, Brook Ave\", HouseCompany.HouseCompanyCost.EXPENSIVE)\n        assertThat(house3, instanceOf(WoodenExpensiveHouse::class.java))\n\n        val expected = \"\"\"\n            address = 77, Brook Ave\n            price = 50000\n            \n            address = 77, Brook Ave\n            price = 250000\n            \n            address = 77, Brook Ave\n            price = 1000000\n        \"\"\".trimIndent()\n        assertEquals(expected, woodenHouseCompany.examplesAlreadyBuiltHouses)\n    }\n\n    @Test\n    fun `test StoneHouseCompany`() {\n        val stoneHouseCompany = StoneHouseCompany()\n\n        val house1 = stoneHouseCompany.orderHouse(\"55, Brook Ave\", HouseCompany.HouseCompanyCost.CHEAP)\n        assertThat(house1, instanceOf(StoneCheapHouse::class.java))\n\n        val house2 = stoneHouseCompany.orderHouse(\"55, Brook Ave\", HouseCompany.HouseCompanyCost.AVERAGE)\n        assertThat(house2, instanceOf(StoneAverageHouse::class.java))\n\n        val house3 = stoneHouseCompany.orderHouse(\"55, Brook Ave\", HouseCompany.HouseCompanyCost.EXPENSIVE)\n        assertThat(house3, instanceOf(StoneExpensiveHouse::class.java))\n\n        val expected = \"\"\"\n            address = 55, Brook Ave\n            price = 45000\n            \n            address = 55, Brook Ave\n            price = 230000\n            \n            address = 55, Brook Ave\n            price = 900000\n        \"\"\".trimIndent()\n        assertEquals(expected, stoneHouseCompany.examplesAlreadyBuiltHouses)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/FlyweightTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass FlyweightTest {\n\n    @Test\n    fun test() {\n        val garden = BeautifulGarden()\n\n        garden.placeTree(\"oak\", \"\", 21, 10, 10)\n        garden.placeTree(\"birch\", \"\", 15, 10, 20)\n        garden.placeTree(\"birch\", \"\", 16, 10, 30)\n        garden.placeTree(\"birch\", \"\", 17, 10, 40)\n        garden.placeTree(\"oak\", \"\", 21, 20, 10)\n        garden.placeTree(\"oak\", \"\", 21, 20, 20)\n        garden.placeTree(\"oak\", \"\", 21, 20, 30)\n        garden.placeTree(\"birch\", \"\", 15, 20, 40)\n\n        assertEquals(\"\"\"\n            Beautiful Garden:\n            name: oak, height: 21, x: 10, y: 10\n            name: birch, height: 15, x: 10, y: 20\n            name: birch, height: 16, x: 10, y: 30\n            name: birch, height: 17, x: 10, y: 40\n            name: oak, height: 21, x: 20, y: 10\n            name: oak, height: 21, x: 20, y: 20\n            name: oak, height: 21, x: 20, y: 30\n            name: birch, height: 15, x: 20, y: 40\n            -|-|-|-|-|-|-|-|-|-|-\n        \"\"\".trimIndent(), garden.placedTreesAsString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/InterpreterTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass InterpreterTest {\n\n    @Test\n    fun test() {\n        // x = 10, y = 20, d = 5\n        // sum = x + y\n        // result = sum * d\n        val expression = PerformExpression(\n            SetIntVariableExpression(\"x\", 10),\n            SetIntVariableExpression(\"y\", 20),\n            AddVariablesExpression(\"x\", \"y\", \"sum\"),\n            SetIntVariableExpression(\"d\", 5),\n            MultipleVariablesExpression(\"sum\", \"d\", \"result\")\n        )\n\n        val context = InterpreterContext()\n\n        expression.interpret(context)\n\n        assertEquals(150, context.fetchVariable(\"result\"))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/IteratorTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass IteratorTest {\n\n    @Test\n    fun test() {\n        val presents = arrayOf(\"chocolate cake\", \"snowboard\", \"snowman\")\n        val giftBox = GiftBox(presents)\n        val giftBoxIterator = giftBox.iterator()\n        val actualPresents = mutableListOf<String>()\n        while (giftBoxIterator.hasNext()) {\n            val present = giftBoxIterator.next()\n            actualPresents.add(present)\n        }\n        assertEquals(presents.toList(), actualPresents)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/MediatorTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass MediatorTest {\n\n    @Test\n    fun test() {\n        val manager = SoftwareDevelopmentManager()\n\n        val customer = CustomerSoftwareDevelopmentMember(manager)\n        manager.changeCustomer(customer)\n        val designer = DesignerSoftwareDevelopmentMember(manager)\n        manager.changeDesigner(designer)\n        val programmer = ProgrammerSoftwareDevelopmentMember(manager)\n        manager.changeProgrammer(programmer)\n        val tester = TesterSoftwareDevelopmentMember(manager)\n        manager.changeTester(tester)\n\n        customer.finishWork()\n        designer.finishWork()\n        programmer.finishWork()\n        tester.finishWork()\n\n        assertEquals(\"\"\"\n            Designer accepted the work: design development\n            Programmer accepted the work: writing code\n            Tester accepted the work: application testing\n            Customer accepted the work: business valuation\n        \"\"\".trimIndent(), manager.stagesAsString)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/MementoTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass MementoTest {\n\n    @Test\n    fun test() {\n        // start Android system\n        val androidOS = AndroidSystem()\n\n        val greetingText = \"Hello, World!\"\n        val greetingView = TextView()\n        greetingView.setText(greetingText)\n        greetingView.draw()\n\n        // rotating Android device (recreating application components)\n        // Android system saves the states of running applications\n        androidOS.saveBundle(greetingView.onSaveInstanceState())\n\n        // the state of the text was lost, but we saved it\n        greetingView.setText(\"\")\n\n        // Android device has already rotated\n        // The system restores the states of running applications\n        greetingView.onRestoreInstanceState(androidOS.restoreBundle())\n\n        assertEquals(greetingText, greetingView.text())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/ObserverTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class ObserverTest {\n\n    @Test\n    fun test() {\n        val ponyList = PonyList()\n\n        val observer1 = PonyObserver { items ->\n            assertEquals(listOf(\"Twillight Sparkle\"), items)\n        }\n        ponyList.addObserver(observer1)\n        // we add the first item, observer1 is triggered\n        ponyList.add(\"Twillight Sparkle\")\n        // we remove observer1 so that it is not called again\n        ponyList.removeObserver(observer1)\n\n        val observer2 = PonyObserver { items ->\n            assertEquals(listOf(\"Twillight Sparkle\", \"Starlight Glimmer\"), items)\n        }\n        ponyList.addObserver(observer2)\n        // we add the second item, observer2 is triggered\n        ponyList.add(\"Starlight Glimmer\")\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/PrototypeTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass PrototypeTest {\n\n    @Test\n    fun test() {\n        // we have a list of sweets that need to be made at the confectionery factory\n        val recipesOfSweets = listOf(\n            OreoCookies(\"Original OREO\", \"Rich chocolate cookies with vanilla creme\", 12),\n            OreoCookies(\"Golden OREO\", \"Sweet vanilla cookies with vanilla creme\", 13),\n            OreoCookies(\"OREO Thins\", \"Sweet vanilla cookies with vanilla creme\", 11),\n            `M&MsChocolate`(\"with puffed rice\", 10),\n            `M&MsChocolate`(\"with peanuts\", 11)\n        )\n\n        // we produce sweets according to existing recipes\n        val producedSweets = recipesOfSweets.flatMap { sweets -> List(10) { sweets.copy() } }\n\n        assertEquals(producedSweets.size, 50)\n        assertEquals(producedSweets[9], recipesOfSweets[0])\n        assertEquals(producedSweets[19], recipesOfSweets[1])\n        assertEquals(producedSweets[29], recipesOfSweets[2])\n        assertEquals(producedSweets[39], recipesOfSweets[3])\n        assertEquals(producedSweets[49], recipesOfSweets[4])\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/ProxyTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass ProxyTest {\n\n    @Test\n    fun test() {\n        // we use the proxy object instead of a real one\n        val mediaPlayer = AudioPlayerProxy()\n\n        mediaPlayer.play(\"track_0.mp3\")\n        assertEquals(\"\"\"\n            current audio: track_0.mp3\n            current status: RUNNING\n        \"\"\".trimIndent(), mediaPlayer.currentState)\n\n        mediaPlayer.pause()\n        assertEquals(\"\"\"\n            current audio: track_0.mp3\n            current status: PAUSED\n        \"\"\".trimIndent(), mediaPlayer.currentState)\n\n        mediaPlayer.resume()\n        assertEquals(\"\"\"\n            current audio: track_0.mp3\n            current status: RUNNING\n        \"\"\".trimIndent(), mediaPlayer.currentState)\n\n        mediaPlayer.stop()\n        assertEquals(\"\"\"\n            current audio: \n            current status: NOT_INITIALIZED\n        \"\"\".trimIndent(), mediaPlayer.currentState)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/SingletonTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SingletonTest {\n\n    @Test\n    fun test() {\n        // we have one instance of SQLiteDatabase class\n        SQLiteDatabase.openConnection()\n\n        val actual = SQLiteDatabase.execSQL(\"select * from names\")\n        val expected = listOf(\"Rick\", \"Morty\", \"Jerry\", \"Beth\")\n\n        assertEquals(expected, actual)\n\n        SQLiteDatabase.closeConnection()\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/StateTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass StateTest {\n\n    @Test\n    fun test() {\n        val machine = CocaColaMachine()\n\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n        machine.pressButton()\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n\n        machine.insertDollar()\n        assertEquals(\"HaveDollarCocaColaState\", machine.currentState)\n        machine.takeBackDollar()\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n        machine.takeBackDollar()\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n\n        machine.insertDollar()\n        assertEquals(\"HaveDollarCocaColaState\", machine.currentState)\n        machine.pressButton()\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n\n        machine.insertDollar()\n        assertEquals(\"HaveDollarCocaColaState\", machine.currentState)\n        machine.pressButton()\n        assertEquals(\"NoDollarCocaColaState\", machine.currentState)\n\n        machine.insertDollar()\n        assertEquals(\"HaveDollarCocaColaState\", machine.currentState)\n        machine.pressButton()\n        assertEquals(\"EmptyCocaColaState\", machine.currentState)\n\n        machine.insertDollar()\n        assertEquals(\"EmptyCocaColaState\", machine.currentState)\n\n        machine.loadDrinks(1)\n        machine.insertDollar()\n        assertEquals(\"HaveDollarCocaColaState\", machine.currentState)\n        machine.pressButton()\n        assertEquals(\"EmptyCocaColaState\", machine.currentState)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/StrategyTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class StrategyTest {\n\n    @Test\n    fun test() {\n        val strategy = OnlyChipsFilterStrategy()\n        val foodStore = FoodStore(strategy)\n\n        assertEquals(listOf(\n            FoodEntity(\n                \"Lays Potato Chips Fried Crab Flavor\",\n                2,\n                \"chips\"\n            ),\n            FoodEntity(\n                \"Lay's Potato Chips, Classic\",\n                3,\n                \"chips\"\n            )\n        ), foodStore.foodItems())\n\n        foodStore.changeStrategy(OnlyChocolateFilterStrategy())\n\n        assertEquals(listOf(\n            FoodEntity(\n                \"Dove Chocolate\",\n                3,\n                \"chocolate\"\n            ),\n            FoodEntity(\n                \"Ritter Sport Chocolate\",\n                4,\n                \"chocolate\"\n            )\n        ), foodStore.foodItems())\n\n        foodStore.changeStrategy(PriceFilterStrategy(3))\n\n        assertEquals(listOf(\n            FoodEntity(\n                \"Lay's Potato Chips, Classic\",\n                3,\n                \"chips\"\n            ),\n            FoodEntity(\n                \"Dove Chocolate\",\n                3,\n                \"chocolate\"\n            ),\n            FoodEntity(\n                \"Ritter Sport Chocolate\",\n                4,\n                \"chocolate\"\n            )\n        ), foodStore.foodItems())\n\n        foodStore.changeStrategy(SearchWordFilterStrategy(\"Ritter Sport\"))\n\n        assertEquals(listOf(\n            FoodEntity(\n                \"Ritter Sport Chocolate\",\n                4,\n                \"chocolate\"\n            )\n        ), foodStore.foodItems())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/TemplateMethodTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass TemplateMethodTest {\n\n    @Test\n    fun `test ChocolateCakeBaker`() {\n        val baker = ChocolateCakeBaker()\n\n        val actual = baker.makeCake(3)\n        val expected = Cake(\n            layers = listOf(\n                \"chocolate cake layer\",\n                \"chocolate cake layer\",\n                \"chocolate cake layer\"\n            ),\n            cream = \"chocolate cream\",\n            sprinkles = \"chocolate chips\"\n        )\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun `test WaffleCakeBaker`() {\n        val baker = WaffleCakeBaker()\n\n        val actual = baker.makeCake(3)\n        val expected = Cake(\n            layers = listOf(\n                \"waffle cake layer\",\n                \"waffle cake layer\",\n                \"waffle cake layer\"\n            ),\n            cream = \"custard cream\",\n            sprinkles = \"coconut flakes\"\n        )\n\n        assertEquals(expected, actual)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/design_patterns/VisitorTest.kt",
    "content": "package design_patterns\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class VisitorTest {\n\n    private val expectedJson = \"\"\"\n        [{\n            \"what\" : \"unicorn\",\n            \"name\" : \"Twilight Sparkle\",\n            \"cutie_mark\" : \"star\n        },\n        {\n            \"what\" : \"pegasus\",\n            \"name\" : \"Rainbow Dash\",\n            \"cutie_mark\" : \"lightning\n        },\n        {\n            \"what\" : \"earth pony\",\n            \"name\" : \"Apple Jack\",\n            \"cutie_mark\" : \"apple\n        }]\n    \"\"\".trimIndent()\n\n    private val expectedXml = \"\"\"\n        <ponies>\n        <pony>\n            <what>unicorn</what>\n            <name>Twilight Sparkle</name>\n            <cutie_mark>star</cutie_mark>\n        </pony>\n        <pony>\n            <what>pegasus</what>\n            <name>Rainbow Dash</name>\n            <cutie_mark>lightning</cutie_mark>\n        </pony>\n        <pony>\n            <what>earth pony</what>\n            <name>Apple Jack</name>\n            <cutie_mark>apple</cutie_mark>\n        </pony>\n        </ponies>\n    \"\"\".trimIndent()\n\n    @Test\n    fun test_json_visitor() {\n        val jsonVisitor = JsonVisitor()\n        val twilightSparkle = Unicorn(\"Twilight Sparkle\", \"star\")\n        val rainbowDash = Pegasus(\"Rainbow Dash\", \"lightning\")\n        val appleJack = EarthPony(\"Apple Jack\", \"apple\")\n        val actual = jsonVisitor.visitPonies(twilightSparkle, rainbowDash, appleJack)\n        assertEquals(expectedJson, actual)\n    }\n\n    @Test\n    fun test_xml_visitor() {\n        val xmlVisitor = XmlVisitor()\n        val twilightSparkle = Unicorn(\"Twilight Sparkle\", \"star\")\n        val rainbowDash = Pegasus(\"Rainbow Dash\", \"lightning\")\n        val appleJack = EarthPony(\"Apple Jack\", \"apple\")\n        val actual = xmlVisitor.visitPonies(twilightSparkle, rainbowDash, appleJack)\n        assertEquals(expectedXml, actual)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/BinaryDigitsCounterTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinaryDigitsCounterTest {\n\n    private val counter = BinaryDigitsCounter()\n\n    @Test\n    fun test_empty_string() {\n        val result = counter.compute(\"\")\n\n        assertEquals(BinaryDigitsCounter.Result(), result)\n    }\n\n    @Test\n    fun test_binary_string_1() {\n        val result = counter.compute(\"10101111000\")\n\n        assertEquals(BinaryDigitsCounter.Result(6, 5), result)\n    }\n\n    @Test\n    fun test_binary_string_2() {\n        val result = counter.compute(\"0100000111110010101010\")\n\n        assertEquals(BinaryDigitsCounter.Result(10, 12), result)\n    }\n\n    @Test\n    fun test_binary_string_3() {\n        val result = counter.compute(\"1111111111\")\n\n        assertEquals(BinaryDigitsCounter.Result(10, 0), result)\n    }\n\n    @Test\n    fun test_binary_string_4() {\n        val result = counter.compute(\"0000000000\")\n\n        assertEquals(BinaryDigitsCounter.Result(0, 10), result)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/EuclidAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class EuclidAlgorithmTest {\n\n    private val euclidAlgorithm = EuclidAlgorithm()\n\n    @Test\n    fun `test computeByDivisionWithRemainder`() {\n        assertEquals(5, euclidAlgorithm.computeByDivisionWithRemainder(10, 5))\n        assertEquals(10, euclidAlgorithm.computeByDivisionWithRemainder(10, 100))\n        assertEquals(9, euclidAlgorithm.computeByDivisionWithRemainder(9, 27))\n        assertEquals(13, euclidAlgorithm.computeByDivisionWithRemainder(26, 39))\n        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(135, 13))\n        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(27, 19))\n        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(2, 17))\n        assertEquals(1, euclidAlgorithm.computeByDivisionWithRemainder(4, 9))\n    }\n\n    @Test\n    fun `test computeBySubtraction`() {\n        assertEquals(5, euclidAlgorithm.computeBySubtraction(10, 5))\n        assertEquals(10, euclidAlgorithm.computeBySubtraction(10, 100))\n        assertEquals(9, euclidAlgorithm.computeBySubtraction(9, 27))\n        assertEquals(13, euclidAlgorithm.computeBySubtraction(26, 39))\n        assertEquals(1, euclidAlgorithm.computeBySubtraction(135, 13))\n        assertEquals(1, euclidAlgorithm.computeBySubtraction(27, 19))\n        assertEquals(1, euclidAlgorithm.computeBySubtraction(2, 17))\n        assertEquals(1, euclidAlgorithm.computeBySubtraction(4, 9))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/FactorialAdvancedTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialAdvancedTest {\n\n    private val factorial = FactorialAdvanced()\n\n    @Test\n    fun test_factorial_30() {\n        val actual = factorial.compute(30)\n        assertEquals(\"265252859812191058636308480000000\", actual.toString())\n    }\n\n    @Test\n    fun test_factorial_60() {\n        val actual = factorial.compute(60)\n        assertEquals(\"8320987112741390144276341183223364380754172606361245952449277696409600000000000000\", actual.toString())\n    }\n\n    @Test\n    fun test_factorial_90() {\n        val expected = \"93326215443944152681699238856266700490715968264381621468592963\" +\n                \"895217599993229915608941463976156518286253697920827223758251185210916\" +\n                \"864000000000000000000000000\"\n\n        val actual = factorial.compute(100)\n        assertEquals(expected, actual.toString())\n    }\n\n    @Test\n    fun test_factorial_200() {\n        val expected = \"788657867364790503552363213932185062295135977687173263294742533244359449963403342920304\" +\n                \"2840119846239041772121389196388302576427902426371050619266249528299311134628572707633172373969\" +\n                \"8894392244562145166424025403329186413122742829485327752424240757390324032125740557956866022603\" +\n                \"1904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000\"\n\n        val actual = factorial.compute(200)\n        assertEquals(expected, actual.toString())\n    }\n\n    @Test\n    fun test_factorial_1000() {\n        val expected = \"40238726007709377354370243392300398571937486421071463254379991042993851\" +\n                \"2398629020592044208486969404800479988610197196058631666872994808558901323829669\" +\n                \"9445909974245040870737599188236277271887325197795059509952761208749754624970436\" +\n                \"0141827809464649629105639388743788648733711918104582578364784997701247663288983\" +\n                \"5955735432513185323958463075557409114262417474349347553428646576611667797396668\" +\n                \"8202912073791438537195882498081268678383745597317461360853795345242215865932019\" +\n                \"2809087829730843139284440328123155861103697680135730421616874760967587134831202\" +\n                \"5478589320767169132448426236131412508780208000261683151027341827977704784635868\" +\n                \"1701643650241536913982812648102130927612448963599287051149649754199093422215668\" +\n                \"3257208082133318611681155361583654698404670897560290095053761647584772842188967\" +\n                \"9646244945160765353408198901385442487984959953319101723355556602139450399736280\" +\n                \"7501378376153071277619268490343526252000158885351473316117021039681759215109077\" +\n                \"8801939317811419454525722386554146106289218796022383897147608850627686296714667\" +\n                \"4697562911234082439208160153780889893964518263243671616762179168909779911903754\" +\n                \"0312746222899880051954444142820121873617459926429565817466283029555702990243241\" +\n                \"5318161721046583203678690611726015878352075151628422554026517048330422614397428\" +\n                \"6933061690897968482590125458327168226458066526769958652682272807075781391858178\" +\n                \"8896522081643483448259932660433676601769996128318607883861502794659551311565520\" +\n                \"3609398818061213855860030143569452722420634463179746059468257310379008402443243\" +\n                \"8465657245014402821885252470935190620929023136493273497565513958720559654228749\" +\n                \"7740114133469627154228458623773875382304838656889764619273838149001407673104466\" +\n                \"4025989949022222176590433990188601856652648506179970235619389701786004081188972\" +\n                \"9918311021171229845901641921068884387121855646124960798722908519296819372388642\" +\n                \"6148396573822911231250241866493531439701374285319266498753372189406942814341185\" +\n                \"2015801412334482801505139969429015348307764456909907315243327828826986460278986\" +\n                \"4321139083506217095002597389863554277196742822248757586765752344220207573630569\" +\n                \"4988250879689281627538488633969099598262809561214509948717012445164612603790293\" +\n                \"0912088908694202851064018215439945715680594187274899809425474217358240106367740\" +\n                \"4595741785160829230135358081840096996372524230560855903700624271243416909004153\" +\n                \"6901059339838357779394109700277534720000000000000000000000000000000000000000000\" +\n                \"0000000000000000000000000000000000000000000000000000000000000000000000000000000\" +\n                \"0000000000000000000000000000000000000000000000000000000000000000000000000000000\" +\n                \"000000000000000000000000000000000000000000000000\"\n\n        val actual = factorial.compute(1000)\n        assertEquals(expected, actual.toString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/FactorialBigWithCacheTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialBigWithCacheTest {\n\n    private val factorial = FactorialBigWithCache()\n\n    @Test\n    fun test() {\n        assertEquals(\"30414093201713378043612608166064768844377641568960512000000000000\", factorial.compute(50).toString())\n        assertEquals(\"265252859812191058636308480000000\", factorial.compute(30).toString())\n        assertEquals(\"11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000\", factorial.compute(70).toString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/FactorialTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialTest {\n\n    private val factorial = Factorial()\n\n    @Test\n    fun test_iterative() {\n        assertEquals(1, factorial.compute(0))\n        assertEquals(1, factorial.compute(1))\n        assertEquals(6, factorial.compute(3))\n        assertEquals(120, factorial.compute(5))\n        assertEquals(720, factorial.compute(6))\n    }\n\n    @Test\n    fun test_recursive() {\n        assertEquals(1, factorial.computeRecursive(0))\n        assertEquals(1, factorial.computeRecursive(1))\n        assertEquals(6, factorial.computeRecursive(3))\n        assertEquals(120, factorial.computeRecursive(5))\n        assertEquals(720, factorial.computeRecursive(6))\n    }\n\n    @Test\n    fun test_recursive_with_kotlin_optimization() {\n        assertEquals(1, factorial.computeRecursiveWithKotlinOptimization(0))\n        assertEquals(1, factorial.computeRecursiveWithKotlinOptimization(1))\n        assertEquals(6, factorial.computeRecursiveWithKotlinOptimization(3))\n        assertEquals(120, factorial.computeRecursiveWithKotlinOptimization(5))\n        assertEquals(720, factorial.computeRecursiveWithKotlinOptimization(6))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/FactorialWithCacheTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FactorialWithCacheTest {\n\n    private val factorial = FactorialWithCache()\n\n    @Test\n    fun test() {\n        assertEquals(6, factorial.compute(3))\n        assertEquals(120, factorial.compute(5))\n        assertEquals(720, factorial.compute(6))\n        assertEquals(3628800, factorial.compute(10))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/FizzBuzzTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class FizzBuzzTest {\n\n    private val fizzBuzz = FizzBuzz()\n\n    @Test\n    fun test_fizz() {\n        val actual = fizzBuzz.compute(3)\n        val expected = \"Fizz\"\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_buzz() {\n        val actual = fizzBuzz.compute(5)\n        val expected = \"Buzz\"\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_fizz_buzz() {\n        val actual = fizzBuzz.compute(15)\n        val expected = \"FizzBuzz\"\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun test_no_fizz_buzz() {\n        val actual = fizzBuzz.compute(1)\n        val expected = \"1\"\n        assertEquals(expected, actual)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/KnuthMorrisPrattAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class KnuthMorrisPrattAlgorithmTest {\n\n    @Test\n    fun test() {\n        val knuthMorrisPrattAlgorithm = KnuthMorrisPrattAlgorithm()\n\n        val sentence1 = \"Twillight Sparkle likes reading books!\"\n        assertEquals(true, knuthMorrisPrattAlgorithm.contains(\"Twillight Sparkle\", sentence1))\n        assertEquals(true, knuthMorrisPrattAlgorithm.contains(\"likes\", sentence1))\n        assertEquals(true, knuthMorrisPrattAlgorithm.contains(\"reading\", sentence1))\n        assertEquals(true, knuthMorrisPrattAlgorithm.contains(\"books\", sentence1))\n\n        assertEquals(false, knuthMorrisPrattAlgorithm.contains(\"Apple Jack\", sentence1))\n        assertEquals(false, knuthMorrisPrattAlgorithm.contains(\"loves\", sentence1))\n        assertEquals(false, knuthMorrisPrattAlgorithm.contains(\"learning\", sentence1))\n        assertEquals(false, knuthMorrisPrattAlgorithm.contains(\"articles\", sentence1))\n\n        val sentence2 = \"\"\"\n            Watch the Keynote, livestream replay, and tech talks to hear about the latest updates \n            in Android development directly from the Android team.\n        \"\"\".trimIndent()\n        assertEquals(3, knuthMorrisPrattAlgorithm.count(\"the\", sentence2))\n        assertEquals(2, knuthMorrisPrattAlgorithm.count(\"Android\", sentence2))\n        assertEquals(1, knuthMorrisPrattAlgorithm.count(\"and\", sentence2))\n        assertEquals(1, knuthMorrisPrattAlgorithm.count(\"Keynote\", sentence2))\n\n        assertEquals(0, knuthMorrisPrattAlgorithm.count(\"Kotlin\", sentence2))\n        assertEquals(0, knuthMorrisPrattAlgorithm.count(\"Jetpack Compose\", sentence2))\n        assertEquals(0, knuthMorrisPrattAlgorithm.count(\"Android Studio\", sentence2))\n        assertEquals(0, knuthMorrisPrattAlgorithm.count(\"developers\", sentence2))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/LevenshteinLengthAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class LevenshteinLengthAlgorithmTest {\n\n    @Test\n    fun test() {\n        val levenshteinLengthAlgorithm = LevenshteinLengthAlgorithm()\n\n        val str1 = \"hello\"\n        val str2 = \"hello,\"\n        assertEquals(1, levenshteinLengthAlgorithm.compute(str1, str2))\n\n        val str3 = \"hello, world!\"\n        val str4 = \"hello, friend\"\n        assertEquals(6, levenshteinLengthAlgorithm.compute(str3, str4))\n\n        assertEquals(0, levenshteinLengthAlgorithm.compute(str1, str1))\n        assertEquals(0, levenshteinLengthAlgorithm.compute(str2, str2))\n        assertEquals(0, levenshteinLengthAlgorithm.compute(str3, str3))\n        assertEquals(0, levenshteinLengthAlgorithm.compute(str4, str4))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/MaxAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MaxAlgorithmTest {\n\n    private val maxAlgorithm = MaxAlgorithm()\n\n    @Test\n    fun `test iterative algorithm`() {\n        val actual1 = maxAlgorithm.compute(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))\n        assertEquals(10, actual1)\n\n        val actual2 = maxAlgorithm.compute(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))\n        assertEquals(10, actual2)\n\n        val actual3 = maxAlgorithm.compute(listOf(-50, 10, 6, -100, -9, 110))\n        assertEquals(110, actual3)\n    }\n\n    @Test\n    fun `test recursive algorithm`() {\n        val actual1 = maxAlgorithm.computeRecursive(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))\n        assertEquals(10, actual1)\n\n        val actual2 = maxAlgorithm.computeRecursive(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))\n        assertEquals(10, actual2)\n\n        val actual3 = maxAlgorithm.computeRecursive(listOf(-50, 10, 6, -100, -9, 110))\n        assertEquals(110, actual3)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/MinAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MinAlgorithmTest {\n\n    private val minAlgorithm = MinAlgorithm()\n\n    @Test\n    fun `test iterative algorithm`() {\n        val actual1 = minAlgorithm.compute(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))\n        assertEquals(1, actual1)\n\n        val actual2 = minAlgorithm.compute(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))\n        assertEquals(1, actual2)\n\n        val actual3 = minAlgorithm.compute(listOf(-50, 10, 6, -100, -9, 110))\n        assertEquals(-100, actual3)\n    }\n\n    @Test\n    fun `test recursive algorithm`() {\n        val actual1 = minAlgorithm.computeRecursive(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))\n        assertEquals(1, actual1)\n\n        val actual2 = minAlgorithm.computeRecursive(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))\n        assertEquals(1, actual2)\n\n        val actual3 = minAlgorithm.computeRecursive(listOf(-50, 10, 6, -100, -9, 110))\n        assertEquals(-100, actual3)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/PalindromeAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass PalindromeAlgorithmTest {\n\n    private val palindromeAlgorithm = PalindromeAlgorithm()\n\n    @Test\n    fun `test empty string`() {\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"\"))\n\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"\"))\n    }\n\n    @Test\n    fun `test string with one symbol`() {\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"a\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"b\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"c\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"d\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"e\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"f\"))\n\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"a\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"b\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"c\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"d\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"e\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"f\"))\n\n    }\n\n    @Test\n    fun `test string is palindrome`() {\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"tenet\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"madam\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"racecar\"))\n        assertEquals(true, palindromeAlgorithm.isPalindrome(\"dad\"))\n\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"tenet\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"madam\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"racecar\"))\n        assertEquals(true, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"dad\"))\n    }\n\n    @Test\n    fun `test string is not palindrome`() {\n        assertEquals(false, palindromeAlgorithm.isPalindrome(\"friend\"))\n        assertEquals(false, palindromeAlgorithm.isPalindrome(\"success\"))\n        assertEquals(false, palindromeAlgorithm.isPalindrome(\"mistake\"))\n        assertEquals(false, palindromeAlgorithm.isPalindrome(\"language\"))\n\n        assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"friend\"))\n        assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"success\"))\n        assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"mistake\"))\n        assertEquals(false, palindromeAlgorithm.isPalindromeSimplifiedVersion(\"language\"))\n    }\n\n}\n\n\n"
  },
  {
    "path": "src/test/kotlin/other/ParenthesisCheckAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class ParenthesisCheckAlgorithmTest {\n\n    private val parenthesisCheckAlgorithm = ParenthesisCheckAlgorithm()\n\n    @Test\n    fun `test success`() {\n        // the correct C program\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"\"\"\n            void main() {\n                printf(\"Hello, World!\");\n            }\n        \"\"\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"()\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"{}\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"[]\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"(([[]]))[[]]\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"[[[[((()))]]]]{}{}{}\"))\n        assertEquals(true, parenthesisCheckAlgorithm.check(\"(())()()[][]{{()}}{}\"))\n    }\n\n    @Test\n    fun `test failed`() {\n        // the failed C program\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"\"\"\n            void main({\n                printf(\"Hello, World!\";\n            }\n        \"\"\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"(\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\")\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"{\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"}\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"[\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"]\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"[](){{}\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"[[[]]]{}{})\"))\n        assertEquals(false, parenthesisCheckAlgorithm.check(\"{{{}}}({[}]))[]\"))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/ReverseArrayAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport junit.framework.TestCase.assertEquals\n\ninternal class ReverseArrayAlgorithmTest {\n\n    private val reverseArrayAlgorithm = ReverseArrayAlgorithm()\n\n    @Test\n    fun `test numbers`() {\n        val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n\n        reverseArrayAlgorithm.compute(array)\n\n        assertEquals(listOf(10, 9, 8, 7, 6, 5, 4, 3, 2, 1), array.toList())\n    }\n\n    @Test\n    fun `test strings`() {\n        val array = arrayOf(\"Twillight Sparkle\", \"Pinky Pie\", \"Apple Jack\", \"Rainbow Dash\", \"Fluttershy\", \"Rarity\")\n\n        reverseArrayAlgorithm.compute(array)\n\n        assertEquals(listOf(\"Rarity\", \"Fluttershy\", \"Rainbow Dash\", \"Apple Jack\", \"Pinky Pie\", \"Twillight Sparkle\"), array.toList())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/SieveOfEratosthenesAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SieveOfEratosthenesAlgorithmTest {\n\n    private val eratosthenesAlgorithm = SieveOfEratosthenesAlgorithm()\n\n    @Test\n    fun tes() {\n        assertEquals(emptyList<Int>(), eratosthenesAlgorithm.compute(1))\n        assertEquals(listOf(2, 3, 5, 7), eratosthenesAlgorithm.compute(10))\n        assertEquals(listOf(2, 3, 5, 7, 11, 13, 17, 19), eratosthenesAlgorithm.compute(20))\n        assertEquals(listOf(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37), eratosthenesAlgorithm.compute(40))\n        assertEquals(\n            listOf(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101),\n            eratosthenesAlgorithm.compute(102)\n        )\n        assertEquals(\n            listOf(\n                2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,\n                103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,\n                211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293\n            ),\n            eratosthenesAlgorithm.compute(300)\n        )\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/SqrtTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SqrtTest {\n\n    @Test\n    fun test() {\n        val sqrt = Sqrt()\n        assertEquals(3.0, sqrt.compute(9.0), 0.0)\n        assertEquals(2.0, sqrt.compute(4.0), 0.0)\n        assertEquals(6.0, sqrt.compute(36.0), 0.0)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/StringEqualsHashAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class StringEqualsHashAlgorithmTest {\n\n    private val stringEqualsHashAlgorithm = StringEqualsHashAlgorithm()\n\n    @Test\n    fun test_two_the_same_strings() {\n        val str1 = \"Twilight Sparkle\"\n        val str2 = \"Twilight Sparkle\"\n\n        assertEquals(true, stringEqualsHashAlgorithm.equals(str1, str2))\n    }\n\n    @Test\n    fun test_two_different_strings() {\n        val greeting = \"How are you?\"\n        val pattern = \"Happy birthday to me!\"\n\n        assertEquals(false, stringEqualsHashAlgorithm.equals(greeting, pattern))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/other/SwapAlgorithmTest.kt",
    "content": "package other\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SwapAlgorithmTest {\n\n    private val swapAlgorithm = SwapAlgorithm()\n\n    @Test\n    fun test_list() {\n        val list = mutableListOf(1, 2, 3, 4, 5, 6)\n     \n        swapAlgorithm.swap(list, 0, 5)\n        swapAlgorithm.swap(list, 1, 4)\n        swapAlgorithm.swap(list, 2, 3)\n        \n        assertEquals(listOf(6, 5, 4, 3, 2, 1), list)\n    }\n\n    @Test\n    fun test_array() {\n        val array = arrayOf(1, 2, 3, 4, 5, 6)\n\n        swapAlgorithm.swap(array, 0, 5)\n        swapAlgorithm.swap(array, 1, 4)\n        swapAlgorithm.swap(array, 2, 3)\n        \n        assertEquals(listOf(6, 5, 4, 3, 2, 1), array.toList())\n    }\n\n    @Test\n    fun test_list_kotlin() {\n        val list = mutableListOf(1, 2, 3, 4, 5, 6)\n\n        swapAlgorithm.swapKotlin(list, 0, 5)\n        swapAlgorithm.swapKotlin(list, 1, 4)\n        swapAlgorithm.swapKotlin(list, 2, 3)\n\n        assertEquals(listOf(6, 5, 4, 3, 2, 1), list)\n    }\n\n    @Test\n    fun test_array_kotlin() {\n        val array = arrayOf(1, 2, 3, 4, 5, 6)\n\n        swapAlgorithm.swapKotlin(array, 0, 5)\n        swapAlgorithm.swapKotlin(array, 1, 4)\n        swapAlgorithm.swapKotlin(array, 2, 3)\n\n        assertEquals(listOf(6, 5, 4, 3, 2, 1), array.toList())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/search/BinarySearchTest.kt",
    "content": "package search\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinarySearchTest {\n\n    private val searchAlgo = BinarySearch()\n\n    @Test\n    fun `test search`() {\n        val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n\n        assertEquals(-1, searchAlgo.search(emptyArray(), 0))\n        assertEquals(-1, searchAlgo.search(array, 0))\n        assertEquals(-1, searchAlgo.search(array, 11))\n        assertEquals(0, searchAlgo.search(array, 1))\n        assertEquals(2, searchAlgo.search(array, 3))\n        assertEquals(4, searchAlgo.search(array, 5))\n        assertEquals(6, searchAlgo.search(array, 7))\n        assertEquals(8, searchAlgo.search(array, 9))\n        assertEquals(9, searchAlgo.search(array, 10))\n\n        assertEquals(-1, searchAlgo.searchRecursive(emptyArray(), 0))\n        assertEquals(-1, searchAlgo.searchRecursive(array, 0))\n        assertEquals(-1, searchAlgo.searchRecursive(array, 11))\n        assertEquals(0, searchAlgo.searchRecursive(array, 1))\n        assertEquals(2, searchAlgo.searchRecursive(array, 3))\n        assertEquals(4, searchAlgo.searchRecursive(array, 5))\n        assertEquals(6, searchAlgo.searchRecursive(array, 7))\n        assertEquals(8, searchAlgo.searchRecursive(array, 9))\n        assertEquals(9, searchAlgo.searchRecursive(array, 10))\n    }\n\n    @Test\n    fun `test bounds`() {\n        val array = arrayOf(1, 2, 3, 4, 6, 7, 8, 10)\n        assertEquals(-1, searchAlgo.leftBound(array, 0))\n        assertEquals(-1, searchAlgo.leftBound(array, 1))\n        assertEquals(1, searchAlgo.leftBound(array, 3))\n        assertEquals(3, searchAlgo.leftBound(array, 5))\n        assertEquals(6, searchAlgo.leftBound(array, 10))\n        assertEquals(7, searchAlgo.leftBound(array, 11))\n        assertEquals(7, searchAlgo.leftBound(array, 100))\n\n        assertEquals(0, searchAlgo.rightBound(array, 0))\n        assertEquals(0, searchAlgo.rightBound(array, 1))\n        assertEquals(2, searchAlgo.rightBound(array, 3))\n        assertEquals(4, searchAlgo.rightBound(array, 5))\n        assertEquals(7, searchAlgo.rightBound(array, 10))\n        assertEquals(8, searchAlgo.rightBound(array, 11))\n        assertEquals(8, searchAlgo.rightBound(array, 100))\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/search/LinearSearchTest.kt",
    "content": "package search\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class LinearSearchTest {\n\n    @Test\n    fun test() {\n        val searchAlgo = LinearSearch()\n\n        val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n\n        assertEquals(-1, searchAlgo.search(emptyArray(), 0))\n        assertEquals(-1, searchAlgo.search(array, 0))\n        assertEquals(-1, searchAlgo.search(array, 11))\n        assertEquals(0, searchAlgo.search(array, 1))\n        assertEquals(2, searchAlgo.search(array, 3))\n        assertEquals(4, searchAlgo.search(array, 5))\n        assertEquals(6, searchAlgo.search(array, 7))\n        assertEquals(8, searchAlgo.search(array, 9))\n        assertEquals(9, searchAlgo.search(array, 10))\n    }\n\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/BubbleSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\ninternal class BubbleSortTest {\n\n    private val bubbleSort = BubbleSort()\n\n    @Test\n    fun `test sort`() {\n        val expected1 = Array(1000) { it }\n        val actual1 = expected1.reversedArray()\n        bubbleSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1000) { Random.nextInt(1000) }\n        val expected2 = actual2.sortedArray()\n        bubbleSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        bubbleSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1000) { it }\n        val actual4 = expected3.copyOf()\n        bubbleSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n    @Test\n    fun `test sort improved`() {\n        val expected1 = Array(1000) { it }\n        val actual1 = expected1.reversedArray()\n        bubbleSort.sortImproved(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1000) { Random.nextInt(1000) }\n        val expected2 = actual2.sortedArray()\n        bubbleSort.sortImproved(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        bubbleSort.sortImproved(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1000) { it }\n        val actual4 = expected3.copyOf()\n        bubbleSort.sortImproved(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/CountingSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\n\nclass CountingSortTest {\n\n    @Test\n    fun test() {\n        val countingSort = CountingSort()\n\n        val actual1 = arrayOf(\n            5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 4, 3, 4, 3, 3, 0,\n            0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 5, 3, 2, 2, 1, 1, 0\n        )\n        val expected1 = actual1.sortedArray()\n        countingSort.sort(actual1,0, 5)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = arrayOf(9, 9, 9, 10, 10, 5, 4, 4, 4, 1, 1, 1, 3, 3, 3)\n        val expected2 = actual2.sortedArray()\n        countingSort.sort(actual2, 1, 10)\n        assertArrayEquals(expected2, actual2)\n\n        val actual3 = arrayOf(\n            1000, 1000, 555, 555, 555, 333, 222, 222, 1, 1, 1, 222, 222, 555, 587, 587, 1, 587,\n            1000, 1000, 1000, 6, 7, 6, 7, 7, 7, 6, 1, 1, 222, 555, 587, 3, 3, 3, 1, 3, 3, 6, 6,\n            49, 587, 587, 49, 49, 49, 100, 100, 1000, 100, 1000, 555, 222\n        )\n        val expected3 = actual3.sortedArray()\n        countingSort.sort(actual3, 1, 1000)\n        assertArrayEquals(expected3, actual3)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/InsertionSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\ninternal class InsertionSortTest {\n\n    @Test\n    fun `test sort`() {\n        val insertionSort = InsertionSort()\n\n        val expected1 = Array(1000) { it }\n        val actual1 = expected1.reversedArray()\n        insertionSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1000) { Random.nextInt(1000) }\n        val expected2 = actual2.sortedArray()\n        insertionSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        insertionSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1000) { it }\n        val actual4 = expected3.copyOf()\n        insertionSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/MergeSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass MergeSortTest {\n\n    private val mergeSort = MergeSort()\n\n    @Test\n    fun `test sort`() {\n        val expected1 = Array(1_000_000) { it }\n        val actual1 = expected1.reversedArray()\n        mergeSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) }\n        val expected2 = actual2.sortedArray()\n        mergeSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1_000_000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        mergeSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1_000_000) { it }\n        val actual4 = expected3.copyOf()\n        mergeSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n    @Test\n    fun `test sort recursive`() {\n        val expected1 = Array(1_000_000) { it }\n        val actual1 = expected1.reversedArray()\n        mergeSort.sortRecursive(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) }\n        val expected2 = actual2.sortedArray()\n        mergeSort.sortRecursive(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1_000_000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        mergeSort.sortRecursive(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1_000_000) { it }\n        val actual4 = expected3.copyOf()\n        mergeSort.sortRecursive(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/QuickSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass QuickSortTest {\n\n    @Test\n    fun `test sort`() {\n        val quickSort = QuickSort()\n\n        val expected1 = Array(1_000_000) { it }\n        val actual1 = expected1.reversedArray()\n        quickSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) }\n        val expected2 = actual2.sortedArray()\n        quickSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1_000_000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        quickSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1_000_000) { it }\n        val actual4 = expected3.copyOf()\n        quickSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/RadixSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\nclass RadixSortTest {\n\n    @Test\n    fun test() {\n        val radixSort = RadixSort()\n\n        val expected1 = Array(1_000_000) { it }\n        val actual1 = expected1.reversedArray()\n        radixSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) }\n        val expected2 = actual2.sortedArray()\n        radixSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1_000_000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        radixSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1_000_000) { it }\n        val actual4 = expected3.copyOf()\n        radixSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/SelectionSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport org.junit.Assert.assertArrayEquals\nimport kotlin.random.Random\n\nclass SelectionSortTest {\n\n    @Test\n    fun test() {\n        val selectionSort = SelectionSort()\n\n        val expected1 = Array(1000) { it }\n        val actual1 = expected1.reversedArray()\n        selectionSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1000) { Random.nextInt(1000) }\n        val expected2 = actual2.sortedArray()\n        selectionSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        selectionSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1000) { it }\n        val actual4 = expected3.copyOf()\n        selectionSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/sorting/TimSortTest.kt",
    "content": "package sorting\n\nimport org.junit.Test\nimport kotlin.random.Random\nimport org.junit.Assert.assertArrayEquals\n\nclass TimSortTest {\n\n    @Test\n    fun `test sort`() {\n        val timSort = TimSort()\n\n        val expected1 = Array(1_000_000) { it }\n        val actual1 = expected1.reversedArray()\n        timSort.sort(actual1)\n        assertArrayEquals(expected1, actual1)\n\n        val actual2 = Array(1_000_000) { Random.nextInt(1_000_000) }\n        val expected2 = actual2.sortedArray()\n        timSort.sort(actual2)\n        assertArrayEquals(expected2, actual2)\n\n        val expected3 = Array(1_000_000) { it }\n        val actual3 = expected3.copyOf()\n        actual3.shuffle()\n        timSort.sort(actual3)\n        assertArrayEquals(expected3, actual3)\n\n        val expected4 = Array(1_000_000) { it }\n        val actual4 = expected3.copyOf()\n        timSort.sort(actual3)\n        assertArrayEquals(expected4, actual4)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/BinaryTreeTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class BinaryTreeTest {\n\n    @Test\n    fun `test add`() {\n        val tree = BinaryTree<Int>()\n\n        tree.add(5)\n        tree.add(10)\n        tree.add(4)\n\n        assertEquals(listOf(5, 4, 10), tree.traverseLevelOrder())\n\n        tree.add(9)\n\n        assertEquals(listOf(5, 4, 10, 9), tree.traverseLevelOrder())\n\n        tree.add(1)\n\n        assertEquals(listOf(5, 4, 10, 1, 9), tree.traverseLevelOrder())\n\n        tree.add(11)\n\n        assertEquals(listOf(5, 4, 10, 1, 9, 11), tree.traverseLevelOrder())\n    }\n\n    @Test\n    fun `test remove`() {\n        val tree = BinaryTree<Int>()\n\n        tree.add(10)\n        tree.add(20)\n        tree.add(30)\n\n        assertEquals(listOf(10, 20, 30), tree.traverseLevelOrder())\n        assertEquals(false, tree.isEmpty)\n\n        tree.remove(20)\n\n        assertEquals(listOf(10, 30), tree.traverseLevelOrder())\n        assertEquals(false, tree.isEmpty)\n\n        tree.remove(10)\n\n        assertEquals(listOf(30), tree.traverseLevelOrder())\n        assertEquals(false, tree.isEmpty)\n\n        tree.remove(30)\n\n        assertEquals(emptyList<Int>(), tree.traverseLevelOrder())\n        assertEquals(true, tree.isEmpty)\n    }\n\n    @Test\n    fun `test is empty`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(true, tree.isEmpty)\n\n        tree.add(10)\n\n        assertEquals(false, tree.isEmpty)\n\n        tree.add(20)\n\n        assertEquals(false, tree.isEmpty)\n\n        tree.remove(10)\n\n        assertEquals(false, tree.isEmpty)\n\n        tree.remove(20)\n\n        assertEquals(true, tree.isEmpty)\n    }\n\n    @Test\n    fun `test contains`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(false, tree.contains(5))\n        assertEquals(false, tree.contains(3))\n        assertEquals(false, tree.contains(7))\n\n        tree.add(5)\n        tree.add(3)\n        tree.add(7)\n\n        assertEquals(true, tree.contains(5))\n        assertEquals(true, tree.contains(3))\n        assertEquals(true, tree.contains(7))\n\n        assertEquals(false, tree.contains(2))\n        assertEquals(false, tree.contains(10))\n\n        tree.add(2)\n        tree.add(10)\n\n        assertEquals(true, tree.contains(2))\n        assertEquals(true, tree.contains(10))\n\n        tree.remove(5)\n        tree.remove(3)\n        tree.remove(7)\n        tree.remove(2)\n\n        assertEquals(false, tree.contains(5))\n        assertEquals(false, tree.contains(3))\n        assertEquals(false, tree.contains(7))\n        assertEquals(false, tree.contains(2))\n        assertEquals(true, tree.contains(10))\n    }\n\n    @Test\n    fun `test traverseInOrder`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(emptyList<Int>(), tree.traverseInOrder())\n\n        tree.add(5)\n        tree.add(3)\n        tree.add(8)\n        tree.add(2)\n        tree.add(9)\n\n        assertEquals(listOf(2, 3, 5, 8, 9), tree.traverseInOrder())\n\n        tree.add(1)\n        tree.add(11)\n\n        assertEquals(listOf(1, 2, 3, 5, 8, 9, 11), tree.traverseInOrder())\n\n        tree.add(20)\n        tree.add(30)\n\n        assertEquals(listOf(1, 2, 3, 5, 8, 9, 11, 20, 30), tree.traverseInOrder())\n    }\n\n    @Test\n    fun `test traversePreOrder`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(emptyList<Int>(), tree.traversePreOrder())\n\n        tree.add(5)\n        tree.add(3)\n        tree.add(8)\n        tree.add(2)\n        tree.add(9)\n\n        assertEquals(listOf(5, 3, 2, 8, 9), tree.traversePreOrder())\n\n        tree.add(1)\n        tree.add(11)\n\n        assertEquals(listOf(5, 3, 2, 1, 8, 9, 11), tree.traversePreOrder())\n\n        tree.add(0)\n        tree.add(20)\n\n        assertEquals(listOf(5, 3, 2, 1, 0, 8, 9, 11, 20), tree.traversePreOrder())\n    }\n\n    @Test\n    fun `test traversePostOrder`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(emptyList<Int>(), tree.traversePostOrder())\n\n        tree.add(5)\n        tree.add(3)\n        tree.add(8)\n        tree.add(2)\n        tree.add(9)\n\n        assertEquals(listOf(2, 3, 9, 8, 5), tree.traversePostOrder())\n\n        tree.add(1)\n        tree.add(11)\n\n        assertEquals(listOf(1, 2, 3, 11, 9, 8, 5), tree.traversePostOrder())\n\n        tree.add(0)\n        tree.add(20)\n\n        assertEquals(listOf(0, 1, 2, 3, 20, 11, 9, 8, 5), tree.traversePostOrder())\n    }\n\n    @Test\n    fun `test traverseLevelOrder`() {\n        val tree = BinaryTree<Int>()\n\n        assertEquals(emptyList<Int>(), tree.traverseLevelOrder())\n\n        tree.add(5)\n        tree.add(3)\n        tree.add(8)\n        tree.add(2)\n        tree.add(9)\n\n        assertEquals(listOf(5, 3, 8, 2, 9), tree.traverseLevelOrder())\n\n        tree.add(1)\n        tree.add(11)\n\n        assertEquals(listOf(5, 3, 8, 2, 9, 1, 11), tree.traverseLevelOrder())\n\n        tree.add(0)\n        tree.add(20)\n        tree.add(30)\n\n        assertEquals(listOf(5, 3, 8, 2, 9, 1, 11, 0, 20, 30), tree.traverseLevelOrder())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/CircularLinkedListTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class CircularLinkedListTest {\n\n    @Test\n    fun `test cyclingList`() {\n        val list = CircularLinkedList<Int>()\n\n        list.add(3)\n        list.add(6)\n        list.add(9)\n        list.add(12)\n\n        assertEquals(emptyList<Int>(), list.cyclingList(0))\n        assertEquals(listOf(3, 6, 9, 12), list.cyclingList(1))\n        assertEquals(listOf(\n            3, 6, 9, 12,\n            3, 6, 9, 12\n        ), list.cyclingList(2))\n        assertEquals(listOf(\n            3, 6, 9, 12,\n            3, 6, 9, 12,\n            3, 6, 9, 12\n        ), list.cyclingList(3))\n\n        list.remove(6)\n\n        assertEquals(listOf(\n            3, 9, 12, 3, 9, 12,\n            3, 9, 12, 3, 9, 12,\n            3, 9, 12, 3, 9, 12\n        ), list.cyclingList(6))\n\n        list.remove(9)\n\n        assertEquals(listOf(\n            3, 12, 3, 12, 3, 12,\n            3, 12, 3, 12, 3, 12,\n            3, 12, 3, 12, 3, 12,\n            3, 12, 3, 12, 3, 12\n        ), list.cyclingList(12))\n\n        list.remove(12)\n\n        assertEquals(List(100) { 3 }, list.cyclingList(100))\n\n        list.remove(3)\n\n        assertEquals(emptyList<Int>(), list.cyclingList(0))\n        assertEquals(emptyList<Int>(), list.cyclingList(1))\n        assertEquals(emptyList<Int>(), list.cyclingList(3))\n        assertEquals(emptyList<Int>(), list.cyclingList(1000))\n    }\n\n    @Test\n    fun `test is empty`() {\n        val list = CircularLinkedList<Int>()\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n\n        assertEquals(false, list.isEmpty)\n\n        list.remove(1)\n        list.remove(2)\n        list.remove(3)\n\n        assertEquals(true, list.isEmpty)\n    }\n\n    @Test\n    fun `test add by index`() {\n        val list = CircularLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 1 - 3 - 5 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.add(1, 2)\n        list.add(3, 4)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 - 2 - 3 - 4 - 5 - \n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addFirst`() {\n        val list = CircularLinkedList<Int>()\n\n        list.addFirst(100)\n        list.addFirst(80)\n        list.addFirst(60)\n        list.addFirst(40)\n        list.addFirst(20)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 20 - 40 - 60 - 80 - 100 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(80)\n        list.remove(40)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 20 - 60 - 100 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.addFirst(0)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 0 - 20 - 60 - 100 - \n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addLast`() {\n        val list = CircularLinkedList<Int>()\n\n        list.addLast(100)\n        list.addLast(200)\n        list.addLast(300)\n        list.addLast(400)\n        list.addLast(500)\n        list.addLast(600)\n        list.addLast(700)\n\n        assertEquals(\"\"\"\n            size: 7\n            elements: 100 - 200 - 300 - 400 - 500 - 600 - 700 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(200)\n        list.remove(400)\n        list.remove(600)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 100 - 300 - 500 - 700 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.addLast(900)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 100 - 300 - 500 - 700 - 900 - \n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test contains`() {\n        val list = CircularLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n        list.add(7)\n        list.add(9)\n        list.add(11)\n\n        assertEquals(true, list.contains(1))\n        assertEquals(true, list.contains(5))\n        assertEquals(true, list.contains(9))\n        assertEquals(true, list.contains(11))\n\n        assertEquals(false, list.contains(2))\n        assertEquals(false, list.contains(4))\n        assertEquals(false, list.contains(8))\n        assertEquals(false, list.contains(10))\n\n        list.clear()\n\n        assertEquals(false, list.contains(1))\n        assertEquals(false, list.contains(5))\n        assertEquals(false, list.contains(9))\n        assertEquals(false, list.contains(11))\n    }\n\n    @Test\n    fun `test remove and clear`() {\n        val list = CircularLinkedList<Int>()\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n        list.add(4)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 - 2 - 3 - 4 - 5 - \n        \"\"\".trimIndent(), list.toString())\n\n        assertEquals(true, list.remove(1))\n        assertEquals(true, list.remove(3))\n        assertEquals(true, list.remove(5))\n\n        assertEquals(\"\"\"\n            size: 2\n            elements: 2 - 4 - \n        \"\"\".trimIndent(), list.toString())\n\n        println(list.toString())\n\n        assertEquals(true, list.remove(2))\n\n        println(list.toString())\n\n        assertEquals(true, list.remove(4))\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(6)\n        list.add(7)\n        list.add(11)\n        list.add(13)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 6 - 7 - 11 - 13 - \n        \"\"\".trimIndent(), list.toString())\n\n        list.clear()\n\n        assertEquals(true, list.isEmpty)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/DoubleLinkedListTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class DoubleLinkedListTest {\n\n    @Test\n    fun `test is empty`() {\n        val list = DoubleLinkedList<Int>()\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n\n        assertEquals(false, list.isEmpty)\n\n        list.remove(1)\n        list.remove(2)\n        list.remove(3)\n\n        assertEquals(true, list.isEmpty)\n    }\n\n    @Test\n    fun `test add by index`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 1 -- 3 -- 5\n        \"\"\".trimIndent(), list.toString())\n\n        list.add(1, 2)\n        list.add(3, 4)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 -- 2 -- 3 -- 4 -- 5\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addFirst`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.addFirst(100)\n        list.addFirst(80)\n        list.addFirst(60)\n        list.addFirst(40)\n        list.addFirst(20)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 20 -- 40 -- 60 -- 80 -- 100\n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(80)\n        list.remove(40)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 20 -- 60 -- 100\n        \"\"\".trimIndent(), list.toString())\n\n        list.addFirst(0)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 0 -- 20 -- 60 -- 100\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addLast`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.addLast(100)\n        list.addLast(200)\n        list.addLast(300)\n        list.addLast(400)\n        list.addLast(500)\n        list.addLast(600)\n        list.addLast(700)\n\n        assertEquals(\"\"\"\n            size: 7\n            elements: 100 -- 200 -- 300 -- 400 -- 500 -- 600 -- 700\n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(200)\n        list.remove(400)\n        list.remove(600)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 100 -- 300 -- 500 -- 700\n        \"\"\".trimIndent(), list.toString())\n\n        list.addLast(900)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 100 -- 300 -- 500 -- 700 -- 900\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test contains`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n        list.add(7)\n        list.add(9)\n        list.add(11)\n\n        assertEquals(true, list.contains(1))\n        assertEquals(true, list.contains(5))\n        assertEquals(true, list.contains(9))\n        assertEquals(true, list.contains(11))\n\n        assertEquals(false, list.contains(2))\n        assertEquals(false, list.contains(4))\n        assertEquals(false, list.contains(8))\n        assertEquals(false, list.contains(10))\n\n        list.clear()\n\n        assertEquals(false, list.contains(1))\n        assertEquals(false, list.contains(5))\n        assertEquals(false, list.contains(9))\n        assertEquals(false, list.contains(11))\n    }\n\n    @Test\n    fun `test remove and clear`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n        list.add(4)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 -- 2 -- 3 -- 4 -- 5\n        \"\"\".trimIndent(), list.toString())\n\n        assertEquals(true, list.remove(1))\n        assertEquals(true, list.remove(3))\n        assertEquals(true, list.remove(5))\n\n        assertEquals(\"\"\"\n            size: 2\n            elements: 2 -- 4\n        \"\"\".trimIndent(), list.toString())\n\n        assertEquals(true, list.remove(2))\n        assertEquals(true, list.remove(4))\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(6)\n        list.add(7)\n        list.add(11)\n        list.add(13)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 6 -- 7 -- 11 -- 13\n        \"\"\".trimIndent(), list.toString())\n\n        list.clear()\n\n        assertEquals(true, list.isEmpty)\n    }\n\n    @Test\n    fun `test list and reversedList`() {\n        val list = DoubleLinkedList<Int>()\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n        list.add(4)\n        list.add(5)\n        list.add(6)\n        list.add(7)\n\n        assertEquals(listOf(1, 2, 3, 4, 5, 6, 7), list.list)\n        assertEquals(listOf(7, 6, 5, 4, 3, 2, 1), list.reversedList)\n\n        list.remove(1)\n        list.remove(4)\n        list.remove(7)\n\n        assertEquals(listOf(2, 3, 5, 6), list.list)\n        assertEquals(listOf(6, 5, 3, 2), list.reversedList)\n\n        list.remove(2)\n        list.remove(6)\n\n        assertEquals(listOf(3, 5), list.list)\n        assertEquals(listOf(5, 3), list.reversedList)\n\n        list.clear()\n\n        assertEquals(emptyList<Int>(), list.list)\n        assertEquals(emptyList<Int>(), list.reversedList)\n        assertEquals(true, list.isEmpty)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/DynamicArrayTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class DynamicArrayTest {\n\n    @Test\n    fun test() {\n        val array = DynamicArray<Int>()\n        array.add(1)\n        array.add(2)\n        array.add(3)\n        array.add(4)\n\n        assertEquals(\"\"\"\n            capacity: 10\n            size: 4\n            elements: 1, 2, 3, 4\n        \"\"\".trimIndent(), array.toString())\n\n        assertEquals(1, array.set(0, 10))\n        assertEquals(10, array.get(0))\n\n        assertEquals(2, array.set(1, 20))\n        assertEquals(20, array.get(1))\n\n        assertEquals(3, array.set(2, 30))\n        assertEquals(30, array.get(2))\n\n        assertEquals(4, array.set(3, 40))\n        assertEquals(40, array.get(3))\n\n        assertEquals(true, array.remove(10))\n        assertEquals(true, array.remove(20))\n        assertEquals(true, array.remove(30))\n        assertEquals(true, array.remove(40))\n\n        array.add(1); array.add(2); array.add(3); array.add(4); array.add(5)\n        array.add(6); array.add(7); array.add(8); array.add(9); array.add(10)\n        array.add(11); array.add(12); array.add(13); array.add(14); array.add(15)\n\n        assertEquals(\"\"\"\n            capacity: 20\n            size: 15\n            elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15\n        \"\"\".trimIndent(), array.toString())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/GraphTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class GraphTest {\n\n    @Test\n    fun `test add and remove vertexes`() {\n        val graph = Graph<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n\n        graph.addEdge(10, 20)\n        graph.addEdge(10, 30)\n        graph.addEdge(20, 30)\n\n        assertEquals(listOf(20, 30), graph.connectedVertexes(10))\n        assertEquals(listOf(10, 30), graph.connectedVertexes(20))\n\n        graph.removeVertex(10)\n\n        assertEquals(listOf(20), graph.connectedVertexes(30))\n        assertEquals(listOf(30), graph.connectedVertexes(20))\n\n        graph.removeVertex(20)\n\n        assertEquals(listOf<Int>(), graph.connectedVertexes(30))\n    }\n\n    @Test\n    fun `test remove edges`() {\n        val graph = Graph<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n\n        graph.addEdge(10, 20)\n        graph.addEdge(10, 30)\n        graph.addEdge(20, 30)\n\n        assertEquals(listOf(20, 30), graph.connectedVertexes(10))\n\n        graph.removeEdge(10, 20)\n\n        assertEquals(listOf(30), graph.connectedVertexes(10))\n\n        graph.removeEdge(10, 30)\n\n        assertEquals(listOf<Int>(), graph.connectedVertexes(10))\n        assertEquals(listOf(30), graph.connectedVertexes(20))\n\n        graph.removeEdge(20, 30)\n\n        assertEquals(listOf<Int>(), graph.connectedVertexes(20))\n    }\n\n    @Test\n    fun `test depthFirstTraversal`() {\n        val graph = Graph<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n\n        graph.addEdge(10, 20)\n        graph.addEdge(20, 30)\n        graph.addEdge(30, 10)\n\n        assertEquals(listOf(10, 20, 30), graph.depthFirstTraversal())\n\n        graph.removeVertex(10)\n\n        assertEquals(listOf(20, 30), graph.depthFirstTraversal())\n\n        graph.removeVertex(30)\n\n        assertEquals(listOf(20), graph.depthFirstTraversal())\n\n        graph.removeVertex(20)\n\n        assertEquals(listOf<Int>(), graph.depthFirstTraversal())\n    }\n\n    @Test\n    fun `test breadthFirstTraversal`() {\n        val graph = Graph<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n        graph.addVertex(40)\n\n        graph.addEdge(10, 20)\n        graph.addEdge(20, 30)\n        graph.addEdge(20, 40)\n\n        assertEquals(listOf(10, 20, 30, 40), graph.breadthFirstTraversal())\n\n        graph.removeVertex(10)\n\n        assertEquals(listOf(20, 30, 40), graph.breadthFirstTraversal())\n\n        graph.removeVertex(40)\n\n        assertEquals(listOf(20, 30), graph.breadthFirstTraversal())\n\n        graph.removeVertex(20)\n        graph.removeVertex(30)\n\n        assertEquals(listOf<Int>(), graph.breadthFirstTraversal())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/GraphWithWeightsTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass GraphWithWeightsTest {\n\n    @Test\n    fun `test add and remove vertexes`() {\n        val graph = GraphWithWeights<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n\n        graph.addEdge(10, 20, 1)\n        graph.addEdge(10, 30, 2)\n        graph.addEdge(20, 30, 3)\n\n        assertEquals(listOf(\n            \"vertex -> 20, cost -> 1\",\n            \"vertex -> 30, cost -> 2\"\n        ), graph.connectedVertexesWithWeights(10))\n\n        graph.removeVertex(10)\n\n        assertEquals(listOf<String>(), graph.connectedVertexesWithWeights(10))\n\n        assertEquals(listOf(\"vertex -> 30, cost -> 3\"), graph.connectedVertexesWithWeights(20))\n\n        graph.removeVertex(20)\n\n        assertEquals(listOf<String>(), graph.connectedVertexesWithWeights(10))\n    }\n\n    @Test\n    fun `test remove edges`() {\n        val graph = GraphWithWeights<Int>()\n\n        graph.addVertex(10)\n        graph.addVertex(20)\n        graph.addVertex(30)\n\n        graph.addEdge(10, 20, 1)\n        graph.addEdge(10, 30, 2)\n        graph.addEdge(20, 30, 3)\n\n        assertEquals(listOf(\n            \"vertex -> 20, cost -> 1\",\n            \"vertex -> 30, cost -> 2\"\n        ), graph.connectedVertexesWithWeights(10))\n\n        graph.removeEdge(10, 20)\n\n        assertEquals(listOf(\"vertex -> 30, cost -> 2\"), graph.connectedVertexesWithWeights(10))\n\n        graph.removeEdge(10, 30)\n\n        assertEquals(listOf<String>(), graph.connectedVertexesWithWeights(10))\n        assertEquals(listOf(\"vertex -> 30, cost -> 3\"), graph.connectedVertexesWithWeights(20))\n\n        graph.removeEdge(20, 30)\n\n        assertEquals(listOf<String>(), graph.connectedVertexesWithWeights(10))\n    }\n\n    @Test\n    fun test_dijkstraAlgorithm() {\n        val graph = GraphWithWeights<Int>()\n\n        graph.addVertex(1)\n        graph.addVertex(2)\n        graph.addVertex(3)\n        graph.addVertex(4)\n        graph.addVertex(5)\n\n        graph.addEdge(1, 2, 10)\n        graph.addEdge(1, 5, 100)\n        graph.addEdge(2, 3, 20)\n        graph.addEdge(2, 4, 5)\n        graph.addEdge(3, 4, 15)\n        graph.addEdge(4, 5, 5)\n\n        assertEquals(linkedMapOf(\n            1 to 0,\n            2 to 10,\n            3 to 30,\n            4 to 15,\n            5 to 20\n        ), graph.dijkstraAlgorithm())\n\n        graph.removeVertex(4)\n\n        assertEquals(linkedMapOf(\n            1 to 0,\n            2 to 10,\n            3 to 30,\n            5 to 100\n        ), graph.dijkstraAlgorithm())\n\n        graph.removeVertex(5)\n\n        assertEquals(linkedMapOf(\n            1 to 0,\n            2 to 10,\n            3 to 30\n        ), graph.dijkstraAlgorithm())\n\n        graph.removeVertex(1)\n        graph.removeVertex(2)\n        graph.removeVertex(3)\n\n        assertEquals(mapOf<Int, Int>(), graph.dijkstraAlgorithm())\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/MatrixTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\nimport org.junit.Assert.assertThrows\nimport java.lang.IllegalArgumentException\n\nclass MatrixTest {\n\n    @Test\n    fun `test when number of elements in each row is not the same`() {\n        assertThrows(IllegalArgumentException::class.java) {\n            matrix {\n                row(1, 2, 3)\n                row(4, 5)\n            }\n        }\n    }\n\n    @Test\n    fun `test equals`() {\n        val matrix1 = matrix {\n            row(1, 2, 3)\n            row(4, 5, 6)\n            row(7, 8, 9)\n        }\n\n        val matrix2 = matrix {\n            row(1, 2, 3)\n            row(4, 5, 6)\n            row(7, 8, 9)\n        }\n\n        assertEquals(true, matrix1 == matrix2)\n\n        val matrix3 = matrix {\n            row(1, 2, 3)\n            row(4, 5, 6)\n        }\n\n        assertEquals(false, matrix2 == matrix3)\n    }\n\n    @Test\n    fun `test plus minus a value`() {\n        val matrix1 = matrix {\n            row(4, 7, 2)\n            row(10, 12, 20)\n            row(100, 1000, 8)\n        }\n\n        val expected1 = matrix {\n            row(6, 9, 4)\n            row(12, 14, 22)\n            row(102, 1002, 10)\n        }\n        val actual1 = matrix1 + 2\n\n        assertEquals(expected1, actual1)\n\n        val actual2 = matrix1 - 10\n\n        val expected2 = matrix {\n            row(-6, -3, -8)\n            row(0, 2, 10)\n            row(90, 990, -2)\n        }\n        assertEquals(expected2, actual2)\n    }\n\n    @Test\n    fun `test multiply and div by value`() {\n        val matrix1 = matrix {\n            row(2, 5)\n            row(10, 19)\n        }\n\n        val expected1 = matrix {\n            row(4, 10)\n            row(20, 38)\n        }\n        val actual1 = matrix1 * 2\n\n        assertEquals(expected1, actual1)\n\n        val matrix2 = matrix {\n            row(100, -95, 1200)\n            row(55, 110, -20)\n            row(5, 2, -10)\n        }\n\n        val actual2 = matrix2 / 5\n\n        val expected2 = matrix {\n            row(20, -19, 240)\n            row(11, 22, -4)\n            row(1, 0, -2)\n        }\n        assertEquals(expected2, actual2)\n    }\n\n    @Test\n    fun `test plus between matrices`() {\n        val matrix1 = matrix {\n            row(13, 109)\n            row(8, 6)\n        }\n\n        val matrix2 = matrix {\n            row(9, 34, 2)\n            row(90, 20, 1005)\n        }\n\n        assertThrows(IllegalArgumentException::class.java) {\n            matrix1 + matrix2\n        }\n\n        val matrix3 = matrix {\n            row(20, 30)\n            row(3, 56)\n            row(5, 28)\n        }\n\n        assertThrows(IllegalArgumentException::class.java) {\n            matrix1 + matrix3\n        }\n\n        val matrix4 = matrix {\n            row(7, 1)\n            row(2, 4)\n        }\n\n        val expected = matrix {\n            row(20, 110)\n            row(10, 10)\n        }\n\n        val actual = matrix1 + matrix4\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun `test minus between matrices`() {\n        val matrix1 = matrix {\n            row(13, 109)\n            row(8, 6)\n        }\n\n        val matrix2 = matrix {\n            row(9, 34, 2)\n            row(90, 20, 1005)\n        }\n\n        assertThrows(IllegalArgumentException::class.java) {\n            matrix1 - matrix2\n        }\n\n        val matrix3 = matrix {\n            row(20, 30)\n            row(3, 56)\n            row(5, 28)\n        }\n\n        assertThrows(IllegalArgumentException::class.java) {\n            matrix1 - matrix3\n        }\n\n        val matrix4 = matrix {\n            row(3, 9)\n            row(8, 6)\n        }\n\n        val expected = matrix {\n            row(10, 100)\n            row(0, 0)\n        }\n\n        val actual = matrix1 - matrix4\n\n        assertEquals(expected, actual)\n    }\n\n    @Test\n    fun `test multiply between matrices`() {\n        val matrix1 = matrix {\n            row(1, 2)\n            row(8, 9)\n        }\n        val matrix2 = matrix {\n            row(2)\n            row(4)\n            row(8)\n        }\n\n        assertThrows(IllegalArgumentException::class.java) { matrix1 * matrix2 }\n\n        val matrix3 = matrix {\n            row(1, 4)\n            row(2, 5)\n            row(3, 6)\n        }\n        val matrix4 = matrix {\n            row(7, 8, 9, 10)\n            row(11, 12, 13, 14)\n        }\n\n        val expected1 = matrix {\n            row(51, 56, 61, 66)\n            row(69, 76, 83, 90)\n            row(87, 96, 105, 114)\n        }\n        val actual1 = matrix3 * matrix4\n\n        assertEquals(expected1, actual1)\n\n        val matrix5 = matrix {\n            row(45, 11, 20, -15)\n            row(-12, 9, -18, 0)\n            row(8, 3, -13, 36)\n        }\n        val matrix6 = matrix {\n            row(-1, 8, 55)\n            row(5, -2, 13)\n            row(14, 27, 6)\n            row(19, 3, -10)\n        }\n\n        val expected2 = matrix {\n            row(5, 833, 2888)\n            row(-195, -600, -651)\n            row(509, -185, 41)\n        }\n        val actual2 = matrix5 * matrix6\n\n        assertEquals(expected2, actual2)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/MaxHeapTest.kt",
    "content": "package structures\n\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MaxHeapTest {\n\n    @Test\n    fun `test operations`() {\n        val heap = MaxHeap(10)\n\n        assertEquals(true, heap.isEmpty)\n\n        heap.add(10)\n        heap.add(17)\n        heap.add(20)\n\n        assertEquals(false, heap.isEmpty)\n\n        assertEquals(20, heap.peekMax())\n        assertEquals(20, heap.popMax())\n\n        heap.add(1)\n        heap.add(5)\n\n        assertEquals(17, heap.peekMax())\n        assertEquals(17, heap.popMax())\n\n        assertEquals(10, heap.peekMax())\n        assertEquals(10, heap.popMax())\n\n        heap.set(1, 100)\n\n        assertEquals(100, heap.peekMax())\n        assertEquals(100, heap.popMax())\n\n        assertEquals(1, heap.peekMax())\n        assertEquals(1, heap.popMax())\n\n        assertEquals(true, heap.isEmpty)\n    }\n\n    @Test\n    fun `test creating from array`() {\n        val array = intArrayOf(10, 2, 11, 17, 5, -1, 9, 0)\n\n        val heap = MaxHeap.create(array)\n\n        assertEquals(17, heap.popMax())\n        assertEquals(11, heap.popMax())\n        assertEquals(10, heap.popMax())\n        assertEquals(9, heap.popMax())\n        assertEquals(5, heap.popMax())\n        assertEquals(2, heap.popMax())\n        assertEquals(0, heap.popMax())\n        assertEquals(-1, heap.popMax())\n\n        assertEquals(true, heap.isEmpty)\n\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/MinHeapTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class MinHeapTest {\n\n    @Test\n    fun `test operations`() {\n        val heap = MinHeap(10)\n\n        assertEquals(true, heap.isEmpty)\n\n        heap.add(10)\n        heap.add(17)\n        heap.add(20)\n\n        assertEquals(false, heap.isEmpty)\n\n        assertEquals(10, heap.peekMin())\n        assertEquals(10, heap.popMin())\n\n        heap.add(1)\n        heap.add(5)\n\n        assertEquals(1, heap.peekMin())\n        assertEquals(1, heap.popMin())\n\n        assertEquals(5, heap.peekMin())\n        assertEquals(5, heap.popMin())\n\n        heap.set(1, 15)\n\n        assertEquals(15, heap.peekMin())\n        assertEquals(15, heap.popMin())\n\n        assertEquals(20, heap.peekMin())\n        assertEquals(20, heap.popMin())\n\n        assertEquals(true, heap.isEmpty)\n    }\n\n    @Test\n    fun `test creating from array`() {\n        val array = intArrayOf(10, 2, 11, 17, 5, -1, 9, 0)\n\n        val heap = MinHeap.create(array)\n\n        assertEquals(-1, heap.popMin())\n        assertEquals(0, heap.popMin())\n        assertEquals(2, heap.popMin())\n        assertEquals(5, heap.popMin())\n        assertEquals(9, heap.popMin())\n        assertEquals(10, heap.popMin())\n        assertEquals(11, heap.popMin())\n        assertEquals(17, heap.popMin())\n\n        assertEquals(true, heap.isEmpty)\n\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/QueueTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass QueueTest {\n\n    @Test\n    fun test() {\n        val queue = Queue<Int>()\n\n        assertEquals(true, queue.isEmpty)\n        assertEquals(0, queue.size)\n\n        queue.enqueue(1)\n        assertEquals(1, queue.peek())\n\n        queue.enqueue(2)\n        assertEquals(1, queue.peek())\n\n        queue.enqueue(3)\n        assertEquals(1, queue.peek())\n\n        assertEquals(false, queue.isEmpty)\n        assertEquals(3, queue.size)\n\n        assertEquals(1, queue.dequeue())\n        assertEquals(2, queue.peek())\n\n        assertEquals(2, queue.dequeue())\n        assertEquals(3, queue.peek())\n\n        assertEquals(3, queue.dequeue())\n\n        assertEquals(true, queue.isEmpty)\n        assertEquals(0, queue.size)\n\n        queue.enqueue(10)\n        queue.enqueue(20)\n        queue.enqueue(30)\n\n        assertEquals(false, queue.isEmpty)\n        assertEquals(3, queue.size)\n\n        queue.clear()\n\n        assertEquals(true, queue.isEmpty)\n        assertEquals(0, queue.size)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/SingleLinkedListTest.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\ninternal class SingleLinkedListTest {\n\n    @Test\n    fun `test is empty`() {\n        val list = SingleLinkedList<Int>()\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n\n        assertEquals(false, list.isEmpty)\n\n        list.remove(1)\n        list.remove(2)\n        list.remove(3)\n\n        assertEquals(true, list.isEmpty)\n    }\n\n    @Test\n    fun `test add by index`() {\n        val list = SingleLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 1 - 3 - 5\n        \"\"\".trimIndent(), list.toString())\n\n        list.add(1, 2)\n        list.add(3, 4)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 - 2 - 3 - 4 - 5\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addFirst`() {\n        val list = SingleLinkedList<Int>()\n\n        list.addFirst(100)\n        list.addFirst(80)\n        list.addFirst(60)\n        list.addFirst(40)\n        list.addFirst(20)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 20 - 40 - 60 - 80 - 100\n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(80)\n        list.remove(40)\n\n        assertEquals(\"\"\"\n            size: 3\n            elements: 20 - 60 - 100\n        \"\"\".trimIndent(), list.toString())\n\n        list.addFirst(0)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 0 - 20 - 60 - 100\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test addLast`() {\n        val list = SingleLinkedList<Int>()\n\n        list.addLast(100)\n        list.addLast(200)\n        list.addLast(300)\n        list.addLast(400)\n        list.addLast(500)\n        list.addLast(600)\n        list.addLast(700)\n\n        assertEquals(\"\"\"\n            size: 7\n            elements: 100 - 200 - 300 - 400 - 500 - 600 - 700\n        \"\"\".trimIndent(), list.toString())\n\n        list.remove(200)\n        list.remove(400)\n        list.remove(600)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 100 - 300 - 500 - 700\n        \"\"\".trimIndent(), list.toString())\n\n        list.addLast(900)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 100 - 300 - 500 - 700 - 900\n        \"\"\".trimIndent(), list.toString())\n    }\n\n    @Test\n    fun `test contains`() {\n        val list = SingleLinkedList<Int>()\n\n        list.add(1)\n        list.add(3)\n        list.add(5)\n        list.add(7)\n        list.add(9)\n        list.add(11)\n\n        assertEquals(true, list.contains(1))\n        assertEquals(true, list.contains(5))\n        assertEquals(true, list.contains(9))\n        assertEquals(true, list.contains(11))\n\n        assertEquals(false, list.contains(2))\n        assertEquals(false, list.contains(4))\n        assertEquals(false, list.contains(8))\n        assertEquals(false, list.contains(10))\n\n        list.clear()\n\n        assertEquals(false, list.contains(1))\n        assertEquals(false, list.contains(5))\n        assertEquals(false, list.contains(9))\n        assertEquals(false, list.contains(11))\n    }\n\n    @Test\n    fun `test remove and clear`() {\n        val list = SingleLinkedList<Int>()\n\n        list.add(1)\n        list.add(2)\n        list.add(3)\n        list.add(4)\n        list.add(5)\n\n        assertEquals(\"\"\"\n            size: 5\n            elements: 1 - 2 - 3 - 4 - 5\n        \"\"\".trimIndent(), list.toString())\n\n        assertEquals(true, list.remove(1))\n        assertEquals(true, list.remove(3))\n        assertEquals(true, list.remove(5))\n\n        assertEquals(\"\"\"\n            size: 2\n            elements: 2 - 4\n        \"\"\".trimIndent(), list.toString())\n\n        assertEquals(true, list.remove(2))\n        assertEquals(true, list.remove(4))\n\n        assertEquals(true, list.isEmpty)\n\n        list.add(6)\n        list.add(7)\n        list.add(11)\n        list.add(13)\n\n        assertEquals(\"\"\"\n            size: 4\n            elements: 6 - 7 - 11 - 13\n        \"\"\".trimIndent(), list.toString())\n\n        list.clear()\n\n        assertEquals(true, list.isEmpty)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/Stack1Test.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass Stack1Test {\n\n    @Test\n    fun test() {\n        val stack = Stack1<Int>()\n\n        stack.push(1)\n        stack.push(2)\n        stack.push(3)\n\n        assertEquals(false, stack.isEmpty)\n        assertEquals(3, stack.size)\n\n        assertEquals(3, stack.pop())\n        assertEquals(2, stack.pop())\n        assertEquals(1, stack.pop())\n\n        assertEquals(true, stack.isEmpty)\n        assertEquals(0, stack.size)\n\n        stack.push(10)\n        stack.push(20)\n        stack.push(30)\n\n        assertEquals(3, stack.size)\n        assertEquals(30, stack.peek())\n        assertEquals(3, stack.size)\n\n        stack.clear()\n\n        assertEquals(true, stack.isEmpty)\n        assertEquals(0, stack.size)\n    }\n\n}"
  },
  {
    "path": "src/test/kotlin/structures/Stack2Test.kt",
    "content": "package structures\n\nimport org.junit.Test\nimport org.junit.Assert.assertEquals\n\nclass Stack2Test {\n\n    @Test\n    fun test() {\n        val stack = Stack2<Int>()\n\n        stack.push(1)\n        stack.push(2)\n        stack.push(3)\n\n        assertEquals(false, stack.isEmpty)\n        assertEquals(3, stack.size)\n\n        assertEquals(3, stack.pop())\n        assertEquals(2, stack.pop())\n        assertEquals(1, stack.pop())\n\n        assertEquals(true, stack.isEmpty)\n        assertEquals(0, stack.size)\n\n        stack.push(10)\n        stack.push(20)\n        stack.push(30)\n\n        assertEquals(3, stack.size)\n        assertEquals(30, stack.peek())\n        assertEquals(3, stack.size)\n\n        stack.clear()\n\n        assertEquals(true, stack.isEmpty)\n        assertEquals(0, stack.size)\n    }\n\n}"
  }
]