├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── dictionaries │ └── Mikhail_Glukhikh.xml └── inspectionProfiles │ └── Project_Default.xml ├── License.md ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── input ├── addr_in1.txt ├── addr_in2.txt ├── addr_in3.txt ├── addr_out2.txt ├── addr_out3.txt ├── balda_in1.txt ├── balda_in2.txt ├── balda_in3.txt ├── buysell_in1.txt ├── buysell_in2.txt ├── buysell_in3.txt ├── empty.txt ├── field_in1.txt ├── field_in2.txt ├── field_in3.txt ├── field_in4.txt ├── field_in5.txt ├── field_in6.txt ├── ruslan_ludmila_1.txt ├── ruslan_ludmila_2.txt ├── seq_in1.txt ├── seq_in2.txt ├── seq_in3.txt ├── seq_in4.txt ├── seq_in5.txt ├── temp_in1.txt ├── time_in1.txt ├── time_in2.txt ├── time_in3.txt └── time_out3.txt ├── settings.gradle ├── src ├── lesson1 │ ├── JavaTasks.java │ ├── SortTasks.kt │ ├── Sorts.java │ └── Sorts.kt ├── lesson2 │ ├── Algorithms.kt │ └── JavaAlgorithms.java ├── lesson3 │ ├── BinarySearchTree.java │ ├── CheckableSortedSet.kt │ ├── KtBinarySearchTree.kt │ ├── PositiveSortedSet.kt │ └── SampleIterableCollection.kt ├── lesson4 │ ├── KtTrie.kt │ └── Trie.java ├── lesson5 │ ├── KtOpenAddressingSet.kt │ └── OpenAddressingSet.java ├── lesson6 │ ├── Bridges.kt │ ├── Dijkstra.kt │ ├── Graph.java │ ├── GraphTasks.kt │ ├── JavaGraphTasks.java │ ├── NoughtsAndCrosses.kt │ ├── Voyager.kt │ └── impl │ │ └── Graph.kt ├── lesson7 │ ├── DynamicTasks.kt │ ├── JavaDynamicTasks.java │ ├── fibonacci │ │ └── Fib.kt │ ├── knapsack │ │ └── Knapsack.kt │ └── rod │ │ └── Cut.kt └── lesson8 │ ├── AbstractVoyagingPathSearcher.kt │ ├── HeuristicsTasks.kt │ ├── JavaHeuristicsTasks.java │ ├── annealing │ └── AnnealingVoyagingPathSearcher.kt │ └── genetic │ ├── Chromosome.kt │ └── GeneticVoyagingPathSearcher.kt └── test ├── lesson1 ├── AbstractFileTests.kt ├── AbstractTaskTests.kt ├── SortsTest.java ├── SortsTestKt.kt ├── TaskTestsJava.kt └── TaskTestsKotlin.kt ├── lesson2 ├── AbstractAlgorithmsTests.kt ├── AlgorithmsTestsJava.kt └── AlgorithmsTestsKotlin.kt ├── lesson3 ├── AbstractBinarySearchTreeTest.kt ├── BinarySearchTreeTest.kt ├── KtBinarySearchTreeTest.kt ├── PositiveSortedSetTest.kt └── SampleIterableCollectionTest.kt ├── lesson4 ├── AbstractTrieTest.kt ├── KtTrieTest.kt └── TrieTest.kt ├── lesson5 ├── AbstractOpenAddressingSetTest.kt ├── KtOpenAddressingSetTest.kt └── OpenAddressingSetTest.kt ├── lesson6 ├── AbstractGraphTests.kt ├── BridgesTest.kt ├── DijkstraTest.kt ├── GraphBuilderTest.kt ├── GraphTestsJava.kt ├── GraphTestsKotlin.kt ├── NoughtsAndCrossesTest.kt └── VoyagerTest.kt ├── lesson7 ├── AbstractDynamicTests.kt ├── DynamicTestsJava.kt ├── DynamicTestsKotlin.kt ├── fibonacci │ └── FibTest.kt ├── knapsack │ └── KnapsackTest.kt └── rod │ └── CutTest.kt ├── lesson8 ├── AbstractHeuristicsTests.kt ├── HeuristicsTestsJava.kt ├── HeuristicsTestsKotlin.kt ├── annealing │ └── AnnealingVoyagingPathSearcherTest.kt └── genetic │ ├── ChromosomeTest.kt │ └── GeneticVoyagingPathSearcherTest.kt └── util └── Util.kt /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | 3 | 4 | .gradle 5 | ./gradle 6 | .idea/*.xml 7 | .idea/copyright 8 | .idea/libraries 9 | .idea/shelf 10 | .idea/.name 11 | target 12 | out 13 | build 14 | lib 15 | gradlew 16 | gradlew.bat 17 | 18 | *.iml 19 | *.ipr 20 | *.iws 21 | *.zip 22 | *.log 23 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/dictionaries/Mikhail_Glukhikh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | acmp 5 | balda 6 | heapify 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithms and Data Structures 2 | 3 | This repo contains examples and tasks for the course http://kspt.icc.spbstu.ru/course/algorithms. 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | import java.nio.file.Files 2 | import java.util.stream.Collectors 3 | 4 | buildscript { 5 | repositories { 6 | maven { 7 | url = 'https://maven.polytech.vorpal-research.science' 8 | } 9 | maven { 10 | url = 'https://maven.vorpal-research.science' 11 | } 12 | mavenLocal() 13 | } 14 | dependencies { 15 | classpath 'org.jetbrains.research:kfirst-runner-gradle-plugin:21.0.0' 16 | } 17 | } 18 | 19 | plugins { 20 | id 'java' 21 | id 'org.jetbrains.kotlin.jvm' version '1.5.32' 22 | } 23 | 24 | group 'ru.spbstu' 25 | version '21.0.0-SNAPSHOT' 26 | 27 | java { 28 | sourceCompatibility = JavaVersion.VERSION_16 29 | targetCompatibility = JavaVersion.VERSION_16 30 | } 31 | 32 | repositories { 33 | mavenCentral() 34 | jcenter() 35 | maven { 36 | url = 'https://maven.polytech.vorpal-research.science' 37 | } 38 | maven { 39 | url = 'https://maven.vorpal-research.science' 40 | } 41 | mavenLocal() 42 | } 43 | 44 | dependencies { 45 | implementation "org.jetbrains.kotlin:kotlin-stdlib" 46 | testImplementation "org.jetbrains.research:kfirst-runner:21.0.0" 47 | testImplementation "org.jetbrains.kotlin:kotlin-test" 48 | testImplementation "org.jetbrains.kotlin:kotlin-test-junit5" 49 | testImplementation "org.junit.jupiter:junit-jupiter-api:5.5.1" 50 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.5.1" 51 | testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.5.1" 52 | } 53 | 54 | compileKotlin { 55 | kotlinOptions.jvmTarget = "16" 56 | } 57 | compileTestKotlin { 58 | kotlinOptions.jvmTarget = "16" 59 | } 60 | 61 | compileJava { 62 | options.encoding = 'UTF-8' 63 | sourceCompatibility = JavaVersion.VERSION_16 64 | targetCompatibility = JavaVersion.VERSION_16 65 | } 66 | 67 | test { 68 | useJUnitPlatform() 69 | } 70 | 71 | sourceSets { 72 | main { 73 | java { 74 | srcDirs = ['src'] 75 | } 76 | } 77 | test { 78 | java { 79 | srcDirs = ['test'] 80 | } 81 | } 82 | } 83 | 84 | apply plugin: org.jetbrains.research.runner.KFirstRunnerPlugin 85 | 86 | task kotoedRun( 87 | type: org.jetbrains.research.runner.KFirstRunnerTask, 88 | dependsOn: ['clean', 'testClasses']) { 89 | def testPackages = sourceSets['test'].java.srcDirs.stream() 90 | .flatMap { 91 | dir -> Files.walk(dir.toPath()) 92 | .map { it.toFile() } 93 | .filter { it.isDirectory() } 94 | .map { it.path } 95 | .map { it.substring(dir.path.length()) } 96 | } 97 | .filter { !it.isEmpty() } 98 | .map { it.substring(1) } 99 | .map { it.replace('/', '.').replace('\\', '.') } 100 | .collect(Collectors.toList()) 101 | .sort() 102 | packages = testPackages 103 | } 104 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin-Polytech/Algorithms/357ca45ba64adb331179d0ddf61cada9babf2f76/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /input/addr_in1.txt: -------------------------------------------------------------------------------- 1 | Петров Иван - Железнодорожная 3 2 | Сидоров Петр - Садовая 5 3 | Иванов Алексей - Железнодорожная 7 4 | Сидорова Мария - Садовая 5 5 | Иванов Михаил - Железнодорожная 7 6 | -------------------------------------------------------------------------------- /input/balda_in1.txt: -------------------------------------------------------------------------------- 1 | И Т Ы Н 2 | К Р А Н 3 | А К В А -------------------------------------------------------------------------------- /input/balda_in2.txt: -------------------------------------------------------------------------------- 1 | К Р Б А Д Т 2 | Т В А Л Д А 3 | И И И И И И 4 | Б А Л Д В Ы -------------------------------------------------------------------------------- /input/buysell_in1.txt: -------------------------------------------------------------------------------- 1 | 201 2 | 196 3 | 190 4 | 198 5 | 187 6 | 194 7 | 193 8 | 185 -------------------------------------------------------------------------------- /input/buysell_in2.txt: -------------------------------------------------------------------------------- 1 | 100 2 | 113 3 | 110 4 | 85 5 | 105 6 | 102 7 | 86 8 | 63 9 | 81 10 | 101 11 | 94 12 | 106 13 | 101 14 | 79 15 | 94 -------------------------------------------------------------------------------- /input/buysell_in3.txt: -------------------------------------------------------------------------------- 1 | 10 2 | 11 3 | 7 4 | 10 5 | 6 -------------------------------------------------------------------------------- /input/empty.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kotlin-Polytech/Algorithms/357ca45ba64adb331179d0ddf61cada9babf2f76/input/empty.txt -------------------------------------------------------------------------------- /input/field_in1.txt: -------------------------------------------------------------------------------- 1 | 0 2 3 2 4 1 2 | 1 5 3 4 6 2 3 | 2 6 2 5 1 3 4 | 1 4 3 2 6 2 5 | 4 2 3 1 5 0 6 | -------------------------------------------------------------------------------- /input/field_in2.txt: -------------------------------------------------------------------------------- 1 | 0 1 1 2 | 1 2 0 -------------------------------------------------------------------------------- /input/field_in3.txt: -------------------------------------------------------------------------------- 1 | 0 4 8 4 1 7 4 3 9 2 3 7 2 | 7 2 3 4 9 3 1 3 5 6 3 8 3 | 2 7 4 9 4 5 8 4 3 9 2 5 4 | 9 2 8 3 6 5 7 6 8 7 4 6 5 | 8 7 3 6 4 8 3 2 7 6 5 8 6 | 8 7 4 6 3 5 4 7 4 3 3 7 7 | 3 2 7 5 8 7 5 6 4 8 7 8 8 | 7 8 3 2 3 2 8 7 5 6 2 3 9 | 8 7 5 6 4 3 2 8 4 7 6 7 10 | 3 2 6 4 3 2 9 5 8 7 5 0 -------------------------------------------------------------------------------- /input/field_in4.txt: -------------------------------------------------------------------------------- 1 | 0 2 3 5 6 9 1 2 0 -------------------------------------------------------------------------------- /input/field_in6.txt: -------------------------------------------------------------------------------- 1 | 0 2 | 2 3 | 4 4 | 5 5 | 4 6 | 0 -------------------------------------------------------------------------------- /input/ruslan_ludmila_1.txt: -------------------------------------------------------------------------------- 1 | Дела давно минувших дней, 2 | Преданья старины глубокой. 3 | 4 | В толпе могучих сыновей, 5 | С друзьями, в гриднице высокой 6 | Владимир-солнце пировал; 7 | Меньшую дочь он выдавал 8 | За князя храброго Руслана 9 | И мед из тяжкого стакана 10 | За их здоровье выпивал. 11 | Не скоро ели предки наши, 12 | Не скоро двигались кругом 13 | Ковши, серебряные чаши 14 | С кипящим пивом и вином. 15 | Они веселье в сердце лили, 16 | Шипела пена по краям, 17 | Их важно чашники носили 18 | И низко кланялись гостям. 19 | 20 | Слилися речи в шум невнятный; 21 | Жужжит гостей веселый круг; 22 | Но вдруг раздался глас приятный 23 | И звонких гуслей беглый звук; 24 | Все смолкли, слушают Баяна: 25 | И славит сладостный певец 26 | Людмилу-прелесть, и Руслана, 27 | И Лелем свитый им венец. 28 | 29 | Но, страстью пылкой утомленный, 30 | Не ест, не пьет Руслан влюбленный; 31 | На друга милого глядит, 32 | Вздыхает, сердится, горит 33 | И, щипля ус от нетерпенья, 34 | Считает каждые мгновенья. 35 | В унынье, с пасмурным челом, 36 | За шумным, свадебным столом 37 | Сидят три витязя младые; 38 | Безмолвны, за ковшом пустым, 39 | Забыты кубки круговые, 40 | И брашна неприятны им; 41 | Не слышат вещего Баяна; 42 | Потупили смущенный взгляд: 43 | То три соперника Руслана; 44 | В душе несчастные таят 45 | Любви и ненависти яд. 46 | Один — Рогдай, воитель смелый, 47 | Мечом раздвинувший пределы 48 | Богатых киевских полей; 49 | Другой — Фарлаф, крикун надменный, 50 | В пирах никем не побежденный, 51 | Но воин скромный средь мечей; 52 | Последний, полный страстной думы, 53 | Младой хазарский хан Ратмир: 54 | Все трое бледны и угрюмы, 55 | И пир веселый им не в пир. 56 | 57 | Вот кончен он; встают рядами, 58 | Смешались шумными толпами, 59 | И все глядят на молодых: 60 | Невеста очи опустила, 61 | Как будто сердцем приуныла, 62 | И светел радостный жених. 63 | Но тень объемлет всю природу, 64 | Уж близко к полночи глухой; 65 | Бояре, задремав от меду, 66 | С поклоном убрались домой. 67 | Жених в восторге, в упоенье: 68 | Ласкает он в воображенье 69 | Стыдливой девы красоту; 70 | (с) Этот весь длинный-длинный текст является цитатой из Пушкина, поэма "Руслан и Людмила" 71 | Но с тайным, грустным умиленьем 72 | Великий князь благословеньем 73 | Дарует юную чету. 74 | 75 | И вот невесту молодую 76 | Ведут на брачную постель; 77 | Огни погасли... и ночную 78 | Лампаду зажигает Лель. 79 | Свершились милые надежды, 80 | Любви готовятся дары; 81 | Падут ревнивые одежды 82 | На цареградские ковры... 83 | Вы слышите ль влюбленный шепот, 84 | И поцелуев сладкий звук, 85 | И прерывающийся ропот 86 | Последней робости?.. Супруг 87 | Восторги чувствует заране; 88 | И вот они настали... Вдруг 89 | Гром грянул, свет блеснул в тумане, 90 | Лампада гаснет, дым бежит, 91 | Кругом всё смерклось, всё дрожит, 92 | И замерла душа в Руслане... 93 | Всё смолкло. В грозной тишине 94 | Раздался дважды голос странный, 95 | И кто-то в дымной глубине 96 | Взвился чернее мглы туманной... 97 | И снова терем пуст и тих; 98 | Встает испуганный жених, 99 | С лица катится пот остылый; 100 | Трепеща, хладною рукой 101 | Он вопрошает мрак немой... 102 | О горе: нет подруги милой! 103 | Хватает воздух он пустой; 104 | Людмилы нет во тьме густой, 105 | Похищена безвестной силой. 106 | 107 | Ах, если мученик любви 108 | Страдает страстью безнадежно, 109 | Хоть грустно жить, друзья мои, 110 | Однако жить еще возможно. 111 | 112 | Но после долгих, долгих лет 113 | Обнять влюбленную подругу, 114 | Желаний, слез, тоски предмет, 115 | И вдруг минутную супругу 116 | Навек утратить... о друзья, 117 | Конечно лучше б умер я! 118 | 119 | Однако жив Руслан несчастный. 120 | Но что сказал великий князь? 121 | Сраженный вдруг молвой ужасной, 122 | На зятя гневом распалясь, 123 | Его и двор он созывает: 124 | «Где, где Людмила?» — вопрошает 125 | С ужасным, пламенным челом. 126 | Руслан не слышит. «Дети, други! 127 | Я помню прежние заслуги: 128 | О, сжальтесь вы над стариком! 129 | Скажите, кто из вас согласен 130 | Скакать за дочерью моей? 131 | Чей подвиг будет не напрасен, 132 | Тому — терзайся, плачь, злодей! 133 | Не мог сберечь жены своей! — 134 | Тому я дам ее в супруги 135 | С полцарством прадедов моих. 136 | Кто ж вызовется, дети, други?..» 137 | «Я!» — молвил горестный жених. 138 | «Я! я!» — воскликнули с Рогдаем 139 | Фарлаф и радостный Ратмир: 140 | «Сейчас коней своих седлаем; 141 | Мы рады весь изъездить мир. 142 | Отец наш, не продлим разлуки; 143 | Не бойся: едем за княжной». 144 | И с благодарностью немой 145 | В слезах к ним простирает руки 146 | Старик, измученный тоской. 147 | 148 | Все четверо выходят вместе; 149 | Руслан уныньем как убит; 150 | Мысль о потерянной невесте 151 | Его терзает и мертвит. 152 | 153 | Садятся на коней ретивых; 154 | Вдоль берегов Днепра счастливых 155 | Летят в клубящейся пыли; 156 | Уже скрываются вдали; 157 | Уж всадников не видно боле... 158 | Но долго всё еще глядит 159 | Великий князь в пустое поле 160 | И думой им вослед летит. 161 | 162 | Руслан томился молчаливо, 163 | И смысл и память потеряв. 164 | Через плечо глядя спесиво 165 | И важно подбочась, Фарлаф, 166 | Надувшись, ехал за Русланом. 167 | Он говорит: «Насилу я 168 | На волю вырвался, друзья! 169 | Ну, скоро ль встречусь с великаном? 170 | Уж то-то крови будет течь, 171 | Уж то-то жертв любви ревнивой! 172 | Повеселись, мой верный меч, 173 | Повеселись, мой конь ретивый!» 174 | 175 | Хазарский хан, в уме своем 176 | Уже Людмилу обнимая, 177 | Едва не пляшет над седлом; 178 | В нем кровь играет молодая, 179 | Огня надежды полон взор: 180 | То скачет он во весь опор, 181 | То дразнит бегуна лихого, 182 | Кружит, подъемлет на дыбы 183 | Иль дерзко мчит на холмы снова. 184 | 185 | Рогдай угрюм, молчит — ни слова... 186 | Страшась неведомой судьбы 187 | И мучась ревностью напрасной, 188 | Всех больше беспокоен он, 189 | И часто взор его ужасный 190 | На князя мрачно устремлен. 191 | 192 | Соперники одной дорогой 193 | Все вместе едут целый день. 194 | 195 | Днепра стал темен брег отлогий; 196 | С востока льется ночи тень; 197 | Туманы над Днепром глубоким; 198 | Пора коням их отдохнуть. 199 | Вот под горой путем широким 200 | Широкий пересекся путь. 201 | «Разъедемся, пора! — сказали, — 202 | Безвестной вверимся судьбе». 203 | И каждый конь, не чуя стали, 204 | По воле путь избрал себе. 205 | 206 | Что делаешь, Руслан несчастный, 207 | Один в пустынной тишине? 208 | Людмилу, свадьбы день ужасный, 209 | Всё, мнится, видел ты во сне. 210 | На брови медный шлем надвинув, 211 | Из мощных рук узду покинув, 212 | Ты шагом едешь меж полей, 213 | И медленно в душе твоей 214 | Надежда гибнет, гаснет вера. 215 | 216 | Но вдруг пред витязем пещера; 217 | В пещере свет. Он прямо к ней 218 | Идет под дремлющие своды, 219 | Ровесники самой природы. 220 | Вошел с уныньем: что же зрит? 221 | В пещере старец; ясный вид, 222 | Спокойный взор, брада седая; 223 | Лампада перед ним горит; 224 | За древней книгой он сидит, 225 | Ее внимательно читая. 226 | «Добро пожаловать, мой сын! — 227 | Сказал с улыбкой он Руслану. — 228 | Уж двадцать лет я здесь один 229 | Во мраке старой жизни вяну; 230 | Но наконец дождался дня, 231 | Давно предвиденного мною. 232 | Мы вместе сведены судьбою; 233 | Садись и выслушай меня. 234 | Руслан, лишился ты Людмилы; 235 | Твой твердый дух теряет силы; 236 | 237 | Но зла промчится быстрый миг: 238 | На время рок тебя постиг. 239 | С надеждой, верою веселой 240 | Иди на всё, не унывай; 241 | Вперед! мечом и грудью смелой 242 | Свой путь на полночь пробивай. 243 | 244 | Узнай, Руслан: твой оскорбитель 245 | Волшебник страшный Черномор, 246 | Красавиц давний похититель, 247 | Полнощных обладатель гор. 248 | Еще ничей в его обитель 249 | Не проникал доныне взор; 250 | Но ты, злых козней истребитель, 251 | В нее ты вступишь, и злодей 252 | Погибнет от руки твоей. 253 | Тебе сказать не должен боле: 254 | Судьба твоих грядущих дней, 255 | Мой сын, в твоей отныне воле». 256 | 257 | Наш витязь старцу пал к ногам 258 | И в радости лобзает руку. 259 | Светлеет мир его очам, 260 | И сердце позабыло муку. 261 | Вновь ожил он; и вдруг опять 262 | На вспыхнувшем лице кручина... 263 | «Ясна тоски твоей причина; 264 | Но грусть не трудно разогнать, — 265 | Сказал старик, — тебе ужасна 266 | Любовь седого колдуна; 267 | Спокойся, знай: она напрасна 268 | И юной деве не страшна. 269 | Он звезды сводит с небосклона, 270 | Он свистнет — задрожит луна; 271 | Но против времени закона 272 | Его наука не сильна. 273 | Ревнивый, трепетный хранитель 274 | Замков безжалостных дверей, 275 | Он только немощный мучитель 276 | Прелестной пленницы своей. 277 | -------------------------------------------------------------------------------- /input/ruslan_ludmila_2.txt: -------------------------------------------------------------------------------- 1 | Вокруг нее он молча бродит, 2 | Клянет жестокий жребий свой... 3 | Но, добрый витязь, день проходит, 4 | А нужен для тебя покой». 5 | 6 | Руслан на мягкий мох ложится 7 | Пред умирающим огнем; 8 | Он ищет позабыться сном, 9 | Вздыхает, медленно вертится... 10 | Напрасно! Витязь наконец: 11 | «Не спится что-то, мой отец! 12 | Что делать: болен я душою, 13 | И сон не в сон, как тошно жить. 14 | Позволь мне сердце освежить 15 | Твоей беседою святою. 16 | Прости мне дерзостный вопрос. 17 | Откройся: кто ты, благодатный, 18 | Судьбы наперсник непонятный? 19 | В пустыню кто тебя занес?» 20 | 21 | Вздохнув с улыбкою печальной, 22 | Старик в ответ: «Любезный сын, 23 | Уж я забыл отчизны дальной 24 | Угрюмый край. Природный финн, 25 | В долинах, нам одним известных, 26 | Гоняя стадо сел окрестных, 27 | В беспечной юности я знал 28 | Одни дремучие дубравы, 29 | Ручьи, пещеры наших скал 30 | Да дикой бедности забавы. 31 | Но жить в отрадной тишине 32 | Дано не долго было мне. 33 | 34 | Тогда близ нашего селенья, 35 | Как милый цвет уединенья, 36 | Жила Наина. Меж подруг 37 | Она гремела красотою. 38 | Однажды утренней порою 39 | Свои стада на темный луг 40 | Я гнал, волынку надувая; 41 | Передо мной шумел поток. 42 | 43 | Одна, красавица младая 44 | На берегу плела венок. 45 | Меня влекла моя судьбина... 46 | Ах, витязь, то была Наина! 47 | Я к ней — и пламень роковой 48 | За дерзкий взор мне был наградой, 49 | И я любовь узнал душой 50 | С ее небесною отрадой, 51 | С ее мучительной тоской. 52 | 53 | Умчалась года половина; 54 | Я с трепетом открылся ей, 55 | Сказал: люблю тебя, Наина. 56 | Но робкой горести моей 57 | Наина с гордостью внимала, 58 | Лишь прелести свои любя, 59 | И равнодушно отвечала: 60 | «Пастух, я не люблю тебя!» 61 | 62 | И всё мне дико, мрачно стало: 63 | Родная куща, тень дубров, 64 | Веселы игры пастухов — 65 | Ничто тоски не утешало. 66 | В уныньи сердце сохло, вяло. 67 | И наконец задумал я 68 | Оставить финские поля; 69 | Морей неверные пучины 70 | С дружиной братской переплыть 71 | И бранной славой заслужить 72 | Вниманье гордое Наины. 73 | Я вызвал смелых рыбаков 74 | Искать опасностей и злата. 75 | Впервые тихий край отцов 76 | Услышал бранный звук булата 77 | И шум немирных челноков. 78 | Я вдаль уплыл, надежды полный, 79 | С толпой бесстрашных земляков; 80 | Мы десять лет снега и волны 81 | Багрили кровию врагов. 82 | Молва неслась: цари чужбины 83 | Страшились дерзости моей; 84 | 85 | Их горделивые дружины 86 | Бежали северных мечей. 87 | Мы весело, мы грозно бились, 88 | Делили дани и дары, 89 | И с побежденными садились 90 | За дружелюбные пиры. 91 | Но сердце, полное Наиной, 92 | Под шумом битвы и пиров, 93 | Томилось тайною кручиной, 94 | Искало финских берегов. 95 | Пора домой, сказал я, други! 96 | Повесим праздные кольчуги 97 | Под сенью хижины родной. 98 | Сказал — и весла зашумели; 99 | И, страх оставя за собой, 100 | В залив отчизны дорогой 101 | Мы с гордой радостью влетели. 102 | 103 | Сбылись давнишние мечты, 104 | Сбылися пылкие желанья! 105 | Минута сладкого свиданья, 106 | И для меня блеснула ты! 107 | К ногам красавицы надменной 108 | Принес я меч окровавленный, 109 | Кораллы, злато и жемчуг; 110 | Пред нею, страстью упоенный, 111 | Безмолвным роем окруженный 112 | Ее завистливых подруг, 113 | Стоял я пленником послушным; 114 | Но дева скрылась от меня, 115 | Примолвя с видом равнодушным: 116 | «Герой, я не люблю тебя!» 117 | 118 | К чему рассказывать, мой сын, 119 | Чего пересказать нет силы? 120 | Ах, и теперь один, один, 121 | Душой уснув, в дверях могилы, 122 | Я помню горесть, и порой, 123 | Как о минувшем мысль родится, 124 | По бороде моей седой 125 | Слеза тяжелая катится. 126 | 127 | Но слушай: в родине моей 128 | Между пустынных рыбарей 129 | Наука дивная таится. 130 | Под кровом вечной тишины, 131 | Среди лесов, в глуши далекой 132 | Живут седые колдуны; 133 | К предметам мудрости высокой 134 | Все мысли их устремлены; 135 | Все слышит голос их ужасный, 136 | Что было и что будет вновь, 137 | И грозной воле их подвластны 138 | И гроб и самая любовь. 139 | 140 | И я, любви искатель жадный, 141 | Решился в грусти безотрадной 142 | Наину чарами привлечь 143 | И в гордом сердце девы хладной 144 | Любовь волшебствами зажечь. 145 | Спешил в объятия свободы, 146 | В уединенный мрак лесов; 147 | И там, в ученье колдунов, 148 | Провел невидимые годы. 149 | Настал давно желанный миг, 150 | И тайну страшную природы 151 | Я светлой мыслию постиг: 152 | Узнал я силу заклинаньям. 153 | Венец любви, венец желаньям! 154 | Теперь, Наина, ты моя! 155 | Победа наша, думал я. 156 | Но в самом деле победитель 157 | Был рок, упорный мой гонитель. 158 | 159 | В мечтах надежды молодой, 160 | В восторге пылкого желанья, 161 | Творю поспешно заклинанья, 162 | Зову духов — и в тьме лесной 163 | Стрела промчалась громовая, 164 | Волшебный вихорь поднял вой, 165 | Земля вздрогнула под ногой... 166 | И вдруг сидит передо мной 167 | Старушка дряхлая, седая, 168 | 169 | Глазами впалыми сверкая, 170 | С горбом, с трясучей головой, 171 | Печальной ветхости картина. 172 | Ах, витязь, то была Наина!.. 173 | Я ужаснулся и молчал, 174 | Глазами страшный призрак мерил, 175 | В сомненье всё еще не верил 176 | И вдруг заплакал, закричал: 177 | «Возможно ль! ах, Наина, ты ли! 178 | Наина, где твоя краса? 179 | Скажи, ужели небеса 180 | Тебя так страшно изменили? 181 | Скажи, давно ль, оставя свет, 182 | Расстался я с душой и с милой? 183 | Давно ли?..» «Ровно сорок лет, — 184 | Был девы роковой ответ, — 185 | Сегодня семьдесят мне било. 186 | Что делать, — мне пищит она, — 187 | Толпою годы пролетели. 188 | Прошла моя, твоя весна — 189 | Мы оба постареть успели. 190 | Но, друг, послушай: не беда 191 | Неверной младости утрата. 192 | Конечно, я теперь седа, 193 | Немножко, может быть, горбата; 194 | Не то, что в старину была, 195 | Не так жива, не так мила; 196 | Зато (прибавила болтунья) 197 | Открою тайну: я колдунья!» 198 | 199 | И было в самом деле так. 200 | Немой, недвижный перед нею, 201 | Я совершенный был дурак 202 | Со всей премудростью моею. 203 | 204 | Но вот ужасно: колдовство 205 | Вполне свершилось по несчастью. 206 | Мое седое божество 207 | Ко мне пылало новой страстью. 208 | Скривив улыбкой страшный рот, 209 | Могильным голосом урод 210 | 211 | Бормочет мне любви признанье. 212 | Вообрази мое страданье! 213 | Я трепетал, потупя взор; 214 | Она сквозь кашель продолжала 215 | Тяжелый, страстный разговор: 216 | «Так, сердце я теперь узнала; 217 | Я вижу, верный друг, оно 218 | Для нежной страсти рождено; 219 | Проснулись чувства, я сгораю, 220 | Томлюсь желаньями любви... 221 | Приди в объятия мои... 222 | О милый, милый! умираю...» 223 | 224 | И между тем она, Руслан, 225 | Мигала томными глазами; 226 | И между тем за мой кафтан 227 | Держалась тощими руками; 228 | И между тем — я обмирал, 229 | От ужаса зажмуря очи; 230 | И вдруг терпеть не стало мочи; 231 | Я с криком вырвался, бежал. 232 | (с) Этот весь длинный-длинный текст является цитатой из Пушкина, поэма "Руслан и Людмила" 233 | Она вослед: «О, недостойный! 234 | Ты возмутил мой век спокойный, 235 | Невинной девы ясны дни! 236 | Добился ты любви Наины, 237 | И презираешь — вот мужчины! 238 | Изменой дышат все они! 239 | Увы, сама себя вини; 240 | Он обольстил меня, несчастный! 241 | Я отдалась любови страстной... 242 | Изменник, изверг! о позор! 243 | Но трепещи, девичий вор!» 244 | 245 | Так мы расстались. С этих пор 246 | Живу в моем уединенье 247 | С разочарованной душой; 248 | И в мире старцу утешенье 249 | Природа, мудрость и покой. 250 | Уже зовет меня могила; 251 | Но чувства прежние свои 252 | Еще старушка не забыла 253 | -------------------------------------------------------------------------------- /input/seq_in1.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 2 5 | 3 6 | 1 7 | 2 8 | -------------------------------------------------------------------------------- /input/seq_in2.txt: -------------------------------------------------------------------------------- 1 | 12 2 | 25 3 | 39 4 | 25 5 | 39 6 | 12 7 | 25 8 | 39 9 | 12 -------------------------------------------------------------------------------- /input/seq_in3.txt: -------------------------------------------------------------------------------- 1 | 12345000 2 | 25986000 3 | 39234000 4 | 25986000 5 | 39234000 6 | 12345000 7 | 25986000 8 | 39234000 9 | 12345000 -------------------------------------------------------------------------------- /input/seq_in4.txt: -------------------------------------------------------------------------------- 1 | 78 2 | 32 3 | 13 4 | 25 5 | 49 6 | 32 7 | 85 8 | 25 9 | 91 10 | 41 -------------------------------------------------------------------------------- /input/seq_in5.txt: -------------------------------------------------------------------------------- 1 | 78 2 | 32 3 | 13 4 | 45 5 | 49 6 | 32 7 | 85 8 | 45 9 | 91 10 | 41 -------------------------------------------------------------------------------- /input/temp_in1.txt: -------------------------------------------------------------------------------- 1 | 24.7 2 | -12.6 3 | 121.3 4 | -98.4 5 | 99.5 6 | -12.6 7 | 11.0 8 | -------------------------------------------------------------------------------- /input/time_in1.txt: -------------------------------------------------------------------------------- 1 | 01:15:19 PM 2 | 07:26:57 AM 3 | 10:00:03 AM 4 | 07:56:14 PM 5 | 01:15:19 PM 6 | 12:40:31 AM 7 | -------------------------------------------------------------------------------- /input/time_in2.txt: -------------------------------------------------------------------------------- 1 | 12:00:00 AM 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenCentral() 4 | 5 | maven { 6 | url 'https://plugins.gradle.org/m2/' 7 | } 8 | } 9 | } 10 | rootProject.name = 'kalgs' 11 | 12 | -------------------------------------------------------------------------------- /src/lesson1/JavaTasks.java: -------------------------------------------------------------------------------- 1 | package lesson1; 2 | 3 | import kotlin.NotImplementedError; 4 | 5 | @SuppressWarnings("unused") 6 | public class JavaTasks { 7 | /** 8 | * Сортировка времён 9 | * 10 | * Простая 11 | * (Модифицированная задача с сайта acmp.ru) 12 | * 13 | * Во входном файле с именем inputName содержатся моменты времени в формате ЧЧ:ММ:СС AM/PM, 14 | * каждый на отдельной строке. См. статью википедии "12-часовой формат времени". 15 | * 16 | * Пример: 17 | * 18 | * 01:15:19 PM 19 | * 07:26:57 AM 20 | * 10:00:03 AM 21 | * 07:56:14 PM 22 | * 01:15:19 PM 23 | * 12:40:31 AM 24 | * 25 | * Отсортировать моменты времени по возрастанию и вывести их в выходной файл с именем outputName, 26 | * сохраняя формат ЧЧ:ММ:СС AM/PM. Одинаковые моменты времени выводить друг за другом. Пример: 27 | * 28 | * 12:40:31 AM 29 | * 07:26:57 AM 30 | * 10:00:03 AM 31 | * 01:15:19 PM 32 | * 01:15:19 PM 33 | * 07:56:14 PM 34 | * 35 | * В случае обнаружения неверного формата файла бросить любое исключение. 36 | */ 37 | static public void sortTimes(String inputName, String outputName) { 38 | throw new NotImplementedError(); 39 | } 40 | 41 | /** 42 | * Сортировка адресов 43 | * 44 | * Средняя 45 | * 46 | * Во входном файле с именем inputName содержатся фамилии и имена жителей города с указанием улицы и номера дома, 47 | * где они прописаны. Пример: 48 | * 49 | * Петров Иван - Железнодорожная 3 50 | * Сидоров Петр - Садовая 5 51 | * Иванов Алексей - Железнодорожная 7 52 | * Сидорова Мария - Садовая 5 53 | * Иванов Михаил - Железнодорожная 7 54 | * 55 | * Людей в городе может быть до миллиона. 56 | * 57 | * Вывести записи в выходной файл outputName, 58 | * упорядоченными по названию улицы (по алфавиту) и номеру дома (по возрастанию). 59 | * Людей, живущих в одном доме, выводить через запятую по алфавиту (вначале по фамилии, потом по имени). Пример: 60 | * 61 | * Железнодорожная 3 - Петров Иван 62 | * Железнодорожная 7 - Иванов Алексей, Иванов Михаил 63 | * Садовая 5 - Сидоров Петр, Сидорова Мария 64 | * 65 | * В случае обнаружения неверного формата файла бросить любое исключение. 66 | */ 67 | static public void sortAddresses(String inputName, String outputName) { 68 | throw new NotImplementedError(); 69 | } 70 | 71 | /** 72 | * Сортировка температур 73 | * 74 | * Средняя 75 | * (Модифицированная задача с сайта acmp.ru) 76 | * 77 | * Во входном файле заданы температуры различных участков абстрактной планеты с точностью до десятых градуса. 78 | * Температуры могут изменяться в диапазоне от -273.0 до +500.0. 79 | * Например: 80 | * 81 | * 24.7 82 | * -12.6 83 | * 121.3 84 | * -98.4 85 | * 99.5 86 | * -12.6 87 | * 11.0 88 | * 89 | * Количество строк в файле может достигать ста миллионов. 90 | * Вывести строки в выходной файл, отсортировав их по возрастанию температуры. 91 | * Повторяющиеся строки сохранить. Например: 92 | * 93 | * -98.4 94 | * -12.6 95 | * -12.6 96 | * 11.0 97 | * 24.7 98 | * 99.5 99 | * 121.3 100 | */ 101 | static public void sortTemperatures(String inputName, String outputName) { 102 | throw new NotImplementedError(); 103 | } 104 | 105 | /** 106 | * Сортировка последовательности 107 | * 108 | * Средняя 109 | * (Задача взята с сайта acmp.ru) 110 | * 111 | * В файле задана последовательность из n целых положительных чисел, каждое в своей строке, например: 112 | * 113 | * 1 114 | * 2 115 | * 3 116 | * 2 117 | * 3 118 | * 1 119 | * 2 120 | * 121 | * Необходимо найти число, которое встречается в этой последовательности наибольшее количество раз, 122 | * а если таких чисел несколько, то найти минимальное из них, 123 | * и после этого переместить все такие числа в конец заданной последовательности. 124 | * Порядок расположения остальных чисел должен остаться без изменения. 125 | * 126 | * 1 127 | * 3 128 | * 3 129 | * 1 130 | * 2 131 | * 2 132 | * 2 133 | */ 134 | static public void sortSequence(String inputName, String outputName) { 135 | throw new NotImplementedError(); 136 | } 137 | 138 | /** 139 | * Соединить два отсортированных массива в один 140 | * 141 | * Простая 142 | * 143 | * Задан отсортированный массив first и второй массив second, 144 | * первые first.size ячеек которого содержат null, а остальные ячейки также отсортированы. 145 | * Соединить оба массива в массиве second так, чтобы он оказался отсортирован. Пример: 146 | * 147 | * first = [4 9 15 20 28] 148 | * second = [null null null null null 1 3 9 13 18 23] 149 | * 150 | * Результат: second = [1 3 4 9 9 13 15 20 23 28] 151 | */ 152 | static > void mergeArrays(T[] first, T[] second) { 153 | throw new NotImplementedError(); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/lesson1/SortTasks.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_PARAMETER") 2 | 3 | package lesson1 4 | 5 | /** 6 | * Сортировка времён 7 | * 8 | * Простая 9 | * (Модифицированная задача с сайта acmp.ru) 10 | * 11 | * Во входном файле с именем inputName содержатся моменты времени в формате ЧЧ:ММ:СС AM/PM, 12 | * каждый на отдельной строке. См. статью википедии "12-часовой формат времени". 13 | * 14 | * Пример: 15 | * 16 | * 01:15:19 PM 17 | * 07:26:57 AM 18 | * 10:00:03 AM 19 | * 07:56:14 PM 20 | * 01:15:19 PM 21 | * 12:40:31 AM 22 | * 23 | * Отсортировать моменты времени по возрастанию и вывести их в выходной файл с именем outputName, 24 | * сохраняя формат ЧЧ:ММ:СС AM/PM. Одинаковые моменты времени выводить друг за другом. Пример: 25 | * 26 | * 12:40:31 AM 27 | * 07:26:57 AM 28 | * 10:00:03 AM 29 | * 01:15:19 PM 30 | * 01:15:19 PM 31 | * 07:56:14 PM 32 | * 33 | * В случае обнаружения неверного формата файла бросить любое исключение. 34 | */ 35 | fun sortTimes(inputName: String, outputName: String) { 36 | TODO() 37 | } 38 | 39 | /** 40 | * Сортировка адресов 41 | * 42 | * Средняя 43 | * 44 | * Во входном файле с именем inputName содержатся фамилии и имена жителей города с указанием улицы и номера дома, 45 | * где они прописаны. Пример: 46 | * 47 | * Петров Иван - Железнодорожная 3 48 | * Сидоров Петр - Садовая 5 49 | * Иванов Алексей - Железнодорожная 7 50 | * Сидорова Мария - Садовая 5 51 | * Иванов Михаил - Железнодорожная 7 52 | * 53 | * Людей в городе может быть до миллиона. 54 | * 55 | * Вывести записи в выходной файл outputName, 56 | * упорядоченными по названию улицы (по алфавиту) и номеру дома (по возрастанию). 57 | * Людей, живущих в одном доме, выводить через запятую по алфавиту (вначале по фамилии, потом по имени). Пример: 58 | * 59 | * Железнодорожная 3 - Петров Иван 60 | * Железнодорожная 7 - Иванов Алексей, Иванов Михаил 61 | * Садовая 5 - Сидоров Петр, Сидорова Мария 62 | * 63 | * В случае обнаружения неверного формата файла бросить любое исключение. 64 | */ 65 | fun sortAddresses(inputName: String, outputName: String) { 66 | TODO() 67 | } 68 | 69 | /** 70 | * Сортировка температур 71 | * 72 | * Средняя 73 | * (Модифицированная задача с сайта acmp.ru) 74 | * 75 | * Во входном файле заданы температуры различных участков абстрактной планеты с точностью до десятых градуса. 76 | * Температуры могут изменяться в диапазоне от -273.0 до +500.0. 77 | * Например: 78 | * 79 | * 24.7 80 | * -12.6 81 | * 121.3 82 | * -98.4 83 | * 99.5 84 | * -12.6 85 | * 11.0 86 | * 87 | * Количество строк в файле может достигать ста миллионов. 88 | * Вывести строки в выходной файл, отсортировав их по возрастанию температуры. 89 | * Повторяющиеся строки сохранить. Например: 90 | * 91 | * -98.4 92 | * -12.6 93 | * -12.6 94 | * 11.0 95 | * 24.7 96 | * 99.5 97 | * 121.3 98 | */ 99 | fun sortTemperatures(inputName: String, outputName: String) { 100 | TODO() 101 | } 102 | 103 | /** 104 | * Сортировка последовательности 105 | * 106 | * Средняя 107 | * (Задача взята с сайта acmp.ru) 108 | * 109 | * В файле задана последовательность из n целых положительных чисел, каждое в своей строке, например: 110 | * 111 | * 1 112 | * 2 113 | * 3 114 | * 2 115 | * 3 116 | * 1 117 | * 2 118 | * 119 | * Необходимо найти число, которое встречается в этой последовательности наибольшее количество раз, 120 | * а если таких чисел несколько, то найти минимальное из них, 121 | * и после этого переместить все такие числа в конец заданной последовательности. 122 | * Порядок расположения остальных чисел должен остаться без изменения. 123 | * 124 | * 1 125 | * 3 126 | * 3 127 | * 1 128 | * 2 129 | * 2 130 | * 2 131 | */ 132 | fun sortSequence(inputName: String, outputName: String) { 133 | TODO() 134 | } 135 | 136 | /** 137 | * Соединить два отсортированных массива в один 138 | * 139 | * Простая 140 | * 141 | * Задан отсортированный массив first и второй массив second, 142 | * первые first.size ячеек которого содержат null, а остальные ячейки также отсортированы. 143 | * Соединить оба массива в массиве second так, чтобы он оказался отсортирован. Пример: 144 | * 145 | * first = [4 9 15 20 28] 146 | * second = [null null null null null 1 3 9 13 18 23] 147 | * 148 | * Результат: second = [1 3 4 9 9 13 15 20 23 28] 149 | */ 150 | fun > mergeArrays(first: Array, second: Array) { 151 | TODO() 152 | } 153 | 154 | -------------------------------------------------------------------------------- /src/lesson1/Sorts.java: -------------------------------------------------------------------------------- 1 | package lesson1; 2 | 3 | import java.util.Arrays; 4 | import java.util.Calendar; 5 | import java.util.Random; 6 | 7 | @SuppressWarnings("WeakerAccess") 8 | public class Sorts { 9 | 10 | public static > void insertionSort(T[] elements) { 11 | for (int i = 1; i < elements.length; i++) { 12 | T current = elements[i]; 13 | int j = i - 1; 14 | for (; j >= 0; j--) { 15 | if (elements[j].compareTo(current) > 0) elements[j+1] = elements[j]; 16 | else break; 17 | } 18 | elements[j+1] = current; 19 | } 20 | } 21 | 22 | public static void insertionSort(int[] elements) { 23 | for (int i = 1; i < elements.length; i++) { 24 | int current = elements[i]; 25 | int j = i - 1; 26 | for (; j >= 0; j--) { 27 | if (elements[j] > current) elements[j+1] = elements[j]; 28 | else break; 29 | } 30 | elements[j+1] = current; 31 | } 32 | } 33 | 34 | private static void merge(int[] elements, int begin, int middle, int end) { 35 | int[] left = Arrays.copyOfRange(elements, begin, middle); 36 | int[] right = Arrays.copyOfRange(elements, middle, end); 37 | int li = 0, ri = 0; 38 | for (int i = begin; i < end; i++) { 39 | if (li < left.length && (ri == right.length || left[li] <= right[ri])) { 40 | elements[i] = left[li++]; 41 | } 42 | else { 43 | elements[i] = right[ri++]; 44 | } 45 | } 46 | } 47 | 48 | private static void mergeSort(int[] elements, int begin, int end) { 49 | if (end - begin <= 1) return; 50 | int middle = (begin + end) / 2; 51 | mergeSort(elements, begin, middle); 52 | mergeSort(elements, middle, end); 53 | merge(elements, begin, middle, end); 54 | } 55 | 56 | public static void mergeSort(int[] elements) { 57 | mergeSort(elements, 0, elements.length); 58 | } 59 | 60 | private static void heapify(int[] elements, int start, int length) { 61 | int left = 2 * start + 1; 62 | int right = left + 1; 63 | int max = start; 64 | if (left < length && elements[left] > elements[max]) { 65 | max = left; 66 | } 67 | if (right < length && elements[right] > elements[max]) { 68 | max = right; 69 | } 70 | if (max != start) { 71 | int temp = elements[max]; 72 | elements[max] = elements[start]; 73 | elements[start] = temp; 74 | heapify(elements, max, length); 75 | } 76 | } 77 | 78 | private static void buildHeap(int[] elements) { 79 | for (int start = elements.length / 2 - 1; start >= 0; start--) { 80 | heapify(elements, start, elements.length); 81 | } 82 | } 83 | 84 | public static void heapSort(int[] elements) { 85 | buildHeap(elements); 86 | for (int j = elements.length - 1; j >= 1; j--) { 87 | int temp = elements[0]; 88 | elements[0] = elements[j]; 89 | elements[j] = temp; 90 | heapify(elements, 0, j); 91 | } 92 | } 93 | 94 | private static final Random random = new Random(Calendar.getInstance().getTimeInMillis()); 95 | 96 | private static int partition(int[] elements, int min, int max) { 97 | int x = elements[min + random.nextInt(max - min + 1)]; 98 | int left = min, right = max; 99 | while (left <= right) { 100 | while (elements[left] < x) { 101 | left++; 102 | } 103 | while (elements[right] > x) { 104 | right--; 105 | } 106 | if (left <= right) { 107 | int temp = elements[left]; 108 | elements[left] = elements[right]; 109 | elements[right] = temp; 110 | left++; 111 | right--; 112 | } 113 | } 114 | return right; 115 | } 116 | 117 | private static void quickSort(int[] elements, int min, int max) { 118 | if (min < max) { 119 | int border = partition(elements, min, max); 120 | quickSort(elements, min, border); 121 | quickSort(elements, border + 1, max); 122 | } 123 | } 124 | 125 | public static void quickSort(int[] elements) { 126 | quickSort(elements, 0, elements.length - 1); 127 | } 128 | 129 | public static int[] countingSort(int[] elements, int limit) { 130 | int[] count = new int[limit + 1]; 131 | for (int element: elements) { 132 | count[element]++; 133 | } 134 | for (int j = 1; j <= limit; j++) { 135 | count[j] += count[j - 1]; 136 | } 137 | int[] out = new int[elements.length]; 138 | for (int j = elements.length - 1; j >= 0; j--) { 139 | out[count[elements[j]] - 1] = elements[j]; 140 | count[elements[j]]--; 141 | } 142 | return out; 143 | } 144 | } -------------------------------------------------------------------------------- /src/lesson1/Sorts.kt: -------------------------------------------------------------------------------- 1 | package lesson1 2 | 3 | import java.util.* 4 | 5 | private val random = Random(Calendar.getInstance().timeInMillis) 6 | 7 | fun > insertionSort(elements: MutableList) { 8 | for (i in 1 until elements.size) { 9 | val current = elements[i] 10 | var j = i - 1 11 | while (j >= 0) { 12 | if (elements[j] > current) 13 | elements[j + 1] = elements[j] 14 | else 15 | break 16 | j-- 17 | } 18 | elements[j + 1] = current 19 | } 20 | } 21 | 22 | private fun merge(elements: IntArray, begin: Int, middle: Int, end: Int) { 23 | val left = elements.copyOfRange(begin, middle) 24 | val right = elements.copyOfRange(middle, end) 25 | var li = 0 26 | var ri = 0 27 | for (i in begin until end) { 28 | if (li < left.size && (ri == right.size || left[li] <= right[ri])) { 29 | elements[i] = left[li++] 30 | } else { 31 | elements[i] = right[ri++] 32 | } 33 | } 34 | } 35 | 36 | private fun mergeSort(elements: IntArray, begin: Int, end: Int) { 37 | if (end - begin <= 1) return 38 | val middle = (begin + end) / 2 39 | mergeSort(elements, begin, middle) 40 | mergeSort(elements, middle, end) 41 | merge(elements, begin, middle, end) 42 | } 43 | 44 | fun mergeSort(elements: IntArray) { 45 | mergeSort(elements, 0, elements.size) 46 | } 47 | 48 | private fun heapify(elements: IntArray, start: Int, length: Int) { 49 | val left = 2 * start + 1 50 | val right = left + 1 51 | var max = start 52 | if (left < length && elements[left] > elements[max]) { 53 | max = left 54 | } 55 | if (right < length && elements[right] > elements[max]) { 56 | max = right 57 | } 58 | if (max != start) { 59 | val temp = elements[max] 60 | elements[max] = elements[start] 61 | elements[start] = temp 62 | heapify(elements, max, length) 63 | } 64 | } 65 | 66 | private fun buildHeap(elements: IntArray) { 67 | for (start in elements.size / 2 - 1 downTo 0) { 68 | heapify(elements, start, elements.size) 69 | } 70 | } 71 | 72 | fun heapSort(elements: IntArray) { 73 | buildHeap(elements) 74 | for (j in elements.size - 1 downTo 1) { 75 | val temp = elements[0] 76 | elements[0] = elements[j] 77 | elements[j] = temp 78 | heapify(elements, 0, j) 79 | } 80 | } 81 | 82 | private fun partition(elements: IntArray, min: Int, max: Int): Int { 83 | val x = elements[min + random.nextInt(max - min + 1)] 84 | var left = min 85 | var right = max 86 | while (left <= right) { 87 | while (elements[left] < x) { 88 | left++ 89 | } 90 | while (elements[right] > x) { 91 | right-- 92 | } 93 | if (left <= right) { 94 | val temp = elements[left] 95 | elements[left] = elements[right] 96 | elements[right] = temp 97 | left++ 98 | right-- 99 | } 100 | } 101 | return right 102 | } 103 | 104 | private fun quickSort(elements: IntArray, min: Int, max: Int) { 105 | if (min < max) { 106 | val border = partition(elements, min, max) 107 | quickSort(elements, min, border) 108 | quickSort(elements, border + 1, max) 109 | } 110 | } 111 | 112 | fun quickSort(elements: IntArray) { 113 | quickSort(elements, 0, elements.size - 1) 114 | } 115 | 116 | fun countingSort(elements: IntArray, limit: Int): IntArray { 117 | val count = IntArray(limit + 1) 118 | for (element in elements) { 119 | count[element]++ 120 | } 121 | for (j in 1..limit) { 122 | count[j] += count[j - 1] 123 | } 124 | val out = IntArray(elements.size) 125 | for (j in elements.indices.reversed()) { 126 | out[count[elements[j]] - 1] = elements[j] 127 | count[elements[j]]-- 128 | } 129 | return out 130 | } 131 | 132 | /** 133 | * Библиотечные сортировки (приведены только для примера, 134 | * рекомендуется использовать list.sorted() и list.sort() напрямую) 135 | */ 136 | fun > librarySortForImmutable(list: List): List = list.sorted() 137 | 138 | fun > librarySortForMutable(list: MutableList) { 139 | list.sort() 140 | } -------------------------------------------------------------------------------- /src/lesson2/Algorithms.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_PARAMETER") 2 | 3 | package lesson2 4 | 5 | /** 6 | * Получение наибольшей прибыли (она же -- поиск максимального подмассива) 7 | * Простая 8 | * 9 | * Во входном файле с именем inputName перечислены цены на акции компании в различные (возрастающие) моменты времени 10 | * (каждая цена идёт с новой строки). Цена -- это целое положительное число. Пример: 11 | * 12 | * 201 13 | * 196 14 | * 190 15 | * 198 16 | * 187 17 | * 194 18 | * 193 19 | * 185 20 | * 21 | * Выбрать два момента времени, первый из них для покупки акций, а второй для продажи, с тем, чтобы разница 22 | * между ценой продажи и ценой покупки была максимально большой. Второй момент должен быть раньше первого. 23 | * Вернуть пару из двух моментов. 24 | * Каждый момент обозначается целым числом -- номер строки во входном файле, нумерация с единицы. 25 | * Например, для приведённого выше файла результат должен быть Pair(3, 4) 26 | * 27 | * В случае обнаружения неверного формата файла бросить любое исключение. 28 | */ 29 | fun optimizeBuyAndSell(inputName: String): Pair { 30 | TODO() 31 | } 32 | 33 | /** 34 | * Задача Иосифа Флафия. 35 | * Простая 36 | * 37 | * Образовав круг, стоят menNumber человек, пронумерованных от 1 до menNumber. 38 | * 39 | * 1 2 3 40 | * 8 4 41 | * 7 6 5 42 | * 43 | * Мы считаем от 1 до choiceInterval (например, до 5), начиная с 1-го человека по кругу. 44 | * Человек, на котором остановился счёт, выбывает. 45 | * 46 | * 1 2 3 47 | * 8 4 48 | * 7 6 х 49 | * 50 | * Далее счёт продолжается со следующего человека, также от 1 до choiceInterval. 51 | * Выбывшие при счёте пропускаются, и человек, на котором остановился счёт, выбывает. 52 | * 53 | * 1 х 3 54 | * 8 4 55 | * 7 6 Х 56 | * 57 | * Процедура повторяется, пока не останется один человек. Требуется вернуть его номер (в данном случае 3). 58 | * 59 | * 1 Х 3 60 | * х 4 61 | * 7 6 Х 62 | * 63 | * 1 Х 3 64 | * Х 4 65 | * х 6 Х 66 | * 67 | * х Х 3 68 | * Х 4 69 | * Х 6 Х 70 | * 71 | * Х Х 3 72 | * Х х 73 | * Х 6 Х 74 | * 75 | * Х Х 3 76 | * Х Х 77 | * Х х Х 78 | * 79 | * Общий комментарий: решение из Википедии для этой задачи принимается, 80 | * но приветствуется попытка решить её самостоятельно. 81 | */ 82 | fun josephTask(menNumber: Int, choiceInterval: Int): Int { 83 | TODO() 84 | } 85 | 86 | /** 87 | * Наибольшая общая подстрока. 88 | * Средняя 89 | * 90 | * Дано две строки, например ОБСЕРВАТОРИЯ и КОНСЕРВАТОРЫ. 91 | * Найти их самую длинную общую подстроку -- в примере это СЕРВАТОР. 92 | * Если общих подстрок нет, вернуть пустую строку. 93 | * При сравнении подстрок, регистр символов *имеет* значение. 94 | * Если имеется несколько самых длинных общих подстрок одной длины, 95 | * вернуть ту из них, которая встречается раньше в строке first. 96 | */ 97 | fun longestCommonSubstring(first: String, second: String): String { 98 | TODO() 99 | } 100 | 101 | /** 102 | * Число простых чисел в интервале 103 | * Простая 104 | * 105 | * Рассчитать количество простых чисел в интервале от 1 до limit (включительно). 106 | * Если limit <= 1, вернуть результат 0. 107 | * 108 | * Справка: простым считается число, которое делится нацело только на 1 и на себя. 109 | * Единица простым числом не считается. 110 | */ 111 | fun calcPrimesNumber(limit: Int): Int { 112 | TODO() 113 | } 114 | -------------------------------------------------------------------------------- /src/lesson2/JavaAlgorithms.java: -------------------------------------------------------------------------------- 1 | package lesson2; 2 | 3 | import kotlin.NotImplementedError; 4 | import kotlin.Pair; 5 | 6 | @SuppressWarnings("unused") 7 | public class JavaAlgorithms { 8 | /** 9 | * Получение наибольшей прибыли (она же -- поиск максимального подмассива) 10 | * Простая 11 | * 12 | * Во входном файле с именем inputName перечислены цены на акции компании в различные (возрастающие) моменты времени 13 | * (каждая цена идёт с новой строки). Цена -- это целое положительное число. Пример: 14 | * 15 | * 201 16 | * 196 17 | * 190 18 | * 198 19 | * 187 20 | * 194 21 | * 193 22 | * 185 23 | * 24 | * Выбрать два момента времени, первый из них для покупки акций, а второй для продажи, с тем, чтобы разница 25 | * между ценой продажи и ценой покупки была максимально большой. Второй момент должен быть раньше первого. 26 | * Вернуть пару из двух моментов. 27 | * Каждый момент обозначается целым числом -- номер строки во входном файле, нумерация с единицы. 28 | * Например, для приведённого выше файла результат должен быть Pair(3, 4) 29 | * 30 | * В случае обнаружения неверного формата файла бросить любое исключение. 31 | */ 32 | static public Pair optimizeBuyAndSell(String inputName) { 33 | throw new NotImplementedError(); 34 | } 35 | 36 | /** 37 | * Задача Иосифа Флафия. 38 | * Простая 39 | * 40 | * Образовав круг, стоят menNumber человек, пронумерованных от 1 до menNumber. 41 | * 42 | * 1 2 3 43 | * 8 4 44 | * 7 6 5 45 | * 46 | * Мы считаем от 1 до choiceInterval (например, до 5), начиная с 1-го человека по кругу. 47 | * Человек, на котором остановился счёт, выбывает. 48 | * 49 | * 1 2 3 50 | * 8 4 51 | * 7 6 х 52 | * 53 | * Далее счёт продолжается со следующего человека, также от 1 до choiceInterval. 54 | * Выбывшие при счёте пропускаются, и человек, на котором остановился счёт, выбывает. 55 | * 56 | * 1 х 3 57 | * 8 4 58 | * 7 6 Х 59 | * 60 | * Процедура повторяется, пока не останется один человек. Требуется вернуть его номер (в данном случае 3). 61 | * 62 | * 1 Х 3 63 | * х 4 64 | * 7 6 Х 65 | * 66 | * 1 Х 3 67 | * Х 4 68 | * х 6 Х 69 | * 70 | * х Х 3 71 | * Х 4 72 | * Х 6 Х 73 | * 74 | * Х Х 3 75 | * Х х 76 | * Х 6 Х 77 | * 78 | * Х Х 3 79 | * Х Х 80 | * Х х Х 81 | * 82 | * Общий комментарий: решение из Википедии для этой задачи принимается, 83 | * но приветствуется попытка решить её самостоятельно. 84 | */ 85 | static public int josephTask(int menNumber, int choiceInterval) { 86 | throw new NotImplementedError(); 87 | } 88 | 89 | /** 90 | * Наибольшая общая подстрока. 91 | * Средняя 92 | * 93 | * Дано две строки, например ОБСЕРВАТОРИЯ и КОНСЕРВАТОРЫ. 94 | * Найти их самую длинную общую подстроку -- в примере это СЕРВАТОР. 95 | * Если общих подстрок нет, вернуть пустую строку. 96 | * При сравнении подстрок, регистр символов *имеет* значение. 97 | * Если имеется несколько самых длинных общих подстрок одной длины, 98 | * вернуть ту из них, которая встречается раньше в строке first. 99 | */ 100 | static public String longestCommonSubstring(String firs, String second) { 101 | throw new NotImplementedError(); 102 | } 103 | 104 | /** 105 | * Число простых чисел в интервале 106 | * Простая 107 | * 108 | * Рассчитать количество простых чисел в интервале от 1 до limit (включительно). 109 | * Если limit <= 1, вернуть результат 0. 110 | * 111 | * Справка: простым считается число, которое делится нацело только на 1 и на себя. 112 | * Единица простым числом не считается. 113 | */ 114 | static public int calcPrimesNumber(int limit) { 115 | throw new NotImplementedError(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/lesson3/BinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package lesson3; 2 | 3 | import java.util.*; 4 | import kotlin.NotImplementedError; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | // attention: Comparable is supported but Comparator is not 9 | public class BinarySearchTree> extends AbstractSet implements CheckableSortedSet { 10 | 11 | private static class Node { 12 | final T value; 13 | Node left = null; 14 | Node right = null; 15 | 16 | Node(T value) { 17 | this.value = value; 18 | } 19 | } 20 | 21 | private Node root = null; 22 | 23 | private int size = 0; 24 | 25 | @Override 26 | public int size() { 27 | return size; 28 | } 29 | 30 | private Node find(T value) { 31 | if (root == null) return null; 32 | return find(root, value); 33 | } 34 | 35 | private Node find(Node start, T value) { 36 | int comparison = value.compareTo(start.value); 37 | if (comparison == 0) { 38 | return start; 39 | } 40 | else if (comparison < 0) { 41 | if (start.left == null) return start; 42 | return find(start.left, value); 43 | } 44 | else { 45 | if (start.right == null) return start; 46 | return find(start.right, value); 47 | } 48 | } 49 | 50 | @Override 51 | public boolean contains(Object o) { 52 | @SuppressWarnings("unchecked") 53 | T t = (T) o; 54 | Node closest = find(t); 55 | return closest != null && t.compareTo(closest.value) == 0; 56 | } 57 | 58 | /** 59 | * Добавление элемента в дерево 60 | * 61 | * Если элемента нет в множестве, функция добавляет его в дерево и возвращает true. 62 | * В ином случае функция оставляет множество нетронутым и возвращает false. 63 | * 64 | * Спецификация: {@link Set#add(Object)} (Ctrl+Click по add) 65 | * 66 | * Пример 67 | */ 68 | @Override 69 | public boolean add(T t) { 70 | Node closest = find(t); 71 | int comparison = closest == null ? -1 : t.compareTo(closest.value); 72 | if (comparison == 0) { 73 | return false; 74 | } 75 | Node newNode = new Node<>(t); 76 | if (closest == null) { 77 | root = newNode; 78 | } 79 | else if (comparison < 0) { 80 | assert closest.left == null; 81 | closest.left = newNode; 82 | } 83 | else { 84 | assert closest.right == null; 85 | closest.right = newNode; 86 | } 87 | size++; 88 | return true; 89 | } 90 | 91 | /** 92 | * Удаление элемента из дерева 93 | * 94 | * Если элемент есть в множестве, функция удаляет его из дерева и возвращает true. 95 | * В ином случае функция оставляет множество нетронутым и возвращает false. 96 | * Высота дерева не должна увеличиться в результате удаления. 97 | * 98 | * Спецификация: {@link Set#remove(Object)} (Ctrl+Click по remove) 99 | * 100 | * Средняя 101 | */ 102 | @Override 103 | public boolean remove(Object o) { 104 | // TODO 105 | throw new NotImplementedError(); 106 | } 107 | 108 | @Nullable 109 | @Override 110 | public Comparator comparator() { 111 | return null; 112 | } 113 | 114 | @NotNull 115 | @Override 116 | public Iterator iterator() { 117 | return new BinarySearchTreeIterator(); 118 | } 119 | 120 | public class BinarySearchTreeIterator implements Iterator { 121 | 122 | private BinarySearchTreeIterator() { 123 | // Добавьте сюда инициализацию, если она необходима. 124 | } 125 | 126 | /** 127 | * Проверка наличия следующего элемента 128 | * 129 | * Функция возвращает true, если итерация по множеству ещё не окончена (то есть, если вызов next() вернёт 130 | * следующий элемент множества, а не бросит исключение); иначе возвращает false. 131 | * 132 | * Спецификация: {@link Iterator#hasNext()} (Ctrl+Click по hasNext) 133 | * 134 | * Средняя 135 | */ 136 | @Override 137 | public boolean hasNext() { 138 | // TODO 139 | throw new NotImplementedError(); 140 | } 141 | 142 | /** 143 | * Получение следующего элемента 144 | * 145 | * Функция возвращает следующий элемент множества. 146 | * Так как BinarySearchTree реализует интерфейс SortedSet, последовательные 147 | * вызовы next() должны возвращать элементы в порядке возрастания. 148 | * 149 | * Бросает NoSuchElementException, если все элементы уже были возвращены. 150 | * 151 | * Спецификация: {@link Iterator#next()} (Ctrl+Click по next) 152 | * 153 | * Средняя 154 | */ 155 | @Override 156 | public T next() { 157 | // TODO 158 | throw new NotImplementedError(); 159 | } 160 | 161 | /** 162 | * Удаление предыдущего элемента 163 | * 164 | * Функция удаляет из множества элемент, возвращённый крайним вызовом функции next(). 165 | * 166 | * Бросает IllegalStateException, если функция была вызвана до первого вызова next() или же была вызвана 167 | * более одного раза после любого вызова next(). 168 | * 169 | * Спецификация: {@link Iterator#remove()} (Ctrl+Click по remove) 170 | * 171 | * Сложная 172 | */ 173 | @Override 174 | public void remove() { 175 | // TODO 176 | throw new NotImplementedError(); 177 | } 178 | } 179 | 180 | /** 181 | * Подмножество всех элементов в диапазоне [fromElement, toElement) 182 | * 183 | * Функция возвращает множество, содержащее в себе все элементы дерева, которые 184 | * больше или равны fromElement и строго меньше toElement. 185 | * При равенстве fromElement и toElement возвращается пустое множество. 186 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 187 | * 188 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 189 | * должен быть брошен IllegalArgumentException. 190 | * 191 | * Спецификация: {@link SortedSet#subSet(Object, Object)} (Ctrl+Click по subSet) 192 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 193 | * 194 | * Очень сложная (в том случае, если спецификация реализуется в полном объёме) 195 | */ 196 | @NotNull 197 | @Override 198 | public SortedSet subSet(T fromElement, T toElement) { 199 | // TODO 200 | throw new NotImplementedError(); 201 | } 202 | 203 | /** 204 | * Подмножество всех элементов строго меньше заданного 205 | * 206 | * Функция возвращает множество, содержащее в себе все элементы дерева строго меньше toElement. 207 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 208 | * 209 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 210 | * должен быть брошен IllegalArgumentException. 211 | * 212 | * Спецификация: {@link SortedSet#headSet(Object)} (Ctrl+Click по headSet) 213 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 214 | * 215 | * Сложная 216 | */ 217 | @NotNull 218 | @Override 219 | public SortedSet headSet(T toElement) { 220 | // TODO 221 | throw new NotImplementedError(); 222 | } 223 | 224 | /** 225 | * Подмножество всех элементов нестрого больше заданного 226 | * 227 | * Функция возвращает множество, содержащее в себе все элементы дерева нестрого больше toElement. 228 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 229 | * 230 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 231 | * должен быть брошен IllegalArgumentException. 232 | * 233 | * Спецификация: {@link SortedSet#tailSet(Object)} (Ctrl+Click по tailSet) 234 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 235 | * 236 | * Сложная 237 | */ 238 | @NotNull 239 | @Override 240 | public SortedSet tailSet(T fromElement) { 241 | // TODO 242 | throw new NotImplementedError(); 243 | } 244 | 245 | @Override 246 | public T first() { 247 | if (root == null) throw new NoSuchElementException(); 248 | Node current = root; 249 | while (current.left != null) { 250 | current = current.left; 251 | } 252 | return current.value; 253 | } 254 | 255 | @Override 256 | public T last() { 257 | if (root == null) throw new NoSuchElementException(); 258 | Node current = root; 259 | while (current.right != null) { 260 | current = current.right; 261 | } 262 | return current.value; 263 | } 264 | 265 | public int height() { 266 | return height(root); 267 | } 268 | 269 | private int height(Node node) { 270 | if (node == null) return 0; 271 | return 1 + Math.max(height(node.left), height(node.right)); 272 | } 273 | 274 | public boolean checkInvariant() { 275 | return root == null || checkInvariant(root); 276 | } 277 | 278 | private boolean checkInvariant(Node node) { 279 | Node left = node.left; 280 | if (left != null && (left.value.compareTo(node.value) >= 0 || !checkInvariant(left))) return false; 281 | Node right = node.right; 282 | return right == null || right.value.compareTo(node.value) > 0 && checkInvariant(right); 283 | } 284 | 285 | } -------------------------------------------------------------------------------- /src/lesson3/CheckableSortedSet.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import java.util.* 4 | 5 | interface CheckableSortedSet : SortedSet { 6 | fun checkInvariant(): Boolean 7 | fun height(): Int 8 | } -------------------------------------------------------------------------------- /src/lesson3/KtBinarySearchTree.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import java.util.* 4 | import kotlin.math.max 5 | 6 | // attention: Comparable is supported but Comparator is not 7 | class KtBinarySearchTree> : AbstractMutableSet(), CheckableSortedSet { 8 | 9 | private class Node( 10 | val value: T 11 | ) { 12 | var left: Node? = null 13 | var right: Node? = null 14 | } 15 | 16 | private var root: Node? = null 17 | 18 | override var size = 0 19 | private set 20 | 21 | private fun find(value: T): Node? = 22 | root?.let { find(it, value) } 23 | 24 | private fun find(start: Node, value: T): Node { 25 | val comparison = value.compareTo(start.value) 26 | return when { 27 | comparison == 0 -> start 28 | comparison < 0 -> start.left?.let { find(it, value) } ?: start 29 | else -> start.right?.let { find(it, value) } ?: start 30 | } 31 | } 32 | 33 | override operator fun contains(element: T): Boolean { 34 | val closest = find(element) 35 | return closest != null && element.compareTo(closest.value) == 0 36 | } 37 | 38 | /** 39 | * Добавление элемента в дерево 40 | * 41 | * Если элемента нет в множестве, функция добавляет его в дерево и возвращает true. 42 | * В ином случае функция оставляет множество нетронутым и возвращает false. 43 | * 44 | * Спецификация: [java.util.Set.add] (Ctrl+Click по add) 45 | * 46 | * Пример 47 | */ 48 | override fun add(element: T): Boolean { 49 | val closest = find(element) 50 | val comparison = if (closest == null) -1 else element.compareTo(closest.value) 51 | if (comparison == 0) { 52 | return false 53 | } 54 | val newNode = Node(element) 55 | when { 56 | closest == null -> root = newNode 57 | comparison < 0 -> { 58 | assert(closest.left == null) 59 | closest.left = newNode 60 | } 61 | else -> { 62 | assert(closest.right == null) 63 | closest.right = newNode 64 | } 65 | } 66 | size++ 67 | return true 68 | } 69 | 70 | /** 71 | * Удаление элемента из дерева 72 | * 73 | * Если элемент есть в множестве, функция удаляет его из дерева и возвращает true. 74 | * В ином случае функция оставляет множество нетронутым и возвращает false. 75 | * Высота дерева не должна увеличиться в результате удаления. 76 | * 77 | * Спецификация: [java.util.Set.remove] (Ctrl+Click по remove) 78 | * (в Котлине тип параметера изменён с Object на тип хранимых в дереве данных) 79 | * 80 | * Средняя 81 | */ 82 | override fun remove(element: T): Boolean { 83 | TODO() 84 | } 85 | 86 | override fun comparator(): Comparator? = 87 | null 88 | 89 | override fun iterator(): MutableIterator = 90 | BinarySearchTreeIterator() 91 | 92 | inner class BinarySearchTreeIterator internal constructor() : MutableIterator { 93 | 94 | /** 95 | * Проверка наличия следующего элемента 96 | * 97 | * Функция возвращает true, если итерация по множеству ещё не окончена (то есть, если вызов next() вернёт 98 | * следующий элемент множества, а не бросит исключение); иначе возвращает false. 99 | * 100 | * Спецификация: [java.util.Iterator.hasNext] (Ctrl+Click по hasNext) 101 | * 102 | * Средняя 103 | */ 104 | override fun hasNext(): Boolean { 105 | // TODO 106 | throw NotImplementedError() 107 | } 108 | 109 | /** 110 | * Получение следующего элемента 111 | * 112 | * Функция возвращает следующий элемент множества. 113 | * Так как BinarySearchTree реализует интерфейс SortedSet, последовательные 114 | * вызовы next() должны возвращать элементы в порядке возрастания. 115 | * 116 | * Бросает NoSuchElementException, если все элементы уже были возвращены. 117 | * 118 | * Спецификация: [java.util.Iterator.next] (Ctrl+Click по next) 119 | * 120 | * Средняя 121 | */ 122 | override fun next(): T { 123 | // TODO 124 | throw NotImplementedError() 125 | } 126 | 127 | /** 128 | * Удаление предыдущего элемента 129 | * 130 | * Функция удаляет из множества элемент, возвращённый крайним вызовом функции next(). 131 | * 132 | * Бросает IllegalStateException, если функция была вызвана до первого вызова next() или же была вызвана 133 | * более одного раза после любого вызова next(). 134 | * 135 | * Спецификация: [java.util.Iterator.remove] (Ctrl+Click по remove) 136 | * 137 | * Сложная 138 | */ 139 | override fun remove() { 140 | // TODO 141 | throw NotImplementedError() 142 | } 143 | 144 | } 145 | 146 | /** 147 | * Подмножество всех элементов в диапазоне [fromElement, toElement) 148 | * 149 | * Функция возвращает множество, содержащее в себе все элементы дерева, которые 150 | * больше или равны fromElement и строго меньше toElement. 151 | * При равенстве fromElement и toElement возвращается пустое множество. 152 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 153 | * 154 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 155 | * должен быть брошен IllegalArgumentException. 156 | * 157 | * Спецификация: [java.util.SortedSet.subSet] (Ctrl+Click по subSet) 158 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 159 | * 160 | * Очень сложная (в том случае, если спецификация реализуется в полном объёме) 161 | */ 162 | override fun subSet(fromElement: T, toElement: T): SortedSet { 163 | TODO() 164 | } 165 | 166 | /** 167 | * Подмножество всех элементов строго меньше заданного 168 | * 169 | * Функция возвращает множество, содержащее в себе все элементы дерева строго меньше toElement. 170 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 171 | * 172 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 173 | * должен быть брошен IllegalArgumentException. 174 | * 175 | * Спецификация: [java.util.SortedSet.headSet] (Ctrl+Click по headSet) 176 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 177 | * 178 | * Сложная 179 | */ 180 | override fun headSet(toElement: T): SortedSet { 181 | TODO() 182 | } 183 | 184 | /** 185 | * Подмножество всех элементов нестрого больше заданного 186 | * 187 | * Функция возвращает множество, содержащее в себе все элементы дерева нестрого больше toElement. 188 | * Изменения в дереве должны отображаться в полученном подмножестве, и наоборот. 189 | * 190 | * При попытке добавить в подмножество элемент за пределами указанного диапазона 191 | * должен быть брошен IllegalArgumentException. 192 | * 193 | * Спецификация: [java.util.SortedSet.tailSet] (Ctrl+Click по tailSet) 194 | * (настоятельно рекомендуется прочитать и понять спецификацию перед выполнением задачи) 195 | * 196 | * Сложная 197 | */ 198 | override fun tailSet(fromElement: T): SortedSet { 199 | TODO() 200 | } 201 | 202 | override fun first(): T { 203 | var current: Node = root ?: throw NoSuchElementException() 204 | while (current.left != null) { 205 | current = current.left!! 206 | } 207 | return current.value 208 | } 209 | 210 | override fun last(): T { 211 | var current: Node = root ?: throw NoSuchElementException() 212 | while (current.right != null) { 213 | current = current.right!! 214 | } 215 | return current.value 216 | } 217 | 218 | override fun height(): Int = 219 | height(root) 220 | 221 | private fun height(node: Node?): Int { 222 | if (node == null) return 0 223 | return 1 + max(height(node.left), height(node.right)) 224 | } 225 | 226 | override fun checkInvariant(): Boolean = 227 | root?.let { checkInvariant(it) } ?: true 228 | 229 | private fun checkInvariant(node: Node): Boolean { 230 | val left = node.left 231 | if (left != null && (left.value >= node.value || !checkInvariant(left))) return false 232 | val right = node.right 233 | return right == null || right.value > node.value && checkInvariant(right) 234 | } 235 | 236 | } -------------------------------------------------------------------------------- /src/lesson3/PositiveSortedSet.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import java.util.SortedSet 4 | import java.util.Comparator 5 | 6 | /** 7 | * Этот класс воспринимать только как пример (несмотря на TO DO). 8 | */ 9 | class PositiveSortedSet(private val delegate: SortedSet) : AbstractMutableSet(), SortedSet { 10 | 11 | override val size: Int 12 | get() = delegate.count { it > 0 } 13 | 14 | override fun add(element: Int): Boolean { 15 | require(element > 0) 16 | return delegate.add(element) 17 | } 18 | 19 | override fun remove(element: Int): Boolean { 20 | require(element > 0) 21 | return delegate.remove(element) 22 | } 23 | 24 | override fun iterator(): MutableIterator = object : MutableIterator { 25 | 26 | private val delegate = this@PositiveSortedSet.delegate.iterator() 27 | 28 | private var next: Int? = null 29 | 30 | init { 31 | while (delegate.hasNext()) { 32 | val next = delegate.next() 33 | if (next > 0) { 34 | this.next = next 35 | break 36 | } 37 | } 38 | } 39 | 40 | override fun hasNext(): Boolean { 41 | return next != null 42 | } 43 | 44 | override fun next(): Int { 45 | val result = next ?: throw NoSuchElementException() 46 | next = if (delegate.hasNext()) delegate.next() else null 47 | return result 48 | } 49 | 50 | override fun remove() { 51 | delegate.remove() 52 | } 53 | 54 | } 55 | 56 | override fun comparator(): Comparator? = 57 | delegate.comparator() 58 | 59 | override fun subSet(fromElement: Int?, toElement: Int?): SortedSet { 60 | TODO() 61 | } 62 | 63 | override fun headSet(toElement: Int?): SortedSet { 64 | TODO() 65 | } 66 | 67 | override fun tailSet(fromElement: Int?): SortedSet { 68 | TODO() 69 | } 70 | 71 | override fun last(): Int { 72 | TODO() 73 | } 74 | 75 | override fun first(): Int { 76 | TODO() 77 | } 78 | 79 | } 80 | 81 | fun SortedSet.positives(): SortedSet = 82 | PositiveSortedSet(this) -------------------------------------------------------------------------------- /src/lesson3/SampleIterableCollection.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | /** 4 | * Этот класс воспринимать только как пример. 5 | */ 6 | class SampleIterableCollection : AbstractMutableCollection() { 7 | 8 | private class Node(val value: T) { 9 | var next: Node? = null 10 | } 11 | 12 | private var start: Node? = null 13 | 14 | override var size = 0 15 | 16 | override fun add(element: T): Boolean { 17 | val prev = start 18 | start = Node(element).apply { 19 | next = prev 20 | } 21 | size++ 22 | return true 23 | } 24 | 25 | override fun iterator(): MutableIterator = 26 | SampleIterator() 27 | 28 | inner class SampleIterator : MutableIterator { 29 | 30 | private var current: Node? = null 31 | 32 | private fun findNext(): Node? { 33 | return if (current != null) current?.next else start 34 | } 35 | 36 | override fun hasNext(): Boolean { 37 | return findNext() != null 38 | } 39 | 40 | override fun next(): T { 41 | current = findNext() ?: throw NoSuchElementException() 42 | return current!!.value 43 | } 44 | 45 | override fun remove() { 46 | current ?: throw NoSuchElementException() 47 | if (current == start) { 48 | start = start!!.next 49 | size-- 50 | return 51 | } 52 | var previous = start 53 | while (previous != null && previous.next != current) { 54 | previous = previous.next 55 | } 56 | previous ?: throw NoSuchElementException() 57 | previous.next = current!!.next 58 | size-- 59 | } 60 | 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/lesson4/KtTrie.kt: -------------------------------------------------------------------------------- 1 | package lesson4 2 | 3 | import java.util.* 4 | 5 | /** 6 | * Префиксное дерево для строк 7 | */ 8 | class KtTrie : AbstractMutableSet(), MutableSet { 9 | 10 | private class Node { 11 | val children: SortedMap = sortedMapOf() 12 | } 13 | 14 | private val root = Node() 15 | 16 | override var size: Int = 0 17 | private set 18 | 19 | override fun clear() { 20 | root.children.clear() 21 | size = 0 22 | } 23 | 24 | private fun String.withZero() = this + 0.toChar() 25 | 26 | private fun findNode(element: String): Node? { 27 | var current = root 28 | for (char in element) { 29 | current = current.children[char] ?: return null 30 | } 31 | return current 32 | } 33 | 34 | override fun contains(element: String): Boolean = 35 | findNode(element.withZero()) != null 36 | 37 | override fun add(element: String): Boolean { 38 | var current = root 39 | var modified = false 40 | for (char in element.withZero()) { 41 | val child = current.children[char] 42 | if (child != null) { 43 | current = child 44 | } else { 45 | modified = true 46 | val newChild = Node() 47 | current.children[char] = newChild 48 | current = newChild 49 | } 50 | } 51 | if (modified) { 52 | size++ 53 | } 54 | return modified 55 | } 56 | 57 | override fun remove(element: String): Boolean { 58 | val current = findNode(element) ?: return false 59 | if (current.children.remove(0.toChar()) != null) { 60 | size-- 61 | return true 62 | } 63 | return false 64 | } 65 | 66 | /** 67 | * Итератор для префиксного дерева 68 | * 69 | * Спецификация: [java.util.Iterator] (Ctrl+Click по Iterator) 70 | * 71 | * Сложная 72 | */ 73 | override fun iterator(): MutableIterator { 74 | TODO() 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /src/lesson4/Trie.java: -------------------------------------------------------------------------------- 1 | package lesson4; 2 | 3 | import java.util.*; 4 | import kotlin.NotImplementedError; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | /** 9 | * Префиксное дерево для строк 10 | */ 11 | public class Trie extends AbstractSet implements Set { 12 | 13 | private static class Node { 14 | SortedMap children = new TreeMap<>(); 15 | } 16 | 17 | private final Node root = new Node(); 18 | 19 | private int size = 0; 20 | 21 | @Override 22 | public int size() { 23 | return size; 24 | } 25 | 26 | @Override 27 | public void clear() { 28 | root.children.clear(); 29 | size = 0; 30 | } 31 | 32 | private String withZero(String initial) { 33 | return initial + (char) 0; 34 | } 35 | 36 | @Nullable 37 | private Node findNode(String element) { 38 | Node current = root; 39 | for (char character : element.toCharArray()) { 40 | if (current == null) return null; 41 | current = current.children.get(character); 42 | } 43 | return current; 44 | } 45 | 46 | @Override 47 | public boolean contains(Object o) { 48 | String element = (String) o; 49 | return findNode(withZero(element)) != null; 50 | } 51 | 52 | @Override 53 | public boolean add(String element) { 54 | Node current = root; 55 | boolean modified = false; 56 | for (char character : withZero(element).toCharArray()) { 57 | Node child = current.children.get(character); 58 | if (child != null) { 59 | current = child; 60 | } else { 61 | modified = true; 62 | Node newChild = new Node(); 63 | current.children.put(character, newChild); 64 | current = newChild; 65 | } 66 | } 67 | if (modified) { 68 | size++; 69 | } 70 | return modified; 71 | } 72 | 73 | @Override 74 | public boolean remove(Object o) { 75 | String element = (String) o; 76 | Node current = findNode(element); 77 | if (current == null) return false; 78 | if (current.children.remove((char) 0) != null) { 79 | size--; 80 | return true; 81 | } 82 | return false; 83 | } 84 | 85 | /** 86 | * Итератор для префиксного дерева 87 | * 88 | * Спецификация: {@link Iterator} (Ctrl+Click по Iterator) 89 | * 90 | * Сложная 91 | */ 92 | @NotNull 93 | @Override 94 | public Iterator iterator() { 95 | // TODO 96 | throw new NotImplementedError(); 97 | } 98 | 99 | } -------------------------------------------------------------------------------- /src/lesson5/KtOpenAddressingSet.kt: -------------------------------------------------------------------------------- 1 | package lesson5 2 | 3 | /** 4 | * Множество(таблица) с открытой адресацией на 2^bits элементов без возможности роста. 5 | */ 6 | class KtOpenAddressingSet(private val bits: Int) : AbstractMutableSet() { 7 | init { 8 | require(bits in 2..31) 9 | } 10 | 11 | private val capacity = 1 shl bits 12 | 13 | private val storage = Array(capacity) { null } 14 | 15 | override var size: Int = 0 16 | 17 | /** 18 | * Индекс в таблице, начиная с которого следует искать данный элемент 19 | */ 20 | private fun T.startingIndex(): Int { 21 | return hashCode() and (0x7FFFFFFF shr (31 - bits)) 22 | } 23 | 24 | /** 25 | * Проверка, входит ли данный элемент в таблицу 26 | */ 27 | override fun contains(element: T): Boolean { 28 | var index = element.startingIndex() 29 | var current = storage[index] 30 | while (current != null) { 31 | if (current == element) { 32 | return true 33 | } 34 | index = (index + 1) % capacity 35 | current = storage[index] 36 | } 37 | return false 38 | } 39 | 40 | /** 41 | * Добавление элемента в таблицу. 42 | * 43 | * Не делает ничего и возвращает false, если такой же элемент уже есть в таблице. 44 | * В противном случае вставляет элемент в таблицу и возвращает true. 45 | * 46 | * Бросает исключение (IllegalStateException) в случае переполнения таблицы. 47 | * Обычно Set не предполагает ограничения на размер и подобных контрактов, 48 | * но в данном случае это было введено для упрощения кода. 49 | */ 50 | override fun add(element: T): Boolean { 51 | val startingIndex = element.startingIndex() 52 | var index = startingIndex 53 | var current = storage[index] 54 | while (current != null) { 55 | if (current == element) { 56 | return false 57 | } 58 | index = (index + 1) % capacity 59 | check(index != startingIndex) { "Table is full" } 60 | current = storage[index] 61 | } 62 | storage[index] = element 63 | size++ 64 | return true 65 | } 66 | 67 | /** 68 | * Удаление элемента из таблицы 69 | * 70 | * Если элемент есть в таблице, функция удаляет его из дерева и возвращает true. 71 | * В ином случае функция оставляет множество нетронутым и возвращает false. 72 | * Высота дерева не должна увеличиться в результате удаления. 73 | * 74 | * Спецификация: [java.util.Set.remove] (Ctrl+Click по remove) 75 | * 76 | * Средняя 77 | */ 78 | override fun remove(element: T): Boolean { 79 | TODO("not implemented") 80 | } 81 | 82 | /** 83 | * Создание итератора для обхода таблицы 84 | * 85 | * Не забываем, что итератор должен поддерживать функции next(), hasNext(), 86 | * и опционально функцию remove() 87 | * 88 | * Спецификация: [java.util.Iterator] (Ctrl+Click по Iterator) 89 | * 90 | * Средняя (сложная, если поддержан и remove тоже) 91 | */ 92 | override fun iterator(): MutableIterator { 93 | TODO("not implemented") 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/lesson5/OpenAddressingSet.java: -------------------------------------------------------------------------------- 1 | package lesson5; 2 | 3 | import kotlin.NotImplementedError; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.AbstractSet; 7 | import java.util.Iterator; 8 | import java.util.Set; 9 | 10 | public class OpenAddressingSet extends AbstractSet { 11 | 12 | private final int bits; 13 | 14 | private final int capacity; 15 | 16 | private final Object[] storage; 17 | 18 | private int size = 0; 19 | 20 | private int startingIndex(Object element) { 21 | return element.hashCode() & (0x7FFFFFFF >> (31 - bits)); 22 | } 23 | 24 | public OpenAddressingSet(int bits) { 25 | if (bits < 2 || bits > 31) { 26 | throw new IllegalArgumentException(); 27 | } 28 | this.bits = bits; 29 | capacity = 1 << bits; 30 | storage = new Object[capacity]; 31 | } 32 | 33 | @Override 34 | public int size() { 35 | return size; 36 | } 37 | 38 | /** 39 | * Проверка, входит ли данный элемент в таблицу 40 | */ 41 | @Override 42 | public boolean contains(Object o) { 43 | int index = startingIndex(o); 44 | Object current = storage[index]; 45 | while (current != null) { 46 | if (current.equals(o)) { 47 | return true; 48 | } 49 | index = (index + 1) % capacity; 50 | current = storage[index]; 51 | } 52 | return false; 53 | } 54 | 55 | /** 56 | * Добавление элемента в таблицу. 57 | * 58 | * Не делает ничего и возвращает false, если такой же элемент уже есть в таблице. 59 | * В противном случае вставляет элемент в таблицу и возвращает true. 60 | * 61 | * Бросает исключение (IllegalStateException) в случае переполнения таблицы. 62 | * Обычно Set не предполагает ограничения на размер и подобных контрактов, 63 | * но в данном случае это было введено для упрощения кода. 64 | */ 65 | @Override 66 | public boolean add(T t) { 67 | int startingIndex = startingIndex(t); 68 | int index = startingIndex; 69 | Object current = storage[index]; 70 | while (current != null) { 71 | if (current.equals(t)) { 72 | return false; 73 | } 74 | index = (index + 1) % capacity; 75 | if (index == startingIndex) { 76 | throw new IllegalStateException("Table is full"); 77 | } 78 | current = storage[index]; 79 | } 80 | storage[index] = t; 81 | size++; 82 | return true; 83 | } 84 | 85 | /** 86 | * Удаление элемента из таблицы 87 | * 88 | * Если элемент есть в таблица, функция удаляет его из дерева и возвращает true. 89 | * В ином случае функция оставляет множество нетронутым и возвращает false. 90 | * Высота дерева не должна увеличиться в результате удаления. 91 | * 92 | * Спецификация: {@link Set#remove(Object)} (Ctrl+Click по remove) 93 | * 94 | * Средняя 95 | */ 96 | @Override 97 | public boolean remove(Object o) { 98 | return super.remove(o); 99 | } 100 | 101 | /** 102 | * Создание итератора для обхода таблицы 103 | * 104 | * Не забываем, что итератор должен поддерживать функции next(), hasNext(), 105 | * и опционально функцию remove() 106 | * 107 | * Спецификация: {@link Iterator} (Ctrl+Click по Iterator) 108 | * 109 | * Средняя (сложная, если поддержан и remove тоже) 110 | */ 111 | @NotNull 112 | @Override 113 | public Iterator iterator() { 114 | // TODO 115 | throw new NotImplementedError(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/lesson6/Bridges.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | fun Graph.findBridges(): Set = 4 | BridgeTraverser(this).findBridges() 5 | 6 | private class BridgeTraverser(val graph: Graph) { 7 | val visitedVertices = mutableSetOf() 8 | 9 | var traverseIndex = 0 10 | 11 | class Info(var inIndex: Int, var bridgeIndex: Int) { 12 | constructor(index: Int) : this(index, index) 13 | } 14 | 15 | val verticesInfo = mutableMapOf() 16 | 17 | val bridges = mutableSetOf() 18 | 19 | fun findBridges(): Set { 20 | for (vertex in graph.vertices) { 21 | if (vertex in visitedVertices) continue 22 | traverse(vertex, null) 23 | } 24 | return bridges 25 | } 26 | 27 | fun traverse(current: Graph.Vertex, previous: Graph.Vertex?) { 28 | visitedVertices += current 29 | verticesInfo[current] = Info(traverseIndex) 30 | traverseIndex++ 31 | for ((next, edge) in graph.getConnections(current)) { 32 | if (next == previous) continue 33 | val currentInfo = verticesInfo[current]!! 34 | if (next in visitedVertices) { 35 | val nextInfo = verticesInfo[next]!! 36 | currentInfo.bridgeIndex = minOf(currentInfo.bridgeIndex, nextInfo.inIndex) 37 | } else { 38 | traverse(next, current) 39 | val nextInfo = verticesInfo[next]!! 40 | currentInfo.bridgeIndex = minOf(currentInfo.bridgeIndex, nextInfo.bridgeIndex) 41 | if (nextInfo.bridgeIndex > currentInfo.inIndex) { 42 | bridges += edge 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/lesson6/Dijkstra.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.Graph.Vertex 4 | import java.util.* 5 | 6 | class VertexInfo( 7 | val vertex: Vertex, 8 | val distance: Int, 9 | val prev: Vertex? 10 | ) : Comparable { 11 | override fun compareTo(other: VertexInfo): Int { 12 | return distance.compareTo(other.distance) 13 | } 14 | } 15 | 16 | fun Graph.shortestPath(from: Vertex): Map { 17 | val info = mutableMapOf() 18 | for (vertex in this.vertices) { 19 | info[vertex] = VertexInfo(vertex, Int.MAX_VALUE, null) 20 | } 21 | val visited = mutableSetOf() 22 | val fromInfo = VertexInfo(from, 0, null) 23 | val queue = PriorityQueue() 24 | queue.add(fromInfo) 25 | info[from] = fromInfo 26 | while (queue.isNotEmpty()) { 27 | val currentInfo = queue.poll() 28 | val currentVertex = currentInfo.vertex 29 | visited += currentVertex 30 | for (vertex in this.getNeighbors(currentVertex)) { 31 | if (vertex in visited) continue 32 | val weight = this.getConnection(currentVertex, vertex)?.weight 33 | if (weight != null) { 34 | val newDistance = info[currentVertex]!!.distance + weight 35 | if (info[vertex]!!.distance > newDistance) { 36 | val newInfo = VertexInfo(vertex, newDistance, currentVertex) 37 | queue.add(newInfo) 38 | info[vertex] = newInfo 39 | } 40 | } 41 | } 42 | } 43 | return info 44 | } 45 | 46 | fun Map.unrollPath(to: Vertex): List { 47 | val result = mutableListOf() 48 | var current: Vertex? = to 49 | while (current != null) { 50 | result += current 51 | current = this[current]?.prev 52 | } 53 | result.reverse() 54 | return result 55 | } -------------------------------------------------------------------------------- /src/lesson6/Graph.java: -------------------------------------------------------------------------------- 1 | package lesson6; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.util.Map; 7 | import java.util.Set; 8 | 9 | public interface Graph { 10 | 11 | interface Vertex { 12 | @NotNull 13 | String getName(); 14 | } 15 | 16 | interface Edge { 17 | @NotNull 18 | Vertex getBegin(); 19 | 20 | @NotNull 21 | Vertex getEnd(); 22 | 23 | default int getWeight() { 24 | return 1; 25 | } 26 | } 27 | 28 | @NotNull 29 | Set getVertices(); 30 | 31 | @NotNull 32 | Set getEdges(); 33 | 34 | @Nullable 35 | Vertex get(String name); 36 | 37 | @NotNull 38 | default Set getNeighbors(@NotNull Vertex v) { 39 | return getConnections(v).keySet(); 40 | } 41 | 42 | @NotNull 43 | Map getConnections(@NotNull Vertex v); 44 | 45 | @Nullable 46 | default Edge getConnection(@NotNull Vertex v1, @NotNull Vertex v2) { 47 | return getConnections(v1).get(v2); 48 | } 49 | } -------------------------------------------------------------------------------- /src/lesson6/GraphTasks.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_PARAMETER", "unused") 2 | 3 | package lesson6 4 | 5 | /** 6 | * Эйлеров цикл. 7 | * Средняя 8 | * 9 | * Дан граф (получатель). Найти по нему любой Эйлеров цикл. 10 | * Если в графе нет Эйлеровых циклов, вернуть пустой список. 11 | * Соседние дуги в списке-результате должны быть инцидентны друг другу, 12 | * а первая дуга в списке инцидентна последней. 13 | * Длина списка, если он не пуст, должна быть равна количеству дуг в графе. 14 | * Веса дуг никак не учитываются. 15 | * 16 | * Пример: 17 | * 18 | * G -- H 19 | * | | 20 | * A -- B -- C -- D 21 | * | | | | 22 | * E F -- I | 23 | * | | 24 | * J ------------ K 25 | * 26 | * Вариант ответа: A, E, J, K, D, C, H, G, B, C, I, F, B, A 27 | * 28 | * Справка: Эйлеров цикл -- это цикл, проходящий через все рёбра 29 | * связного графа ровно по одному разу 30 | */ 31 | fun Graph.findEulerLoop(): List { 32 | TODO() 33 | } 34 | 35 | /** 36 | * Минимальное остовное дерево. 37 | * Средняя 38 | * 39 | * Дан связный граф (получатель). Найти по нему минимальное остовное дерево. 40 | * Если есть несколько минимальных остовных деревьев с одинаковым числом дуг, 41 | * вернуть любое из них. Веса дуг не учитывать. 42 | * 43 | * Пример: 44 | * 45 | * G -- H 46 | * | | 47 | * A -- B -- C -- D 48 | * | | | | 49 | * E F -- I | 50 | * | | 51 | * J ------------ K 52 | * 53 | * Ответ: 54 | * 55 | * G H 56 | * | | 57 | * A -- B -- C -- D 58 | * | | | 59 | * E F I 60 | * | 61 | * J ------------ K 62 | */ 63 | fun Graph.minimumSpanningTree(): Graph { 64 | TODO() 65 | } 66 | 67 | /** 68 | * Максимальное независимое множество вершин в графе без циклов. 69 | * Сложная 70 | * 71 | * Дан граф без циклов (получатель), например 72 | * 73 | * G -- H -- J 74 | * | 75 | * A -- B -- D 76 | * | | 77 | * C -- F I 78 | * | 79 | * E 80 | * 81 | * Найти в нём самое большое независимое множество вершин и вернуть его. 82 | * Никакая пара вершин в независимом множестве не должна быть связана ребром. 83 | * 84 | * Если самых больших множеств несколько, приоритет имеет то из них, 85 | * в котором вершины расположены раньше во множестве this.vertices (начиная с первых). 86 | * 87 | * В данном случае ответ (A, E, F, D, G, J) 88 | * 89 | * Если на входе граф с циклами, бросить IllegalArgumentException 90 | */ 91 | fun Graph.largestIndependentVertexSet(): Set { 92 | TODO() 93 | } 94 | 95 | /** 96 | * Наидлиннейший простой путь. 97 | * Сложная 98 | * 99 | * Дан граф (получатель). Найти в нём простой путь, включающий максимальное количество рёбер. 100 | * Простым считается путь, вершины в котором не повторяются. 101 | * Если таких путей несколько, вернуть любой из них. 102 | * 103 | * Пример: 104 | * 105 | * G -- H 106 | * | | 107 | * A -- B -- C -- D 108 | * | | | | 109 | * E F -- I | 110 | * | | 111 | * J ------------ K 112 | * 113 | * Ответ: A, E, J, K, D, C, H, G, B, F, I 114 | */ 115 | fun Graph.longestSimplePath(): Path { 116 | TODO() 117 | } 118 | 119 | /** 120 | * Балда 121 | * Сложная 122 | * 123 | * Задача хоть и не использует граф напрямую, но решение базируется на тех же алгоритмах - 124 | * поэтому задача присутствует в этом разделе 125 | * 126 | * В файле с именем inputName задана матрица из букв в следующем формате 127 | * (отдельные буквы в ряду разделены пробелами): 128 | * 129 | * И Т Ы Н 130 | * К Р А Н 131 | * А К В А 132 | * 133 | * В аргументе words содержится множество слов для поиска, например, 134 | * ТРАВА, КРАН, АКВА, НАРТЫ, РАК. 135 | * 136 | * Попытаться найти каждое из слов в матрице букв, используя правила игры БАЛДА, 137 | * и вернуть множество найденных слов. В данном случае: 138 | * ТРАВА, КРАН, АКВА, НАРТЫ 139 | * 140 | * И т Ы Н И т ы Н 141 | * К р а Н К р а н 142 | * А К в а А К В А 143 | * 144 | * Все слова и буквы -- русские или английские, прописные. 145 | * В файле буквы разделены пробелами, строки -- переносами строк. 146 | * Остальные символы ни в файле, ни в словах не допускаются. 147 | */ 148 | fun baldaSearcher(inputName: String, words: Set): Set { 149 | TODO() 150 | } 151 | -------------------------------------------------------------------------------- /src/lesson6/JavaGraphTasks.java: -------------------------------------------------------------------------------- 1 | package lesson6; 2 | 3 | import kotlin.NotImplementedError; 4 | 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | @SuppressWarnings("unused") 9 | public class JavaGraphTasks { 10 | /** 11 | * Эйлеров цикл. 12 | * Средняя 13 | * 14 | * Дан граф (получатель). Найти по нему любой Эйлеров цикл. 15 | * Если в графе нет Эйлеровых циклов, вернуть пустой список. 16 | * Соседние дуги в списке-результате должны быть инцидентны друг другу, 17 | * а первая дуга в списке инцидентна последней. 18 | * Длина списка, если он не пуст, должна быть равна количеству дуг в графе. 19 | * Веса дуг никак не учитываются. 20 | * 21 | * Пример: 22 | * 23 | * G -- H 24 | * | | 25 | * A -- B -- C -- D 26 | * | | | | 27 | * E F -- I | 28 | * | | 29 | * J ------------ K 30 | * 31 | * Вариант ответа: A, E, J, K, D, C, H, G, B, C, I, F, B, A 32 | * 33 | * Справка: Эйлеров цикл -- это цикл, проходящий через все рёбра 34 | * связного графа ровно по одному разу 35 | */ 36 | public static List findEulerLoop(Graph graph) { 37 | throw new NotImplementedError(); 38 | } 39 | 40 | /** 41 | * Минимальное остовное дерево. 42 | * Средняя 43 | * 44 | * Дан связный граф (получатель). Найти по нему минимальное остовное дерево. 45 | * Если есть несколько минимальных остовных деревьев с одинаковым числом дуг, 46 | * вернуть любое из них. Веса дуг не учитывать. 47 | * 48 | * Пример: 49 | * 50 | * G -- H 51 | * | | 52 | * A -- B -- C -- D 53 | * | | | | 54 | * E F -- I | 55 | * | | 56 | * J ------------ K 57 | * 58 | * Ответ: 59 | * 60 | * G H 61 | * | | 62 | * A -- B -- C -- D 63 | * | | | 64 | * E F I 65 | * | 66 | * J ------------ K 67 | */ 68 | public static Graph minimumSpanningTree(Graph graph) { 69 | throw new NotImplementedError(); 70 | } 71 | 72 | /** 73 | * Максимальное независимое множество вершин в графе без циклов. 74 | * Сложная 75 | * 76 | * Дан граф без циклов (получатель), например 77 | * 78 | * G -- H -- J 79 | * | 80 | * A -- B -- D 81 | * | | 82 | * C -- F I 83 | * | 84 | * E 85 | * 86 | * Найти в нём самое большое независимое множество вершин и вернуть его. 87 | * Никакая пара вершин в независимом множестве не должна быть связана ребром. 88 | * 89 | * Если самых больших множеств несколько, приоритет имеет то из них, 90 | * в котором вершины расположены раньше во множестве this.vertices (начиная с первых). 91 | * 92 | * В данном случае ответ (A, E, F, D, G, J) 93 | * 94 | * Если на входе граф с циклами, бросить IllegalArgumentException 95 | */ 96 | public static Set largestIndependentVertexSet(Graph graph) { 97 | throw new NotImplementedError(); 98 | } 99 | 100 | /** 101 | * Наидлиннейший простой путь. 102 | * Сложная 103 | * 104 | * Дан граф (получатель). Найти в нём простой путь, включающий максимальное количество рёбер. 105 | * Простым считается путь, вершины в котором не повторяются. 106 | * Если таких путей несколько, вернуть любой из них. 107 | * 108 | * Пример: 109 | * 110 | * G -- H 111 | * | | 112 | * A -- B -- C -- D 113 | * | | | | 114 | * E F -- I | 115 | * | | 116 | * J ------------ K 117 | * 118 | * Ответ: A, E, J, K, D, C, H, G, B, F, I 119 | */ 120 | public static Path longestSimplePath(Graph graph) { 121 | throw new NotImplementedError(); 122 | } 123 | 124 | 125 | /** 126 | * Балда 127 | * Сложная 128 | * 129 | * Задача хоть и не использует граф напрямую, но решение базируется на тех же алгоритмах - 130 | * поэтому задача присутствует в этом разделе 131 | * 132 | * В файле с именем inputName задана матрица из букв в следующем формате 133 | * (отдельные буквы в ряду разделены пробелами): 134 | * 135 | * И Т Ы Н 136 | * К Р А Н 137 | * А К В А 138 | * 139 | * В аргументе words содержится множество слов для поиска, например, 140 | * ТРАВА, КРАН, АКВА, НАРТЫ, РАК. 141 | * 142 | * Попытаться найти каждое из слов в матрице букв, используя правила игры БАЛДА, 143 | * и вернуть множество найденных слов. В данном случае: 144 | * ТРАВА, КРАН, АКВА, НАРТЫ 145 | * 146 | * И т Ы Н И т ы Н 147 | * К р а Н К р а н 148 | * А К в а А К В А 149 | * 150 | * Все слова и буквы -- русские или английские, прописные. 151 | * В файле буквы разделены пробелами, строки -- переносами строк. 152 | * Остальные символы ни в файле, ни в словах не допускаются. 153 | */ 154 | static public Set baldaSearcher(String inputName, Set words) { 155 | throw new NotImplementedError(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/lesson6/NoughtsAndCrosses.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | class NoughtsAndCrosses() { 4 | 5 | data class Cell(val x: Int, val y: Int) 6 | 7 | private val field = mutableMapOf() 8 | 9 | constructor(original: NoughtsAndCrosses) : this() { 10 | field.putAll(original.field) 11 | } 12 | 13 | fun makeTurn(x: Int, y: Int, isCross: Boolean): Boolean { 14 | val cell = Cell(x, y) 15 | if (cell in field) return false 16 | field[cell] = isCross 17 | return true 18 | } 19 | 20 | private val winningLines = listOf( 21 | listOf(Cell(0, 0), Cell(0, 1), Cell(0, 2)), 22 | listOf(Cell(1, 0), Cell(1, 1), Cell(1, 2)), 23 | listOf(Cell(2, 0), Cell(2, 1), Cell(2, 2)), 24 | listOf(Cell(0, 0), Cell(1, 0), Cell(2, 0)), 25 | listOf(Cell(0, 1), Cell(1, 1), Cell(2, 1)), 26 | listOf(Cell(0, 2), Cell(1, 2), Cell(2, 2)), 27 | listOf(Cell(0, 0), Cell(1, 1), Cell(2, 2)), 28 | listOf(Cell(0, 2), Cell(1, 1), Cell(2, 0)) 29 | ) 30 | 31 | fun findWinnerIfAny(): Boolean? { 32 | for (line in winningLines) { 33 | if (line.all { field[it] == true }) return true 34 | if (line.all { field[it] == false }) return false 35 | } 36 | return null 37 | } 38 | 39 | fun findBestMoveAndEvaluation(crossesTurn: Boolean, depth: Int = 0): Pair { 40 | when (findWinnerIfAny()) { 41 | crossesTurn -> return null to 10 - depth 42 | !crossesTurn -> return null to -10 + depth 43 | else -> { 44 | var bestMove: Pair = null to -11 45 | for (x in 0..2) { 46 | for (y in 0..2) { 47 | val move = Cell(x, y) 48 | if (move in field) continue 49 | val copy = NoughtsAndCrosses(this) 50 | copy.makeTurn(x, y, crossesTurn) 51 | val evaluation = -copy.findBestMoveAndEvaluation(!crossesTurn, depth + 1).second 52 | if (evaluation > bestMove.second) { 53 | bestMove = move to evaluation 54 | } 55 | } 56 | } 57 | if (bestMove.first == null) { 58 | return null to 0 59 | } 60 | return bestMove 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/lesson6/Voyager.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.Graph.Vertex 4 | 5 | class Path private constructor( 6 | val vertices: List, 7 | val length: Int 8 | ) : Comparable { 9 | override fun compareTo(other: Path) = length.compareTo(other.length) 10 | 11 | fun isLoop(graph: Graph): Boolean = 12 | vertices.size == graph.vertices.size + 1 && vertices.first() == vertices.last() 13 | 14 | operator fun contains(v: Vertex) = v in vertices 15 | 16 | constructor(first: Vertex) : this(listOf(first), 0) 17 | 18 | constructor() : this(emptyList(), 0) 19 | 20 | constructor(previous: Path, g: Graph, next: Vertex) : this( 21 | previous.vertices + next, 22 | previous.length + g.getConnection(previous.vertices.last(), next)!!.weight 23 | ) 24 | 25 | override fun toString() = "<$vertices of length $length>" 26 | } 27 | 28 | fun findVoyagingPath( 29 | g: Graph, 30 | currentPath: Path = Path(g.vertices.first()), 31 | bestPath: Path? = null 32 | ): Path? { 33 | var best = bestPath 34 | for (next in g.getNeighbors(currentPath.vertices.last())) { 35 | if (next != g.vertices.first() && next in currentPath) continue 36 | val nextPath = Path(currentPath, g, next) 37 | if (best != null && best.length <= nextPath.length) continue 38 | val cyclePath = if (nextPath.isLoop(g)) { 39 | nextPath 40 | } else { 41 | findVoyagingPath(g, nextPath, best) ?: continue 42 | } 43 | if (best == null || best.length > cyclePath.length) { 44 | best = cyclePath 45 | } 46 | } 47 | return best 48 | } 49 | -------------------------------------------------------------------------------- /src/lesson6/impl/Graph.kt: -------------------------------------------------------------------------------- 1 | package lesson6.impl 2 | 3 | import lesson6.Graph.Edge 4 | import lesson6.Graph 5 | import lesson6.Graph.Vertex 6 | 7 | class GraphBuilder { 8 | 9 | data class VertexImpl(private val nameField: String) : Vertex { 10 | override fun getName() = nameField 11 | 12 | override fun toString() = name 13 | } 14 | 15 | data class EdgeImpl( 16 | private val weightField: Int, 17 | private val _begin: Vertex, 18 | private val _end: Vertex 19 | ) : Edge { 20 | override fun getBegin() = _begin 21 | 22 | override fun getEnd() = _end 23 | 24 | override fun getWeight() = weightField 25 | } 26 | 27 | private val vertices = mutableMapOf() 28 | 29 | private val connections = mutableMapOf>() 30 | 31 | private fun addVertex(v: Vertex) { 32 | vertices[v.name] = v 33 | } 34 | 35 | fun addVertex(name: String): Vertex { 36 | return VertexImpl(name).apply { 37 | addVertex(this) 38 | } 39 | } 40 | 41 | fun addConnection(begin: Vertex, end: Vertex, weight: Int = 1) { 42 | val edge = EdgeImpl(weight, begin, end) 43 | connections[begin] = connections[begin]?.let { it + edge } ?: setOf(edge) 44 | connections[end] = connections[end]?.let { it + edge } ?: setOf(edge) 45 | } 46 | 47 | fun build(): Graph = object : Graph { 48 | 49 | override fun get(name: String): Vertex? = this@GraphBuilder.vertices[name] 50 | 51 | override fun getVertices(): Set = this@GraphBuilder.vertices.values.toSet() 52 | 53 | override fun getEdges(): Set { 54 | return connections.values.flatten().toSet() 55 | } 56 | 57 | override fun getConnections(v: Vertex): Map { 58 | val edges = connections[v] ?: emptySet() 59 | val result = mutableMapOf() 60 | for (edge in edges) { 61 | when (v) { 62 | edge.begin -> result[edge.end] = edge 63 | edge.end -> result[edge.begin] = edge 64 | } 65 | } 66 | return result 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/lesson7/DynamicTasks.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_PARAMETER") 2 | 3 | package lesson7 4 | 5 | /** 6 | * Наибольшая общая подпоследовательность. 7 | * Средняя 8 | * 9 | * Дано две строки, например "nematode knowledge" и "empty bottle". 10 | * Найти их самую длинную общую подпоследовательность -- в примере это "emt ole". 11 | * Подпоследовательность отличается от подстроки тем, что её символы не обязаны идти подряд 12 | * (но по-прежнему должны быть расположены в исходной строке в том же порядке). 13 | * Если общей подпоследовательности нет, вернуть пустую строку. 14 | * Если есть несколько самых длинных общих подпоследовательностей, вернуть любую из них. 15 | * При сравнении подстрок, регистр символов *имеет* значение. 16 | */ 17 | fun longestCommonSubSequence(first: String, second: String): String { 18 | TODO() 19 | } 20 | 21 | /** 22 | * Наибольшая возрастающая подпоследовательность 23 | * Сложная 24 | * 25 | * Дан список целых чисел, например, [2 8 5 9 12 6]. 26 | * Найти в нём самую длинную возрастающую подпоследовательность. 27 | * Элементы подпоследовательности не обязаны идти подряд, 28 | * но должны быть расположены в исходном списке в том же порядке. 29 | * Если самых длинных возрастающих подпоследовательностей несколько (как в примере), 30 | * то вернуть ту, в которой числа расположены раньше (приоритет имеют первые числа). 31 | * В примере ответами являются 2, 8, 9, 12 или 2, 5, 9, 12 -- выбираем первую из них. 32 | */ 33 | fun longestIncreasingSubSequence(list: List): List { 34 | TODO() 35 | } 36 | 37 | /** 38 | * Самый короткий маршрут на прямоугольном поле. 39 | * Средняя 40 | * 41 | * В файле с именем inputName задано прямоугольное поле: 42 | * 43 | * 0 2 3 2 4 1 44 | * 1 5 3 4 6 2 45 | * 2 6 2 5 1 3 46 | * 1 4 3 2 6 2 47 | * 4 2 3 1 5 0 48 | * 49 | * Можно совершать шаги длиной в одну клетку вправо, вниз или по диагонали вправо-вниз. 50 | * В каждой клетке записано некоторое натуральное число или нуль. 51 | * Необходимо попасть из верхней левой клетки в правую нижнюю. 52 | * Вес маршрута вычисляется как сумма чисел со всех посещенных клеток. 53 | * Необходимо найти маршрут с минимальным весом и вернуть этот минимальный вес. 54 | * 55 | * Здесь ответ 2 + 3 + 4 + 1 + 2 = 12 56 | */ 57 | fun shortestPathOnField(inputName: String): Int { 58 | TODO() 59 | } 60 | -------------------------------------------------------------------------------- /src/lesson7/JavaDynamicTasks.java: -------------------------------------------------------------------------------- 1 | package lesson7; 2 | 3 | import kotlin.NotImplementedError; 4 | 5 | import java.util.List; 6 | 7 | @SuppressWarnings("unused") 8 | public class JavaDynamicTasks { 9 | /** 10 | * Наибольшая общая подпоследовательность. 11 | * Средняя 12 | * 13 | * Дано две строки, например "nematode knowledge" и "empty bottle". 14 | * Найти их самую длинную общую подпоследовательность -- в примере это "emt ole". 15 | * Подпоследовательность отличается от подстроки тем, что её символы не обязаны идти подряд 16 | * (но по-прежнему должны быть расположены в исходной строке в том же порядке). 17 | * Если общей подпоследовательности нет, вернуть пустую строку. 18 | * Если есть несколько самых длинных общих подпоследовательностей, вернуть любую из них. 19 | * При сравнении подстрок, регистр символов *имеет* значение. 20 | */ 21 | public static String longestCommonSubSequence(String first, String second) { 22 | throw new NotImplementedError(); 23 | } 24 | 25 | /** 26 | * Наибольшая возрастающая подпоследовательность 27 | * Сложная 28 | * 29 | * Дан список целых чисел, например, [2 8 5 9 12 6]. 30 | * Найти в нём самую длинную возрастающую подпоследовательность. 31 | * Элементы подпоследовательности не обязаны идти подряд, 32 | * но должны быть расположены в исходном списке в том же порядке. 33 | * Если самых длинных возрастающих подпоследовательностей несколько (как в примере), 34 | * то вернуть ту, в которой числа расположены раньше (приоритет имеют первые числа). 35 | * В примере ответами являются 2, 8, 9, 12 или 2, 5, 9, 12 -- выбираем первую из них. 36 | */ 37 | public static List longestIncreasingSubSequence(List list) { 38 | throw new NotImplementedError(); 39 | } 40 | 41 | /** 42 | * Самый короткий маршрут на прямоугольном поле. 43 | * Средняя 44 | * 45 | * В файле с именем inputName задано прямоугольное поле: 46 | * 47 | * 0 2 3 2 4 1 48 | * 1 5 3 4 6 2 49 | * 2 6 2 5 1 3 50 | * 1 4 3 2 6 2 51 | * 4 2 3 1 5 0 52 | * 53 | * Можно совершать шаги длиной в одну клетку вправо, вниз или по диагонали вправо-вниз. 54 | * В каждой клетке записано некоторое натуральное число или нуль. 55 | * Необходимо попасть из верхней левой клетки в правую нижнюю. 56 | * Вес маршрута вычисляется как сумма чисел со всех посещенных клеток. 57 | * Необходимо найти маршрут с минимальным весом и вернуть этот минимальный вес. 58 | * 59 | * Здесь ответ 2 + 3 + 4 + 1 + 2 = 12 60 | */ 61 | public static int shortestPathOnField(String inputName) { 62 | throw new NotImplementedError(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/lesson7/fibonacci/Fib.kt: -------------------------------------------------------------------------------- 1 | package lesson7.fibonacci 2 | 3 | private val storage = hashMapOf(0 to 0L, 1 to 1L) 4 | 5 | fun fib(n: Int): Long = storage.getOrPut(n) { fib(n - 1) + fib(n - 2) } 6 | 7 | fun fib2(n: Int): Long = if (n < 2) n.toLong() else fib2(n - 1) + fib2(n - 2) 8 | 9 | fun main() { 10 | println(fib(4)) 11 | println(fib(6)) 12 | println(fib(10)) 13 | println(fib(20)) 14 | println(fib(30)) 15 | println(fib(40)) 16 | println(fib(50)) 17 | println(fib2(4)) 18 | println(fib2(6)) 19 | println(fib2(10)) 20 | println(fib2(20)) 21 | println(fib2(30)) 22 | println(fib2(40)) 23 | println(fib2(50)) 24 | } -------------------------------------------------------------------------------- /src/lesson7/knapsack/Knapsack.kt: -------------------------------------------------------------------------------- 1 | package lesson7.knapsack 2 | 3 | import java.util.* 4 | 5 | data class Fill(val cost: Int, val items: Set) { 6 | operator fun plus(fill: Fill) = Fill(cost + fill.cost, items + fill.items) 7 | 8 | constructor(cost: Int, vararg items: Item) : this(cost, items.toSet()) 9 | 10 | constructor(item: Item) : this(item.cost, item) 11 | } 12 | 13 | data class LoadCount(val load: Int, val count: Int) 14 | 15 | data class Item(val cost: Int, val weight: Int) 16 | 17 | fun fillKnapsackDynamic( 18 | load: Int, items: List, 19 | storage: HashMap = hashMapOf() 20 | ): Fill { 21 | if (load <= 0 || items.isEmpty()) return Fill(0, emptySet()) 22 | val loadCount = LoadCount(load, items.size) 23 | return storage.getOrPut(loadCount) { 24 | val itemsWithoutLast = items.subList(0, items.size - 1) 25 | val fillWithoutLast = fillKnapsackDynamic(load, itemsWithoutLast, storage) 26 | val last = items.last() 27 | if (last.weight > load) fillWithoutLast 28 | else { 29 | val fillWithLast = fillKnapsackDynamic(load - last.weight, itemsWithoutLast, storage) + Fill(last) 30 | if (fillWithLast.cost > fillWithoutLast.cost) fillWithLast 31 | else fillWithoutLast 32 | } 33 | } 34 | } 35 | 36 | private tailrec fun fillKnapsackGreedySorted(load: Int, items: List, baseFill: Fill = Fill(0)): Fill { 37 | if (load <= 0 || items.isEmpty()) return baseFill 38 | val itemsWithoutLast = items.subList(0, items.size - 1) 39 | val last = items.last() 40 | return fillKnapsackGreedySorted( 41 | if (last.weight > load) load else load - last.weight, itemsWithoutLast, 42 | if (last.weight > load) baseFill else baseFill + Fill(last) 43 | ) 44 | } 45 | 46 | fun fillKnapsackGreedy(load: Int, items: List): Fill { 47 | val sorted = items.sortedWith(Comparator { o1, o2 -> 48 | (o1.cost.toDouble() / o1.weight).compareTo(o2.cost.toDouble() / o2.weight) 49 | }) 50 | return fillKnapsackGreedySorted(load, sorted) 51 | } 52 | 53 | fun main() { 54 | val items = listOf(Item(8, 10), Item(5, 12), Item(6, 8), Item(10, 15), Item(4, 2)) 55 | println(fillKnapsackDynamic(30, items)) 56 | println(fillKnapsackGreedy(30, items)) 57 | } -------------------------------------------------------------------------------- /src/lesson7/rod/Cut.kt: -------------------------------------------------------------------------------- 1 | package lesson7.rod 2 | 3 | data class Cut(val cost: Int, val length: List) { 4 | operator fun plus(cut: Cut) = Cut(cost + cut.cost, length + cut.length) 5 | 6 | constructor(cost: Int, vararg length: Int) : this(cost, length.asList()) 7 | } 8 | 9 | fun cutRod(n: Int, storage: MutableMap = hashMapOf(), cost: (Int) -> Int): Cut = storage.getOrPut(n) { 10 | var best = Cut(cost(n), n) 11 | for (first in 1 until n) { 12 | val current = Cut(cost(first), first) + cutRod(n - first, storage, cost) 13 | if (current.cost > best.cost) { 14 | best = current 15 | } 16 | } 17 | best 18 | } 19 | 20 | private val cost = mapOf(1 to 1, 2 to 5, 3 to 9, 4 to 9, 5 to 10, 6 to 17, 7 to 17, 8 to 20, 9 to 24) 21 | 22 | fun main() { 23 | println(cutRod(20) { cost[it] ?: 0 }) 24 | println(cutRod(10) { cost[it] ?: 0 }) 25 | println(cutRod(8) { cost[it] ?: 0 }) 26 | } -------------------------------------------------------------------------------- /src/lesson8/AbstractVoyagingPathSearcher.kt: -------------------------------------------------------------------------------- 1 | package lesson8 2 | 3 | import lesson6.Graph 4 | import lesson6.Path 5 | import java.util.* 6 | 7 | abstract class AbstractVoyagingPathSearcher(private val g: Graph) { 8 | protected val size = g.vertices.size 9 | private val vertexByIndex: MutableMap = mutableMapOf() 10 | protected val random = Random() 11 | 12 | init { 13 | for ((index, vertex) in g.vertices.withIndex()) { 14 | vertexByIndex[index] = vertex 15 | } 16 | } 17 | 18 | protected fun List.evaluation(): Int { 19 | var result = 0 20 | for (i in 0 until size) { 21 | val previousVertex = vertexByIndex[this[i]]!! 22 | val nextVertex = vertexByIndex[this[if (i < size - 1) i + 1 else 0]]!! 23 | val edge = g.getConnection(previousVertex, nextVertex) 24 | result += edge?.weight ?: 1000000 25 | } 26 | return result 27 | } 28 | 29 | protected fun List.buildPath(): Path { 30 | var path = Path(vertexByIndex[this[0]]!!) 31 | for (i in 1 until size) { 32 | path = Path(path, g, vertexByIndex[this[i]]!!) 33 | } 34 | return Path(path, g, vertexByIndex[this[0]]!!) 35 | } 36 | 37 | abstract fun findVoyagingPath(): Path 38 | } -------------------------------------------------------------------------------- /src/lesson8/HeuristicsTasks.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_PARAMETER", "unused") 2 | 3 | package lesson8 4 | 5 | import lesson6.Graph 6 | import lesson6.Path 7 | import lesson7.knapsack.Fill 8 | import lesson7.knapsack.Item 9 | 10 | // Примечание: в этом уроке достаточно решить одну задачу 11 | 12 | /** 13 | * Решить задачу о ранце (см. урок 6) любым эвристическим методом 14 | * 15 | * Очень сложная 16 | * 17 | * load - общая вместимость ранца, items - список предметов 18 | * 19 | * Используйте parameters для передачи дополнительных параметров алгоритма 20 | * (не забудьте изменить тесты так, чтобы они передавали эти параметры) 21 | */ 22 | fun fillKnapsackHeuristics(load: Int, items: List, vararg parameters: Any): Fill { 23 | TODO() 24 | } 25 | 26 | /** 27 | * Решить задачу коммивояжёра (см. урок 5) методом колонии муравьёв 28 | * или любым другим эвристическим методом, кроме генетического и имитации отжига 29 | * (этими двумя методами задача уже решена в под-пакетах annealing & genetic). 30 | * 31 | * Очень сложная 32 | * 33 | * Граф передаётся через получатель метода 34 | * 35 | * Используйте parameters для передачи дополнительных параметров алгоритма 36 | * (не забудьте изменить тесты так, чтобы они передавали эти параметры) 37 | */ 38 | fun Graph.findVoyagingPathHeuristics(vararg parameters: Any): Path { 39 | TODO() 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/lesson8/JavaHeuristicsTasks.java: -------------------------------------------------------------------------------- 1 | package lesson8; 2 | 3 | import kotlin.NotImplementedError; 4 | import lesson6.Graph; 5 | import lesson6.Path; 6 | import lesson7.knapsack.Fill; 7 | import lesson7.knapsack.Item; 8 | 9 | import java.util.List; 10 | 11 | // Примечание: в этом уроке достаточно решить одну задачу 12 | @SuppressWarnings("unused") 13 | public class JavaHeuristicsTasks { 14 | 15 | /** 16 | * Решить задачу о ранце (см. урок 6) любым эвристическим методом 17 | * 18 | * Очень сложная 19 | * 20 | * load - общая вместимость ранца, items - список предметов 21 | * 22 | * Используйте parameters для передачи дополнительных параметров алгоритма 23 | * (не забудьте изменить тесты так, чтобы они передавали эти параметры) 24 | */ 25 | public static Fill fillKnapsackHeuristics(int load, List items, Object... parameters) { 26 | throw new NotImplementedError(); 27 | } 28 | 29 | /** 30 | * Решить задачу коммивояжёра (см. урок 5) методом колонии муравьёв 31 | * или любым другим эвристическим методом, кроме генетического и имитации отжига 32 | * (этими двумя методами задача уже решена в под-пакетах annealing & genetic). 33 | * 34 | * Очень сложная 35 | * 36 | * Граф передаётся через параметр graph 37 | * 38 | * Используйте parameters для передачи дополнительных параметров алгоритма 39 | * (не забудьте изменить тесты так, чтобы они передавали эти параметры) 40 | */ 41 | public static Path findVoyagingPathHeuristics(Graph graph, Object... parameters) { 42 | throw new NotImplementedError(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/lesson8/annealing/AnnealingVoyagingPathSearcher.kt: -------------------------------------------------------------------------------- 1 | package lesson8.annealing 2 | 3 | import lesson6.Graph 4 | import lesson6.Path 5 | import lesson8.AbstractVoyagingPathSearcher 6 | import kotlin.math.exp 7 | 8 | class AnnealingVoyagingPathSearcher( 9 | g: Graph, 10 | private val startTemperature: Int, 11 | private val iterationNumber: Int 12 | ) : AbstractVoyagingPathSearcher(g) { 13 | 14 | private fun List.generateNewState(): List { 15 | val newState = mutableListOf() 16 | val i = random.nextInt(size) 17 | val j = random.nextInt(size) 18 | val first = minOf(i, j) 19 | val second = maxOf(i, j) 20 | for (k in 0 until first) { 21 | newState += this[k] 22 | } 23 | for (k in second downTo first) { 24 | newState += this[k] 25 | } 26 | for (k in second + 1 until size) { 27 | newState += this[k] 28 | } 29 | assert(newState.size == size) 30 | return newState 31 | } 32 | 33 | private fun transitionProbability(evaluationIncrease: Int, temperature: Double): Double { 34 | return exp(-evaluationIncrease / temperature) 35 | } 36 | 37 | override fun findVoyagingPath(): Path { 38 | var state: List = (0 until size).toMutableList().apply { shuffle() } 39 | for (i in 1..iterationNumber) { 40 | val newState = state.generateNewState() 41 | assert(newState.size == size) 42 | val evaluation = state.evaluation() 43 | val newEvaluation = newState.evaluation() 44 | 45 | if (newEvaluation < evaluation) { 46 | state = newState 47 | } else if (random.nextDouble() < 48 | transitionProbability( 49 | newEvaluation - evaluation, 50 | startTemperature.toDouble() / i 51 | ) 52 | ) { 53 | state = newState 54 | } 55 | } 56 | return state.buildPath() 57 | } 58 | } 59 | 60 | fun Graph.findVoyagingPathAnnealing( 61 | startTemperature: Int, 62 | iterationNumber: Int, 63 | @Suppress("UNUSED_PARAMETER") vararg otherParams: Any 64 | ): Path = AnnealingVoyagingPathSearcher(this, startTemperature, iterationNumber).findVoyagingPath() -------------------------------------------------------------------------------- /src/lesson8/genetic/Chromosome.kt: -------------------------------------------------------------------------------- 1 | package lesson8.genetic 2 | 3 | import java.util.* 4 | 5 | internal class Chromosome(val visitingOrder: List) { 6 | constructor(size: Int, random: Random) : this( 7 | (0 until size).toMutableList().apply { shuffle(random) } 8 | ) 9 | 10 | fun mutate(random: Random): Chromosome = 11 | Chromosome( 12 | visitingOrder.toMutableList().apply { 13 | val first = random.nextInt(visitingOrder.size) 14 | var second: Int 15 | do { 16 | second = random.nextInt(visitingOrder.size) 17 | } while (first == second) 18 | Collections.swap(this, first, second) 19 | } 20 | ) 21 | 22 | fun crossBreed(other: Chromosome, random: Random): Chromosome { 23 | assert(visitingOrder.size == other.visitingOrder.size) 24 | val result = mutableSetOf() 25 | for ((index, vertexNumber) in visitingOrder.withIndex()) { 26 | val otherVertexNumber = other.visitingOrder[index] 27 | val resultVertexNumber = when (vertexNumber) { 28 | otherVertexNumber -> vertexNumber 29 | else -> { 30 | val (first, second) = when (random.nextBoolean()) { 31 | true -> vertexNumber to otherVertexNumber 32 | false -> otherVertexNumber to vertexNumber 33 | } 34 | when { 35 | first !in result -> first 36 | second !in result -> second 37 | else -> { 38 | var randomNumber: Int 39 | do { 40 | randomNumber = random.nextInt(visitingOrder.size) 41 | } while (randomNumber in result || 42 | visitingOrder.indexOf(randomNumber) == other.visitingOrder.indexOf(randomNumber) 43 | ) 44 | randomNumber 45 | } 46 | } 47 | } 48 | } 49 | result += resultVertexNumber 50 | } 51 | assert(result.size == visitingOrder.size) 52 | return Chromosome(result.toList()) 53 | } 54 | } -------------------------------------------------------------------------------- /src/lesson8/genetic/GeneticVoyagingPathSearcher.kt: -------------------------------------------------------------------------------- 1 | package lesson8.genetic 2 | 3 | import lesson6.Graph 4 | import lesson6.Path 5 | import lesson8.AbstractVoyagingPathSearcher 6 | 7 | class GeneticVoyagingPathSearcher( 8 | g: Graph, 9 | private val chromosomeNumber: Int, 10 | private val generationNumber: Int 11 | ) : AbstractVoyagingPathSearcher(g) { 12 | private fun generateChromosomes(number: Int): List { 13 | val result = mutableListOf() 14 | for (i in 0 until number) { 15 | result += Chromosome(size, random) 16 | } 17 | return result 18 | } 19 | 20 | private fun Chromosome.evaluation(): Int = visitingOrder.evaluation() 21 | 22 | private fun List.generateCrossBreeds(): List { 23 | val result = mutableListOf() 24 | for (i in 0 until size) { 25 | val first = this[random.nextInt(size)] 26 | val second = this[random.nextInt(size)] 27 | result += if (first === second) first else first.crossBreed(second, random) 28 | } 29 | return result 30 | } 31 | 32 | override fun findVoyagingPath(): Path { 33 | var chromosomes = generateChromosomes(chromosomeNumber) 34 | for (generation in 0 until generationNumber) { 35 | val crossBreeds = chromosomes.generateCrossBreeds() 36 | val crossBreedsAfterMutation = crossBreeds.map { 37 | if (random.nextDouble() < 0.1) it.mutate(random) else it 38 | } 39 | val evaluatedChromosomes = (chromosomes + crossBreedsAfterMutation) 40 | .sortedBy { it.evaluation() } 41 | chromosomes = evaluatedChromosomes.subList(0, chromosomeNumber) 42 | } 43 | val visitingOrder = chromosomes.first().visitingOrder 44 | return visitingOrder.buildPath() 45 | } 46 | } 47 | 48 | fun Graph.findVoyagingPathGenetically( 49 | chromosomeNumber: Int, 50 | generationNumber: Int, 51 | @Suppress("UNUSED_PARAMETER") vararg otherParams: Any 52 | ): Path = GeneticVoyagingPathSearcher(this, chromosomeNumber, generationNumber).findVoyagingPath() -------------------------------------------------------------------------------- /test/lesson1/AbstractFileTests.kt: -------------------------------------------------------------------------------- 1 | package lesson1 2 | 3 | import java.io.File 4 | import kotlin.test.assertEquals 5 | 6 | abstract class AbstractFileTests { 7 | protected fun assertFileContent(name: String, expectedContent: String) { 8 | val content = File(name).readLines().joinToString("\n") 9 | assertEquals(expectedContent.trim(), content.trim()) 10 | } 11 | 12 | protected fun assertFileContent(name: String, expectedContent: List) { 13 | var i = 0 14 | File(name).forEachLine { line -> 15 | val expectedLine = expectedContent.getOrElse(i++) { "\n" } 16 | assertEquals(expectedLine, line) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/lesson1/SortsTest.java: -------------------------------------------------------------------------------- 1 | package lesson1; 2 | 3 | import org.junit.jupiter.api.Tag; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.util.Calendar; 7 | import java.util.Random; 8 | 9 | import static org.junit.jupiter.api.Assertions.*; 10 | 11 | @SuppressWarnings("WeakerAccess") 12 | public class SortsTest { 13 | 14 | static private final Random r = new Random(Calendar.getInstance().getTimeInMillis()); 15 | 16 | private static void assertSorted(int[] arr, String prefix) { 17 | for (int i = 0; i< arr.length-1; i++) { 18 | assertTrue(arr[i] <= arr[i+1], 19 | prefix + " ERROR: i = " + i + " a[i] = " + arr[i] + " a[i+1] = " + arr[i+1]); 20 | } 21 | } 22 | 23 | private static > void assertSorted(T[] arr, String prefix) { 24 | for (int i = 0; i< arr.length-1; i++) { 25 | assertTrue(arr[i].compareTo(arr[i+1]) <= 0, 26 | prefix + " ERROR: i = " + i + " a[i] = " + arr[i] + " a[i+1] = " + arr[i+1]); 27 | } 28 | } 29 | 30 | @Test 31 | @Tag("Example") 32 | public void insertionSort() { 33 | int[] arr = new int[] { 3, 7, 5, 9, 1, 6, 19, 13 }; 34 | Sorts.insertionSort(arr); 35 | assertSorted(arr, "INSERTION SORT"); 36 | } 37 | 38 | @Test 39 | @Tag("Example") 40 | public void insertionSortStrings() { 41 | String[] arr = new String[] { "beta", "omega", "alpha", "", "!!!", "teta", "O" }; 42 | Sorts.insertionSort(arr); 43 | assertSorted(arr, "INSERTION SORT"); 44 | } 45 | 46 | @Test 47 | @Tag("Example") 48 | public void mergeSort() { 49 | int[] arr = new int[] { 3, 7, 5, 9, 1, 6, 19, 13 }; 50 | Sorts.mergeSort(arr); 51 | assertSorted(arr, "MERGE SORT"); 52 | } 53 | 54 | @Test 55 | @Tag("Example") 56 | public void longInsertionSort() { 57 | int LENGTH = 65536; 58 | int[] arr = new int[LENGTH]; 59 | for (int i=0; i JavaTasks.sortTimes(inputName, outputName) } 12 | } 13 | 14 | @Test 15 | @Tag("4") 16 | fun testSortAddressesJava() { 17 | sortAddresses { inputName, outputName -> JavaTasks.sortAddresses(inputName, outputName) } 18 | } 19 | 20 | @Test 21 | @Tag("4") 22 | fun testSortTemperaturesJava() { 23 | sortTemperatures { inputName, outputName -> JavaTasks.sortTemperatures(inputName, outputName) } 24 | } 25 | 26 | @Test 27 | @Tag("4") 28 | fun testSortSequenceJava() { 29 | sortSequence { inputName, outputName -> JavaTasks.sortSequence(inputName, outputName) } 30 | } 31 | 32 | @Test 33 | @Tag("2") 34 | fun testMergeArraysJava() { 35 | mergeArrays { first, second -> JavaTasks.mergeArrays(first, second) } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/lesson1/TaskTestsKotlin.kt: -------------------------------------------------------------------------------- 1 | package lesson1 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class TaskTestsKotlin : AbstractTaskTests() { 7 | 8 | @Test 9 | @Tag("3") 10 | fun testSortTimes() { 11 | sortTimes { inputName, outputName -> sortTimes(inputName, outputName) } 12 | } 13 | 14 | @Test 15 | @Tag("4") 16 | fun testSortAddresses() { 17 | sortAddresses { inputName, outputName -> sortAddresses(inputName, outputName) } 18 | } 19 | 20 | @Test 21 | @Tag("4") 22 | fun testSortTemperatures() { 23 | sortTemperatures { inputName, outputName -> sortTemperatures(inputName, outputName) } 24 | } 25 | 26 | @Test 27 | @Tag("4") 28 | fun testSortSequence() { 29 | sortSequence { inputName, outputName -> sortSequence(inputName, outputName) } 30 | } 31 | 32 | @Test 33 | @Tag("2") 34 | fun testMergeArrays() { 35 | mergeArrays { first, second -> mergeArrays(first, second) } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/lesson2/AbstractAlgorithmsTests.kt: -------------------------------------------------------------------------------- 1 | package lesson2 2 | 3 | import java.io.BufferedWriter 4 | import java.io.File 5 | import java.util.* 6 | import kotlin.test.assertEquals 7 | 8 | abstract class AbstractAlgorithmsTests { 9 | 10 | private val minPrice = 42 11 | 12 | private val maxPrice = 99999 13 | 14 | private fun generatePrices(size: Int): Pair { 15 | val random = Random() 16 | val prices = mutableListOf() 17 | for (index in 1..size) { 18 | val price = minPrice + 1 + random.nextInt(maxPrice - 1 - minPrice) 19 | prices += price 20 | } 21 | val firstIndex = random.nextInt(size) 22 | val secondIndex = random.nextInt(size).let { 23 | when (it) { 24 | firstIndex -> if (firstIndex == size - 1) firstIndex - 1 else firstIndex + 1 25 | else -> it 26 | } 27 | } 28 | val (minIndex, maxIndex) = 29 | if (firstIndex < secondIndex) firstIndex to secondIndex else secondIndex to firstIndex 30 | prices[minIndex] = minPrice 31 | prices[maxIndex] = maxPrice 32 | 33 | fun BufferedWriter.writePrices() { 34 | for (price in prices) { 35 | write(price.toString()) 36 | newLine() 37 | } 38 | close() 39 | } 40 | 41 | File("temp_prices.txt").bufferedWriter().writePrices() 42 | return minIndex + 1 to maxIndex + 1 43 | } 44 | 45 | fun optimizeBuyAndSell(optimizeBuyAndSell: (String) -> Pair) { 46 | assertEquals(3 to 4, optimizeBuyAndSell("input/buysell_in1.txt")) 47 | assertEquals(8 to 12, optimizeBuyAndSell("input/buysell_in2.txt")) 48 | assertEquals(3 to 4, optimizeBuyAndSell("input/buysell_in3.txt")) 49 | try { 50 | val expectedAnswer = generatePrices(1000) 51 | assertEquals(expectedAnswer, optimizeBuyAndSell("temp_prices.txt")) 52 | } finally { 53 | File("temp_prices.txt").delete() 54 | } 55 | try { 56 | val expectedAnswer = generatePrices(100000) 57 | assertEquals(expectedAnswer, optimizeBuyAndSell("temp_prices.txt")) 58 | } finally { 59 | File("temp_prices.txt").delete() 60 | } 61 | } 62 | 63 | fun josephTask(josephTask: (Int, Int) -> Int) { 64 | assertEquals(1, josephTask(1, 1)) 65 | assertEquals(2, josephTask(2, 1)) 66 | assertEquals(50000000, josephTask(50000000, 1)) 67 | assertEquals(3, josephTask(8, 5)) 68 | assertEquals(28, josephTask(40, 3)) 69 | var menNumber = 2 70 | for (i in 1..20) { 71 | assertEquals(1, josephTask(menNumber, 2)) 72 | menNumber *= 2 73 | } 74 | } 75 | 76 | fun longestCommonSubstring(longestCommonSubstring: (String, String) -> String) { 77 | assertEquals("", longestCommonSubstring("мой мир", "я")) 78 | assertEquals("зд", longestCommonSubstring("здравствуй мир", "мы здесь")) 79 | assertEquals("СЕРВАТОР", longestCommonSubstring("ОБСЕРВАТОРИЯ", "КОНСЕРВАТОРЫ")) 80 | assertEquals( 81 | "огда ", longestCommonSubstring( 82 | """ 83 | Мой дядя самых честных правил, 84 | Когда не в шутку занемог, 85 | Он уважать себя заставил 86 | И лучше выдумать не мог. 87 | Его пример другим наука; 88 | Но, боже мой, какая скука 89 | С больным сидеть и день и ночь, 90 | Не отходя ни шагу прочь! 91 | Какое низкое коварство 92 | Полуживого забавлять, 93 | Ему подушки поправлять, 94 | Печально подносить лекарство, 95 | Вздыхать и думать про себя: 96 | Когда же черт возьмет тебя! 97 | """.trimIndent(), 98 | """ 99 | Так думал молодой повеса, 100 | Летя в пыли на почтовых, 101 | Всевышней волею Зевеса 102 | Наследник всех своих родных. 103 | Друзья Людмилы и Руслана! 104 | С героем моего романа 105 | Без предисловий, сей же час 106 | Позвольте познакомить вас: 107 | Онегин, добрый мой приятель, 108 | Родился на брегах Невы, 109 | Где, может быть, родились вы 110 | Или блистали, мой читатель; 111 | Там некогда гулял и я: 112 | Но вреден север для меня 113 | """.trimIndent() 114 | ) 115 | ) 116 | assertEquals( 117 | "(с) Этот весь длинный-длинный текст является цитатой из Пушкина, поэма \"Руслан и Людмила\"", 118 | longestCommonSubstring( 119 | File("input/ruslan_ludmila_1.txt").readText(), 120 | File("input/ruslan_ludmila_2.txt").readText() 121 | ).trim() 122 | ) 123 | } 124 | 125 | fun calcPrimesNumber(calcPrimesNumber: (Int) -> Int) { 126 | assertEquals(0, calcPrimesNumber(-1)) 127 | assertEquals(0, calcPrimesNumber(1)) 128 | assertEquals(1, calcPrimesNumber(2)) 129 | assertEquals(2, calcPrimesNumber(4)) 130 | assertEquals(4, calcPrimesNumber(10)) 131 | assertEquals(8, calcPrimesNumber(20)) 132 | assertEquals(10, calcPrimesNumber(29)) 133 | assertEquals(20, calcPrimesNumber(71)) 134 | assertEquals(100, calcPrimesNumber(541)) 135 | assertEquals(500, calcPrimesNumber(3571)) 136 | assertEquals(1000, calcPrimesNumber(7920)) 137 | assertEquals(1229, calcPrimesNumber(10000)) 138 | assertEquals(2262, calcPrimesNumber(20000)) 139 | assertEquals(5133, calcPrimesNumber(50000)) 140 | assertEquals(9592, calcPrimesNumber(100000)) 141 | assertEquals(17984, calcPrimesNumber(200000)) 142 | assertEquals(33860, calcPrimesNumber(400000)) 143 | assertEquals(49098, calcPrimesNumber(600000)) 144 | assertEquals(56543, calcPrimesNumber(700000)) 145 | assertEquals(63951, calcPrimesNumber(800000)) 146 | assertEquals(71274, calcPrimesNumber(900000)) 147 | assertEquals(78498, calcPrimesNumber(1000000)) 148 | assertEquals(148933, calcPrimesNumber(2000000)) 149 | assertEquals(348513, calcPrimesNumber(5000000)) 150 | assertEquals(664579, calcPrimesNumber(10000000)) 151 | } 152 | } -------------------------------------------------------------------------------- /test/lesson2/AlgorithmsTestsJava.kt: -------------------------------------------------------------------------------- 1 | package lesson2 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class AlgorithmsTestsJava : AbstractAlgorithmsTests() { 7 | @Test 8 | @Tag("2") 9 | fun testOptimizeBuyAndSellJava() { 10 | optimizeBuyAndSell { JavaAlgorithms.optimizeBuyAndSell(it) } 11 | } 12 | 13 | @Test 14 | @Tag("2") 15 | fun testJosephTaskJava() { 16 | josephTask { menNumber, choiceInterval -> JavaAlgorithms.josephTask(menNumber, choiceInterval) } 17 | } 18 | 19 | @Test 20 | @Tag("4") 21 | fun testLongestCommonSubstringJava() { 22 | longestCommonSubstring { first, second -> JavaAlgorithms.longestCommonSubstring(first, second) } 23 | } 24 | 25 | @Test 26 | @Tag("3") 27 | fun testCalcPrimesNumberJava() { 28 | calcPrimesNumber { JavaAlgorithms.calcPrimesNumber(it) } 29 | } 30 | } -------------------------------------------------------------------------------- /test/lesson2/AlgorithmsTestsKotlin.kt: -------------------------------------------------------------------------------- 1 | package lesson2 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class AlgorithmsTestsKotlin : AbstractAlgorithmsTests() { 7 | @Test 8 | @Tag("2") 9 | fun testOptimizeBuyAndSell() { 10 | optimizeBuyAndSell { optimizeBuyAndSell(it) } 11 | } 12 | 13 | @Test 14 | @Tag("2") 15 | fun testJosephTask() { 16 | josephTask { menNumber, choiceInterval -> josephTask(menNumber, choiceInterval) } 17 | } 18 | 19 | @Test 20 | @Tag("4") 21 | fun testLongestCommonSubstring() { 22 | longestCommonSubstring { first, second -> longestCommonSubstring(first, second) } 23 | } 24 | 25 | @Test 26 | @Tag("3") 27 | fun testCalcPrimesNumber() { 28 | calcPrimesNumber { calcPrimesNumber(it) } 29 | } 30 | } -------------------------------------------------------------------------------- /test/lesson3/BinarySearchTreeTest.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class BinarySearchTreeTest : AbstractBinarySearchTreeTest() { 7 | 8 | override fun create(): CheckableSortedSet = 9 | BinarySearchTree() 10 | 11 | @Test 12 | @Tag("Example") 13 | fun initTestJava() { 14 | doInitTest() 15 | } 16 | 17 | @Test 18 | @Tag("Example") 19 | fun addTestJava() { 20 | doAddTest() 21 | } 22 | 23 | @Test 24 | @Tag("Example") 25 | fun firstAndLastTestJava() { 26 | doFirstAndLastTest() 27 | } 28 | 29 | @Test 30 | @Tag("5") 31 | fun removeTestJava() { 32 | doRemoveTest() 33 | } 34 | 35 | @Test 36 | @Tag("5") 37 | fun iteratorTestJava() { 38 | doIteratorTest() 39 | } 40 | 41 | @Test 42 | @Tag("8") 43 | fun iteratorRemoveTestJava() { 44 | doIteratorRemoveTest() 45 | } 46 | 47 | @Test 48 | @Tag("5") 49 | fun subSetTestJava() { 50 | doSubSetTest() 51 | } 52 | 53 | @Test 54 | @Tag("8") 55 | fun subSetRelationTestJava() { 56 | doSubSetRelationTest() 57 | } 58 | 59 | @Test 60 | @Tag("7") 61 | fun subSetFirstAndLastTestJava() { 62 | doSubSetFirstAndLastTest() 63 | } 64 | 65 | @Test 66 | @Tag("4") 67 | fun headSetTestJava() { 68 | doHeadSetTest() 69 | } 70 | 71 | @Test 72 | @Tag("7") 73 | fun headSetRelationTestJava() { 74 | doHeadSetRelationTest() 75 | } 76 | 77 | @Test 78 | @Tag("4") 79 | fun tailSetTestJava() { 80 | doTailSetTest() 81 | } 82 | 83 | @Test 84 | @Tag("7") 85 | fun tailSetRelationTestJava() { 86 | doTailSetRelationTest() 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /test/lesson3/KtBinarySearchTreeTest.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class KtBinarySearchTreeTest : AbstractBinarySearchTreeTest() { 7 | 8 | override fun create(): CheckableSortedSet = 9 | KtBinarySearchTree() 10 | 11 | @Test 12 | @Tag("Example") 13 | fun initTest() { 14 | doInitTest() 15 | } 16 | 17 | @Test 18 | @Tag("Example") 19 | fun addTest() { 20 | doAddTest() 21 | } 22 | 23 | @Test 24 | @Tag("Example") 25 | fun firstAndLastTest() { 26 | doFirstAndLastTest() 27 | } 28 | 29 | @Test 30 | @Tag("5") 31 | fun removeTest() { 32 | doRemoveTest() 33 | } 34 | 35 | @Test 36 | @Tag("5") 37 | fun iteratorTest() { 38 | doIteratorTest() 39 | } 40 | 41 | @Test 42 | @Tag("8") 43 | fun iteratorRemoveTest() { 44 | doIteratorRemoveTest() 45 | } 46 | 47 | @Test 48 | @Tag("5") 49 | fun subSetTest() { 50 | doSubSetTest() 51 | } 52 | 53 | @Test 54 | @Tag("8") 55 | fun subSetRelationTest() { 56 | doSubSetRelationTest() 57 | } 58 | 59 | @Test 60 | @Tag("7") 61 | fun subSetFirstAndLastTest() { 62 | doSubSetFirstAndLastTest() 63 | } 64 | 65 | @Test 66 | @Tag("4") 67 | fun headSetTest() { 68 | doHeadSetTest() 69 | } 70 | 71 | @Test 72 | @Tag("7") 73 | fun headSetRelationTest() { 74 | doHeadSetRelationTest() 75 | } 76 | 77 | @Test 78 | @Tag("4") 79 | fun tailSetTest() { 80 | doTailSetTest() 81 | } 82 | 83 | @Test 84 | @Tag("7") 85 | fun tailSetRelationTest() { 86 | doTailSetRelationTest() 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /test/lesson3/PositiveSortedSetTest.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import java.util.TreeSet 4 | import org.junit.jupiter.api.Tag 5 | import java.lang.IllegalArgumentException 6 | import kotlin.test.* 7 | 8 | class PositiveSortedSetTest { 9 | 10 | @Test 11 | @Tag("Example") 12 | fun basic() { 13 | val set = listOf(7, -4, 5, 9, -3, 4, 0, 99, -12).let { 14 | val tree = TreeSet() 15 | tree.addAll(it) 16 | tree 17 | } 18 | val subSet = set.positives() 19 | assertEquals(5, subSet.size) 20 | subSet.add(10) 21 | assertEquals(6, subSet.size) 22 | assertEquals(10, set.size) 23 | assertFailsWith { subSet.add(-10) } 24 | assertEquals(6, subSet.size) 25 | assertEquals(10, set.size) 26 | set.remove(5) 27 | assertEquals(5, subSet.size) 28 | assertEquals(9, set.size) 29 | set.remove(-4) 30 | assertEquals(5, subSet.size) 31 | assertEquals(8, set.size) 32 | subSet.remove(99) 33 | assertEquals(4, subSet.size) 34 | assertEquals(7, set.size) 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /test/lesson3/SampleIterableCollectionTest.kt: -------------------------------------------------------------------------------- 1 | package lesson3 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.* 5 | 6 | class SampleIterableCollectionTest { 7 | 8 | @Test 9 | @Tag("Example") 10 | fun testAdd() { 11 | val collection = SampleIterableCollection() 12 | collection.add("Omega") 13 | collection.add("Beta") 14 | collection.add("Alpha") 15 | assertEquals(3, collection.size) 16 | 17 | val checkList = listOf("Alpha", "Beta", "Omega") 18 | assertTrue(collection.containsAll(checkList)) 19 | 20 | var sizeByIterator = 0 21 | for (element in collection) { 22 | sizeByIterator++ 23 | } 24 | assertEquals(3, collection.size) 25 | assertEquals(3, sizeByIterator) 26 | } 27 | 28 | @Test 29 | @Tag("Example") 30 | fun testRemove() { 31 | val collection = SampleIterableCollection() 32 | collection.add("Omega") 33 | collection.add("Beta") 34 | collection.add("Alpha") 35 | 36 | val iterator = collection.iterator() 37 | iterator.next() 38 | iterator.next() 39 | iterator.remove() 40 | 41 | assertEquals(2, collection.size) 42 | assertFalse("Beta" in collection) 43 | assertTrue("Omega" in collection) 44 | assertTrue("Alpha" in collection) 45 | 46 | iterator.next() 47 | iterator.remove() 48 | assertEquals(1, collection.size) 49 | assertFalse("Omega" in collection) 50 | } 51 | 52 | @Test 53 | @Tag("Example") 54 | fun testRemoveFirst() { 55 | val collection = SampleIterableCollection() 56 | collection.add("Omega") 57 | collection.add("Beta") 58 | collection.add("Alpha") 59 | 60 | val iterator = collection.iterator() 61 | iterator.next() 62 | iterator.remove() 63 | 64 | assertEquals(2, collection.size) 65 | assertTrue("Beta" in collection) 66 | assertTrue("Omega" in collection) 67 | assertFalse("Alpha" in collection) 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /test/lesson4/AbstractTrieTest.kt: -------------------------------------------------------------------------------- 1 | package lesson4 2 | 3 | import java.util.* 4 | import kotlin.math.abs 5 | import ru.spbstu.kotlin.generate.util.nextString 6 | import kotlin.NoSuchElementException 7 | import kotlin.test.* 8 | 9 | abstract class AbstractTrieTest { 10 | 11 | abstract fun create(): MutableSet 12 | 13 | private fun implementationTest(function: () -> R) { 14 | try { 15 | function() 16 | } catch (e: Error) { 17 | if (e is NotImplementedError) { 18 | throw e 19 | } 20 | } catch (e: Exception) { 21 | // let it slide for now 22 | } 23 | } 24 | 25 | protected fun doGeneralTest() { 26 | val random = Random() 27 | for (iteration in 1..100) { 28 | val trie = create() 29 | assertEquals(0, trie.size) 30 | assertFalse("some" in trie) 31 | var wordCounter = 0 32 | val wordList = mutableSetOf() 33 | val removeIndex = random.nextInt(15) + 1 34 | var toRemove = "" 35 | for (i in 1..15) { 36 | val string = random.nextString("abcdefgh", 1, 15) 37 | wordList += string 38 | if (i == removeIndex) { 39 | toRemove = string 40 | } 41 | if (trie.add(string)) { 42 | wordCounter++ 43 | } 44 | assertTrue( 45 | string in trie, 46 | "An element wasn't added to trie when it should've been." 47 | ) 48 | if (string.length != 1) { 49 | val substring = string.substring(0, random.nextInt(string.length - 1)) 50 | if (substring !in wordList) { 51 | assertTrue( 52 | substring !in trie, 53 | "An element is considered to be in trie when it should not be there." 54 | ) 55 | } 56 | } 57 | } 58 | assertEquals(wordCounter, trie.size) 59 | trie.remove(toRemove) 60 | assertEquals(wordCounter - 1, trie.size) 61 | assertFalse( 62 | toRemove in trie, 63 | "A supposedly removed element is still considered to be in trie." 64 | ) 65 | trie.clear() 66 | assertEquals(0, trie.size) 67 | assertFalse("some" in trie) 68 | } 69 | } 70 | 71 | protected fun doIteratorTest() { 72 | implementationTest { create().iterator().hasNext() } 73 | implementationTest { create().iterator().next() } 74 | val random = Random() 75 | for (iteration in 1..100) { 76 | val controlSet = sortedSetOf() 77 | for (i in 1..15) { 78 | val string = random.nextString("abcdefgh", 1, 15) 79 | controlSet.add(string) 80 | } 81 | println("Control set: $controlSet") 82 | val trieSet = create() 83 | assertFalse( 84 | trieSet.iterator().hasNext(), 85 | "Iterator of an empty set should not have any next elements." 86 | ) 87 | for (element in controlSet) { 88 | trieSet += element 89 | } 90 | val iterator1 = trieSet.iterator() 91 | val iterator2 = trieSet.iterator() 92 | println("Checking if calling hasNext() changes the state of the iterator...") 93 | while (iterator1.hasNext()) { 94 | assertEquals( 95 | iterator2.next(), iterator1.next(), 96 | "Calling TrieIterator.hasNext() changes the state of the iterator." 97 | ) 98 | } 99 | val trieIter = trieSet.iterator() 100 | println("Checking if the iterator traverses the entire set...") 101 | while (trieIter.hasNext()) { 102 | controlSet.remove(trieIter.next()) 103 | } 104 | assertTrue( 105 | controlSet.isEmpty(), 106 | "TrieIterator doesn't traverse the entire set." 107 | ) 108 | assertFailsWith("Something was supposedly returned after the elements ended") { 109 | trieIter.next() 110 | } 111 | println("All clear!") 112 | } 113 | } 114 | 115 | protected fun doIteratorRemoveTest() { 116 | implementationTest { create().iterator().remove() } 117 | val random = Random() 118 | for (iteration in 1..100) { 119 | val controlSet = mutableSetOf() 120 | val removeIndex = random.nextInt(15) + 1 121 | var toRemove = "" 122 | for (i in 1..15) { 123 | val string = random.nextString("abcdefgh", 1, 15) 124 | controlSet.add(string) 125 | if (i == removeIndex) { 126 | toRemove = string 127 | } 128 | } 129 | println("Initial set: $controlSet") 130 | val trieSet = create() 131 | for (element in controlSet) { 132 | trieSet += element 133 | } 134 | controlSet.remove(toRemove) 135 | println("Control set: $controlSet") 136 | println("Removing element \"$toRemove\" from trie set through the iterator...") 137 | val iterator = trieSet.iterator() 138 | assertFailsWith("Something was supposedly deleted before the iteration started") { 139 | iterator.remove() 140 | } 141 | var counter = trieSet.size 142 | while (iterator.hasNext()) { 143 | val element = iterator.next() 144 | counter-- 145 | if (element == toRemove) { 146 | iterator.remove() 147 | assertFailsWith("Trie.remove() was successfully called twice in a row.") { 148 | iterator.remove() 149 | } 150 | } 151 | } 152 | assertEquals( 153 | 0, counter, 154 | "TrieIterator.remove() changed iterator position: ${abs(counter)} elements were ${if (counter > 0) "skipped" else "revisited"}." 155 | ) 156 | assertEquals( 157 | controlSet.size, trieSet.size, 158 | "The size of the set is incorrect: was ${trieSet.size}, should've been ${controlSet.size}." 159 | ) 160 | for (element in controlSet) { 161 | assertTrue( 162 | trieSet.contains(element), 163 | "Trie set doesn't have the element $element from the control set." 164 | ) 165 | } 166 | for (element in trieSet) { 167 | assertTrue( 168 | controlSet.contains(element), 169 | "Trie set has the element $element that is not in control set." 170 | ) 171 | } 172 | println("All clear!") 173 | } 174 | } 175 | 176 | } -------------------------------------------------------------------------------- /test/lesson4/KtTrieTest.kt: -------------------------------------------------------------------------------- 1 | package lesson4 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class KtTrieTest : AbstractTrieTest() { 7 | 8 | override fun create(): MutableSet = 9 | KtTrie() 10 | 11 | @Test 12 | @Tag("Example") 13 | fun generalTest() { 14 | doGeneralTest() 15 | } 16 | 17 | @Test 18 | @Tag("7") 19 | fun iteratorTest() { 20 | doIteratorTest() 21 | } 22 | 23 | @Test 24 | @Tag("8") 25 | fun iteratorRemoveTest() { 26 | doIteratorRemoveTest() 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /test/lesson4/TrieTest.kt: -------------------------------------------------------------------------------- 1 | package lesson4 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class TrieTest : AbstractTrieTest() { 7 | 8 | override fun create(): MutableSet = 9 | Trie() 10 | 11 | @Test 12 | @Tag("Example") 13 | fun generalTestJava() { 14 | doGeneralTest() 15 | } 16 | 17 | @Test 18 | @Tag("7") 19 | fun iteratorTestJava() { 20 | doIteratorTest() 21 | } 22 | 23 | @Test 24 | @Tag("8") 25 | fun iteratorRemoveTestJava() { 26 | doIteratorRemoveTest() 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /test/lesson5/AbstractOpenAddressingSetTest.kt: -------------------------------------------------------------------------------- 1 | package lesson5 2 | 3 | import ru.spbstu.kotlin.generate.util.nextString 4 | import java.util.* 5 | import kotlin.math.abs 6 | import kotlin.test.assertEquals 7 | import kotlin.test.assertFailsWith 8 | import kotlin.test.assertFalse 9 | import kotlin.test.assertTrue 10 | 11 | abstract class AbstractOpenAddressingSetTest { 12 | 13 | abstract fun create(bits: Int): MutableSet 14 | 15 | protected fun doAddTest() { 16 | val random = Random() 17 | for (iteration in 1..100) { 18 | val controlSet = mutableSetOf() 19 | val bitsNumber = random.nextInt(4) + 5 20 | val openAddressingSet = create(bitsNumber) 21 | assertTrue(openAddressingSet.size == 0, "Size of an empty set is not zero.") 22 | for (i in 1..50) { 23 | val nextInt = random.nextInt(32) 24 | val additionResult = openAddressingSet.add(nextInt) 25 | assertEquals( 26 | nextInt !in controlSet, additionResult, 27 | "An element was ${if (additionResult) "" else "not"} added when it ${if (additionResult) "was already in the set" else "should have been"}." 28 | ) 29 | controlSet += nextInt 30 | assertTrue(nextInt in openAddressingSet, "A supposedly added element is not in the set.") 31 | assertEquals(controlSet.size, openAddressingSet.size, "The size of the set is not as expected.") 32 | } 33 | val smallSet = create(bitsNumber) 34 | assertFailsWith("A table overflow is not being prevented.") { 35 | for (i in 1..4000) { 36 | smallSet.add(random.nextInt()) 37 | } 38 | } 39 | } 40 | } 41 | 42 | protected fun doRemoveTest() { 43 | val random = Random() 44 | for (iteration in 1..100) { 45 | val bitsNumber = random.nextInt(4) + 6 46 | val openAddressingSet = create(bitsNumber) 47 | for (i in 1..50) { 48 | val firstInt = random.nextInt(32) 49 | val secondInt = firstInt + (1 shl bitsNumber) 50 | openAddressingSet += secondInt 51 | openAddressingSet += firstInt 52 | val expectedSize = openAddressingSet.size - 1 53 | assertTrue( 54 | openAddressingSet.remove(secondInt), 55 | "An element wasn't removed contrary to expected." 56 | ) 57 | assertFalse( 58 | secondInt in openAddressingSet, 59 | "A supposedly removed element is still in the set." 60 | ) 61 | assertTrue( 62 | firstInt in openAddressingSet, 63 | "The removal of the element prevented access to the other elements." 64 | ) 65 | assertEquals( 66 | expectedSize, openAddressingSet.size, 67 | "The size of the set is not as expected." 68 | ) 69 | assertFalse( 70 | openAddressingSet.remove(secondInt), 71 | "A removed element was supposedly removed twice." 72 | ) 73 | assertEquals( 74 | expectedSize, openAddressingSet.size, 75 | "The size of the set is not as expected." 76 | ) 77 | } 78 | } 79 | } 80 | 81 | protected fun doIteratorTest() { 82 | val random = Random() 83 | for (iteration in 1..100) { 84 | val controlSet = mutableSetOf() 85 | for (i in 1..15) { 86 | val string = random.nextString("abcdefgh12345678", 1, 15) 87 | controlSet.add(string) 88 | } 89 | println("Control set: $controlSet") 90 | val openAddressingSet = create(random.nextInt(6) + 4) 91 | assertFalse( 92 | openAddressingSet.iterator().hasNext(), 93 | "Iterator of an empty set should not have any next elements." 94 | ) 95 | for (element in controlSet) { 96 | openAddressingSet += element 97 | } 98 | val iterator1 = openAddressingSet.iterator() 99 | val iterator2 = openAddressingSet.iterator() 100 | println("Checking if calling hasNext() changes the state of the iterator...") 101 | while (iterator1.hasNext()) { 102 | assertEquals( 103 | iterator2.next(), iterator1.next(), 104 | "Calling OpenAddressingSetIterator.hasNext() changes the state of the iterator." 105 | ) 106 | } 107 | val openAddressingSetIter = openAddressingSet.iterator() 108 | println("Checking if the iterator traverses the entire set...") 109 | while (openAddressingSetIter.hasNext()) { 110 | controlSet.remove(openAddressingSetIter.next()) 111 | } 112 | assertTrue( 113 | controlSet.isEmpty(), 114 | "OpenAddressingSetIterator doesn't traverse the entire set." 115 | ) 116 | assertFailsWith("Something was supposedly returned after the elements ended") { 117 | openAddressingSetIter.next() 118 | } 119 | println("All clear!") 120 | } 121 | } 122 | 123 | protected fun doIteratorRemoveTest() { 124 | val random = Random() 125 | for (iteration in 1..100) { 126 | val controlSet = mutableSetOf() 127 | val removeIndex = random.nextInt(15) + 1 128 | var toRemove = "" 129 | for (i in 1..15) { 130 | val string = random.nextString("abcdefgh12345678", 1, 15) 131 | controlSet.add(string) 132 | if (i == removeIndex) { 133 | toRemove = string 134 | } 135 | } 136 | println("Initial set: $controlSet") 137 | val openAddressingSet = create(random.nextInt(6) + 4) 138 | for (element in controlSet) { 139 | openAddressingSet += element 140 | } 141 | controlSet.remove(toRemove) 142 | println("Control set: $controlSet") 143 | println("Removing element \"$toRemove\" from open addressing set through the iterator...") 144 | val iterator = openAddressingSet.iterator() 145 | assertFailsWith("Something was supposedly deleted before the iteration started") { 146 | iterator.remove() 147 | } 148 | var counter = openAddressingSet.size 149 | while (iterator.hasNext()) { 150 | val element = iterator.next() 151 | counter-- 152 | if (element == toRemove) { 153 | iterator.remove() 154 | } 155 | } 156 | assertEquals( 157 | 0, counter, 158 | "OpenAddressingSetIterator.remove() changed iterator position: ${abs(counter)} elements were ${if (counter > 0) "skipped" else "revisited"}." 159 | ) 160 | assertEquals( 161 | controlSet.size, openAddressingSet.size, 162 | "The size of the set is incorrect: was ${openAddressingSet.size}, should've been ${controlSet.size}." 163 | ) 164 | for (element in controlSet) { 165 | assertTrue( 166 | openAddressingSet.contains(element), 167 | "Open addressing set doesn't have the element $element from the control set." 168 | ) 169 | } 170 | for (element in openAddressingSet) { 171 | assertTrue( 172 | controlSet.contains(element), 173 | "Open addressing set has the element $element that is not in control set." 174 | ) 175 | } 176 | println("All clear!") 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /test/lesson5/KtOpenAddressingSetTest.kt: -------------------------------------------------------------------------------- 1 | package lesson5 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class KtOpenAddressingSetTest : AbstractOpenAddressingSetTest() { 7 | 8 | override fun create(bits: Int): MutableSet { 9 | return KtOpenAddressingSet(bits) 10 | } 11 | 12 | @Test 13 | @Tag("Example") 14 | fun addTest() { 15 | doAddTest() 16 | } 17 | 18 | @Test 19 | @Tag("7") 20 | fun removeTest() { 21 | doRemoveTest() 22 | } 23 | 24 | @Test 25 | @Tag("5") 26 | fun iteratorTest() { 27 | doIteratorTest() 28 | } 29 | 30 | @Test 31 | @Tag("8") 32 | fun iteratorRemoveTest() { 33 | doIteratorRemoveTest() 34 | } 35 | } -------------------------------------------------------------------------------- /test/lesson5/OpenAddressingSetTest.kt: -------------------------------------------------------------------------------- 1 | package lesson5 2 | 3 | import org.junit.jupiter.api.Tag 4 | import org.junit.jupiter.api.Test 5 | 6 | class OpenAddressingSetTest : AbstractOpenAddressingSetTest() { 7 | 8 | override fun create(bits: Int): MutableSet { 9 | return OpenAddressingSet(bits) 10 | } 11 | 12 | @Test 13 | @Tag("Example") 14 | fun addTestJava() { 15 | doAddTest() 16 | } 17 | 18 | @Test 19 | @Tag("7") 20 | fun removeTestJava() { 21 | doRemoveTest() 22 | } 23 | 24 | @Test 25 | @Tag("5") 26 | fun iteratorTestJava() { 27 | doIteratorTest() 28 | } 29 | 30 | @Test 31 | @Tag("8") 32 | fun iteratorRemoveTestJava() { 33 | doIteratorRemoveTest() 34 | } 35 | } -------------------------------------------------------------------------------- /test/lesson6/BridgesTest.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.impl.GraphBuilder 4 | import org.junit.jupiter.api.Tag 5 | import kotlin.test.* 6 | 7 | class BridgesTest { 8 | @Test 9 | @Tag("Example") 10 | fun simple() { 11 | val graph = GraphBuilder().apply { 12 | val a = addVertex("A") 13 | val b = addVertex("B") 14 | val c = addVertex("C") 15 | addConnection(a, b) 16 | addConnection(b, c) 17 | addConnection(a, c) 18 | val d = addVertex("D") 19 | val e = addVertex("E") 20 | val f = addVertex("F") 21 | addConnection(d, e) 22 | addConnection(e, f) 23 | addConnection(d, f) 24 | addConnection(c, d) 25 | }.build() 26 | val bridges = graph.findBridges() 27 | assertEquals(1, bridges.size) 28 | val bridge = bridges.first() 29 | assertEquals(graph.getConnection(graph["C"]!!, graph["D"]!!), bridge) 30 | } 31 | 32 | @Test 33 | @Tag("Example") 34 | fun none() { 35 | val graph = GraphBuilder().apply { 36 | val a = addVertex("A") 37 | val b = addVertex("B") 38 | val c = addVertex("C") 39 | val d = addVertex("D") 40 | val e = addVertex("E") 41 | addConnection(a, b) 42 | addConnection(b, c) 43 | addConnection(a, c) 44 | addConnection(a, d) 45 | addConnection(b, d) 46 | addConnection(c, d) 47 | addConnection(a, e) 48 | addConnection(b, e) 49 | addConnection(c, e) 50 | addConnection(d, e) 51 | }.build() 52 | assertEquals(0, graph.findBridges().size) 53 | } 54 | } -------------------------------------------------------------------------------- /test/lesson6/DijkstraTest.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.impl.GraphBuilder 4 | import org.junit.jupiter.api.Tag 5 | import kotlin.test.* 6 | 7 | class DijkstraTest { 8 | 9 | @Test 10 | @Tag("Example") 11 | fun test1() { 12 | val graph = GraphBuilder().apply { 13 | val a = addVertex("A") 14 | val b = addVertex("B") 15 | val c = addVertex("C") 16 | addConnection(a, b, 10) 17 | addConnection(b, c, 5) 18 | }.build() 19 | val pathMap = graph.shortestPath(graph["A"]!!) 20 | assertEquals(10, pathMap[graph["B"]!!]?.distance) 21 | assertEquals(15, pathMap[graph["C"]!!]?.distance) 22 | assertEquals(listOf(graph["A"], graph["B"], graph["C"]), pathMap.unrollPath(graph["C"]!!)) 23 | } 24 | 25 | @Test 26 | @Tag("Example") 27 | fun test2() { 28 | val graph = GraphBuilder().apply { 29 | val a = addVertex("A") 30 | val b = addVertex("B") 31 | val c = addVertex("C") 32 | val d = addVertex("D") 33 | val e = addVertex("E") 34 | val f = addVertex("F") 35 | addConnection(a, b, 15) 36 | addConnection(b, c, 15) 37 | addConnection(b, d, 20) 38 | addConnection(a, c, 10) 39 | addConnection(c, e, 5) 40 | addConnection(d, e, 15) 41 | addConnection(d, f, 15) 42 | }.build() 43 | val pathMap = graph.shortestPath(graph["A"]!!) 44 | assertEquals(15, pathMap[graph["B"]!!]?.distance) 45 | assertEquals(10, pathMap[graph["C"]!!]?.distance) 46 | assertEquals(30, pathMap[graph["D"]!!]?.distance) 47 | assertEquals(15, pathMap[graph["E"]!!]?.distance) 48 | assertEquals( 49 | listOf(graph["A"], graph["C"], graph["E"], graph["D"], graph["F"]), 50 | pathMap.unrollPath(graph["F"]!!) 51 | ) 52 | } 53 | } -------------------------------------------------------------------------------- /test/lesson6/GraphBuilderTest.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.impl.GraphBuilder 4 | import org.junit.jupiter.api.Tag 5 | import kotlin.test.* 6 | 7 | class GraphBuilderTest { 8 | 9 | @Test 10 | @Tag("Example") 11 | fun generalTest() { 12 | val graph = GraphBuilder().apply { 13 | val a = addVertex("A") 14 | val b = addVertex("B") 15 | val c = addVertex("C") 16 | addConnection(a, b, 10) 17 | addConnection(b, c, 5) 18 | }.build() 19 | assertEquals(3, graph.vertices.size) 20 | val b = graph["B"]!! 21 | assertEquals(2, graph.getNeighbors(b).size) 22 | for ((vertex, edge) in graph.getConnections(b)) { 23 | when (vertex.name) { 24 | "A" -> assertEquals(10, edge.weight) 25 | "C" -> assertEquals(5, edge.weight) 26 | else -> throw AssertionError() 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /test/lesson6/GraphTestsJava.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class GraphTestsJava : AbstractGraphTests() { 7 | @Test 8 | @Tag("6") 9 | fun testFindEulerLoopJava() { 10 | findEulerLoop { let { JavaGraphTasks.findEulerLoop(it) } } 11 | } 12 | 13 | @Test 14 | @Tag("7") 15 | fun testMinimumSpanningTreeJava() { 16 | minimumSpanningTree { let { JavaGraphTasks.minimumSpanningTree(it) } } 17 | } 18 | 19 | @Test 20 | @Tag("10") 21 | fun testLargestIndependentVertexSetJava() { 22 | largestIndependentVertexSet { let { JavaGraphTasks.largestIndependentVertexSet(it) } } 23 | } 24 | 25 | @Test 26 | @Tag("8") 27 | fun testLongestSimplePathJava() { 28 | longestSimplePath { let { JavaGraphTasks.longestSimplePath(it) } } 29 | } 30 | 31 | @Test 32 | @Tag("6") 33 | fun testBaldaSearcherJava() { 34 | baldaSearcher { inputName, words -> JavaGraphTasks.baldaSearcher(inputName, words) } 35 | } 36 | } -------------------------------------------------------------------------------- /test/lesson6/GraphTestsKotlin.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class GraphTestsKotlin : AbstractGraphTests() { 7 | 8 | @Test 9 | @Tag("6") 10 | fun testFindEulerLoop() { 11 | findEulerLoop { findEulerLoop() } 12 | } 13 | 14 | @Test 15 | @Tag("7") 16 | fun testMinimumSpanningTree() { 17 | minimumSpanningTree { minimumSpanningTree() } 18 | } 19 | 20 | @Test 21 | @Tag("10") 22 | fun testLargestIndependentVertexSet() { 23 | largestIndependentVertexSet { largestIndependentVertexSet() } 24 | } 25 | 26 | @Test 27 | @Tag("8") 28 | fun testLongestSimplePath() { 29 | longestSimplePath { longestSimplePath() } 30 | } 31 | 32 | @Test 33 | @Tag("6") 34 | fun testBaldaSearcher() { 35 | baldaSearcher { inputName, words -> baldaSearcher(inputName, words) } 36 | } 37 | } -------------------------------------------------------------------------------- /test/lesson6/NoughtsAndCrossesTest.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | import kotlin.test.assertEquals 6 | 7 | class NoughtsAndCrossesTest { 8 | 9 | @Test 10 | @Tag("Example") 11 | fun gameOne() { 12 | val nc = NoughtsAndCrosses() 13 | nc.makeTurn(0, 0, true) 14 | nc.makeTurn(1, 0, false) 15 | nc.makeTurn(0, 1, true) 16 | assertEquals(NoughtsAndCrosses.Cell(0, 2), nc.findBestMoveAndEvaluation(false).first) 17 | nc.makeTurn(1, 1, false) 18 | assertEquals(NoughtsAndCrosses.Cell(0, 2), nc.findBestMoveAndEvaluation(true).first) 19 | nc.makeTurn(0, 2, true) 20 | assertEquals(true, nc.findWinnerIfAny()) 21 | } 22 | 23 | @Test 24 | @Tag("Example") 25 | fun gameTwo() { 26 | val nc = NoughtsAndCrosses() 27 | nc.makeTurn(1, 1, true) 28 | nc.makeTurn(0, 0, false) 29 | nc.makeTurn(2, 2, true) 30 | assertEquals(NoughtsAndCrosses.Cell(0, 2), nc.findBestMoveAndEvaluation(false).first) 31 | nc.makeTurn(0, 2, false) 32 | assertEquals(NoughtsAndCrosses.Cell(0, 1), nc.findBestMoveAndEvaluation(true).first) 33 | nc.makeTurn(2, 0, true) 34 | nc.makeTurn(0, 1, false) 35 | assertEquals(false, nc.findWinnerIfAny()) 36 | } 37 | 38 | @Test 39 | @Tag("Example") 40 | fun gameThree() { 41 | val nc = NoughtsAndCrosses() 42 | nc.makeTurn(1, 1, true) 43 | nc.makeTurn(0, 0, false) 44 | nc.makeTurn(2, 2, true) 45 | nc.makeTurn(1, 0, false) 46 | assertEquals(NoughtsAndCrosses.Cell(2, 0), nc.findBestMoveAndEvaluation(true).first) 47 | nc.makeTurn(2, 0, true) 48 | nc.makeTurn(0, 2, false) 49 | assertEquals(NoughtsAndCrosses.Cell(2, 1), nc.findBestMoveAndEvaluation(true).first) 50 | nc.makeTurn(2, 1, true) 51 | assertEquals(true, nc.findWinnerIfAny()) 52 | } 53 | 54 | @Test 55 | @Tag("Example") 56 | fun gameFour() { 57 | val nc = NoughtsAndCrosses() 58 | nc.makeTurn(1, 1, true) 59 | nc.makeTurn(0, 0, false) 60 | nc.makeTurn(2, 2, true) 61 | nc.makeTurn(1, 0, false) 62 | nc.makeTurn(0, 1, true) 63 | assertEquals(NoughtsAndCrosses.Cell(2, 0), nc.findBestMoveAndEvaluation(false).first) 64 | } 65 | 66 | @Test 67 | @Tag("Example") 68 | fun gameFive() { 69 | val nc = NoughtsAndCrosses() 70 | nc.makeTurn(1, 1, true) 71 | nc.makeTurn(0, 0, false) 72 | nc.makeTurn(2, 2, true) 73 | nc.makeTurn(0, 2, false) 74 | assertEquals(0, nc.findBestMoveAndEvaluation(true).second) 75 | nc.makeTurn(0, 1, true) 76 | assertEquals(0, nc.findBestMoveAndEvaluation(false).second) 77 | } 78 | } -------------------------------------------------------------------------------- /test/lesson6/VoyagerTest.kt: -------------------------------------------------------------------------------- 1 | package lesson6 2 | 3 | import lesson6.impl.GraphBuilder 4 | import org.junit.jupiter.api.Tag 5 | import kotlin.test.* 6 | 7 | class VoyagerTest { 8 | 9 | @Test 10 | @Tag("Example") 11 | fun test1() { 12 | val graph = GraphBuilder().apply { 13 | val a = addVertex("A") 14 | val b = addVertex("B") 15 | val c = addVertex("C") 16 | val d = addVertex("D") 17 | val e = addVertex("E") 18 | val f = addVertex("F") 19 | addConnection(a, b, 10) 20 | addConnection(b, c, 15) 21 | addConnection(c, f, 30) 22 | addConnection(a, d, 20) 23 | addConnection(d, e, 25) 24 | addConnection(e, f, 15) 25 | addConnection(a, f, 40) 26 | addConnection(b, d, 10) 27 | addConnection(c, e, 5) 28 | }.build() 29 | val path = findVoyagingPath(graph)!! 30 | assertEquals(105, path.length) 31 | assertEquals( 32 | listOf(graph["A"], graph["D"], graph["B"], graph["C"], graph["E"], graph["F"], graph["A"]), 33 | path.vertices 34 | ) 35 | } 36 | } -------------------------------------------------------------------------------- /test/lesson7/AbstractDynamicTests.kt: -------------------------------------------------------------------------------- 1 | package lesson7 2 | 3 | import kotlin.test.assertEquals 4 | 5 | abstract class AbstractDynamicTests { 6 | fun longestCommonSubSequence(longestCommonSubSequence: (String, String) -> String) { 7 | assertEquals("", longestCommonSubSequence("мой мир", "я")) 8 | assertEquals("1", longestCommonSubSequence("1", "1")) 9 | assertEquals("13", longestCommonSubSequence("123", "13")) 10 | assertEquals("здс", longestCommonSubSequence("здравствуй мир", "мы здесь")) 11 | assertEquals("emt ole", longestCommonSubSequence("nematode knowledge", "empty bottle")) 12 | val expectedLength = "e kerwelkkd r".length 13 | assertEquals( 14 | expectedLength, longestCommonSubSequence( 15 | "oiweijgw kejrhwejelkrw kjhdkfjs hrk", 16 | "perhkhk lerkerorwetp lkjklvvd durltr" 17 | ).length, "Answer must have length of $expectedLength, e.g. 'e kerwelkkd r' or 'erhlkrw kjk r'" 18 | ) 19 | val expectedLength2 = """ дд саы чтых, 20 | евшнео ваа се сви дн. 21 | """.trimIndent().length 22 | assertEquals( 23 | expectedLength2, longestCommonSubSequence( 24 | """ 25 | Мой дядя самых честных правил, 26 | Когда не в шутку занемог, 27 | Он уважать себя заставил 28 | И лучше выдумать не мог. 29 | """.trimIndent(), 30 | """ 31 | Так думал молодой повеса, 32 | Летя в пыли на почтовых, 33 | Всевышней волею Зевеса 34 | Наследник всех своих родных. 35 | """.trimIndent() 36 | ).length, "Answer must have length of $expectedLength2" 37 | ) 38 | } 39 | 40 | fun longestIncreasingSubSequence(longestIncreasingSubSequence: (List) -> List) { 41 | assertEquals(listOf(), longestIncreasingSubSequence(listOf())) 42 | assertEquals(listOf(1), longestIncreasingSubSequence(listOf(1))) 43 | assertEquals(listOf(1, 2), longestIncreasingSubSequence(listOf(1, 2))) 44 | assertEquals(listOf(2), longestIncreasingSubSequence(listOf(2, 1))) 45 | assertEquals( 46 | listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 47 | longestIncreasingSubSequence(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) 48 | ) 49 | assertEquals(listOf(2, 8, 9, 12), longestIncreasingSubSequence(listOf(2, 8, 5, 9, 12, 6))) 50 | assertEquals( 51 | listOf(23, 34, 56, 87, 91, 98, 140, 349), longestIncreasingSubSequence( 52 | listOf( 53 | 23, 76, 34, 93, 123, 21, 56, 87, 91, 12, 45, 98, 140, 12, 5, 38, 349, 65, 94, 54 | 45, 76, 15, 99, 100, 88, 84, 35, 88 55 | ) 56 | ) 57 | ) 58 | } 59 | 60 | fun shortestPathOnField(shortestPathOnField: (String) -> Int) { 61 | assertEquals(1, shortestPathOnField("input/field_in2.txt")) 62 | assertEquals(12, shortestPathOnField("input/field_in1.txt")) 63 | assertEquals(43, shortestPathOnField("input/field_in3.txt")) 64 | assertEquals(28, shortestPathOnField("input/field_in4.txt")) 65 | assertEquals(222, shortestPathOnField("input/field_in5.txt")) 66 | assertEquals(15, shortestPathOnField("input/field_in6.txt")) 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /test/lesson7/DynamicTestsJava.kt: -------------------------------------------------------------------------------- 1 | package lesson7 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class DynamicTestsJava : AbstractDynamicTests() { 7 | 8 | @Test 9 | @Tag("5") 10 | fun testLongestCommonSubSequenceJava() { 11 | longestCommonSubSequence { first, second -> JavaDynamicTasks.longestCommonSubSequence(first, second) } 12 | } 13 | 14 | @Test 15 | @Tag("7") 16 | fun testLongestIncreasingSubSequenceJava() { 17 | longestIncreasingSubSequence { JavaDynamicTasks.longestIncreasingSubSequence(it) } 18 | } 19 | 20 | @Test 21 | @Tag("4") 22 | fun testShortestPathOnFieldJava() { 23 | shortestPathOnField { JavaDynamicTasks.shortestPathOnField(it) } 24 | } 25 | } -------------------------------------------------------------------------------- /test/lesson7/DynamicTestsKotlin.kt: -------------------------------------------------------------------------------- 1 | package lesson7 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class DynamicTestsKotlin : AbstractDynamicTests() { 7 | 8 | @Test 9 | @Tag("5") 10 | fun testLongestCommonSubSequence() { 11 | longestCommonSubSequence { first, second -> longestCommonSubSequence(first, second) } 12 | } 13 | 14 | @Test 15 | @Tag("7") 16 | fun testLongestIncreasingSubSequence() { 17 | longestIncreasingSubSequence { longestIncreasingSubSequence(it) } 18 | } 19 | 20 | @Test 21 | @Tag("4") 22 | fun testShortestPathOnField() { 23 | shortestPathOnField { shortestPathOnField(it) } 24 | } 25 | } -------------------------------------------------------------------------------- /test/lesson7/fibonacci/FibTest.kt: -------------------------------------------------------------------------------- 1 | package lesson7.fibonacci 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.* 5 | 6 | class FibTest { 7 | @Test 8 | @Tag("Example") 9 | fun fib() { 10 | assertEquals(1L, fib(1)) 11 | assertEquals(1L, fib(2)) 12 | assertEquals(2L, fib(3)) 13 | assertEquals(3L, fib(4)) 14 | assertEquals(5L, fib(5)) 15 | assertEquals(13L, fib(7)) 16 | assertEquals(89L, fib(11)) 17 | assertEquals(610L, fib(15)) 18 | assertEquals(6765L, fib(20)) 19 | assertEquals(832040L, fib(30)) 20 | } 21 | } -------------------------------------------------------------------------------- /test/lesson7/knapsack/KnapsackTest.kt: -------------------------------------------------------------------------------- 1 | package lesson7.knapsack 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.* 5 | import java.util.* 6 | 7 | class KnapsackTest { 8 | private var items = listOf( 9 | Item(cost = 8, weight = 10), 10 | Item(cost = 5, weight = 12), 11 | Item(cost = 6, weight = 8), 12 | Item(cost = 10, weight = 15), 13 | Item(cost = 4, weight = 2) 14 | ) 15 | 16 | @Test 17 | @Tag("Example") 18 | fun fillKnapsackDynamic() { 19 | assertEquals( 20 | Fill( 21 | 22, 22 | Item(cost = 8, weight = 10), 23 | Item(cost = 10, weight = 15), 24 | Item(cost = 4, weight = 2) 25 | ), fillKnapsackDynamic(30, items) 26 | ) 27 | } 28 | 29 | @Test 30 | @Tag("Example") 31 | fun fillKnapsackGreedy() { 32 | assertEquals( 33 | Fill( 34 | 18, 35 | Item(cost = 6, weight = 8), 36 | Item(cost = 8, weight = 10), 37 | Item(cost = 4, weight = 2) 38 | ), fillKnapsackGreedy(30, items) 39 | ) 40 | } 41 | 42 | private val items2 = listOf( 43 | Item(cost = 1, weight = 3), 44 | Item(cost = 6, weight = 4), 45 | Item(cost = 4, weight = 5), 46 | Item(cost = 7, weight = 8), 47 | Item(cost = 6, weight = 9) 48 | ) 49 | 50 | @Test 51 | @Tag("Example") 52 | fun fillKnapsackDynamic2() { 53 | assertEquals( 54 | Fill( 55 | 13, 56 | Item(cost = 6, weight = 4), 57 | Item(cost = 7, weight = 8) 58 | ), fillKnapsackDynamic(13, items2) 59 | ) 60 | } 61 | 62 | @Test 63 | @Tag("Example") 64 | fun fillKnapsackGreedy2() { 65 | assertEquals( 66 | Fill( 67 | 13, 68 | Item(cost = 6, weight = 4), 69 | Item(cost = 7, weight = 8) 70 | ), fillKnapsackGreedy(13, items2) 71 | ) 72 | } 73 | 74 | private val items3 = listOf( 75 | Item(cost = 2, weight = 1), 76 | Item(cost = 5, weight = 3), 77 | Item(cost = 10, weight = 5), 78 | Item(cost = 15, weight = 7) 79 | ) 80 | 81 | @Test 82 | @Tag("Example") 83 | fun fillKnapsackDynamic3() { 84 | assertEquals( 85 | Fill( 86 | 20, 87 | Item(cost = 5, weight = 3), 88 | Item(cost = 15, weight = 7) 89 | ), fillKnapsackDynamic(10, items3) 90 | ) 91 | } 92 | 93 | @Test 94 | @Tag("Example") 95 | fun fillKnapsackGreedy3() { 96 | assertEquals( 97 | Fill( 98 | 17, 99 | Item(cost = 2, weight = 1), 100 | Item(cost = 15, weight = 7) 101 | ), fillKnapsackGreedy(10, items3) 102 | ) 103 | } 104 | 105 | @Test 106 | @Tag("Example") 107 | fun fillKnapsackGreedyBigTest() { 108 | for (i in 0..9) { 109 | val items = mutableListOf() 110 | val random = Random() 111 | for (j in 0 until 10000) { 112 | items += Item(1 + random.nextInt(10000), 300 + random.nextInt(600)) 113 | } 114 | try { 115 | val fillGreedy = fillKnapsackGreedy(1000, items) 116 | println("Жадный набрал = " + fillGreedy.cost) 117 | val weight = fillGreedy.items.sumOf { it.weight } 118 | println("Вес: $weight") 119 | } catch (e: StackOverflowError) { 120 | println("Жадный выбыл") 121 | throw AssertionError(e) 122 | } 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /test/lesson7/rod/CutTest.kt: -------------------------------------------------------------------------------- 1 | package lesson7.rod 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.* 5 | 6 | class CutTest { 7 | private val cost = mapOf(1 to 1, 2 to 5, 3 to 9, 4 to 9, 5 to 10, 6 to 17, 7 to 17, 8 to 20, 9 to 24) 8 | 9 | @Test 10 | @Tag("Example") 11 | fun cutRod() { 12 | assertEquals(Cut(cost = 59, length = listOf(2, 3, 3, 3, 3, 3, 3)), cutRod(20) { cost[it] ?: 0 }) 13 | assertEquals(Cut(cost = 28, length = listOf(1, 3, 3, 3)), cutRod(10) { cost[it] ?: 0 }) 14 | assertEquals(Cut(cost = 23, length = listOf(2, 3, 3)), cutRod(8) { cost[it] ?: 0 }) 15 | } 16 | 17 | private val cost2 = mapOf(1 to 1, 2 to 2, 3 to 4, 4 to 7) 18 | 19 | @Test 20 | @Tag("Example") 21 | fun cutRod2() { 22 | assertEquals(Cut(cost = 15, length = listOf(1, 4, 4)), cutRod(9) { cost2[it] ?: 0 }) 23 | assertEquals(Cut(cost = 4, length = listOf(3)), cutRod(3) { cost2[it] ?: 0 }) 24 | } 25 | 26 | @Test 27 | @Tag("Example") 28 | fun cutRod3() { 29 | assertEquals(Cut(cost = 17, length = listOf(1, 4)), cutRod(5) { listOf(0, 3, 5, 10, 14, 16)[it] }) 30 | } 31 | } -------------------------------------------------------------------------------- /test/lesson8/AbstractHeuristicsTests.kt: -------------------------------------------------------------------------------- 1 | package lesson8 2 | 3 | import lesson6.Graph 4 | import lesson6.Path 5 | import lesson6.impl.GraphBuilder 6 | import lesson7.knapsack.Fill 7 | import lesson7.knapsack.Item 8 | import lesson7.knapsack.fillKnapsackGreedy 9 | import java.util.* 10 | import kotlin.test.assertEquals 11 | import kotlin.test.assertTrue 12 | 13 | abstract class AbstractHeuristicsTests { 14 | 15 | fun fillKnapsackCompareWithGreedyTest(fillKnapsackHeuristics: (Int, List) -> Fill) { 16 | for (i in 0..9) { 17 | val items = mutableListOf() 18 | val random = Random() 19 | for (j in 0 until 10000) { 20 | items += Item(1 + random.nextInt(10000), 300 + random.nextInt(600)) 21 | } 22 | try { 23 | val fillHeuristics = fillKnapsackHeuristics(1000, items) 24 | println("Heuristics score = " + fillHeuristics.cost) 25 | val fillGreedy = fillKnapsackGreedy(1000, items) 26 | println("Greedy score = " + fillGreedy.cost) 27 | assertTrue(fillHeuristics.cost >= fillGreedy.cost) 28 | } catch (e: StackOverflowError) { 29 | println("Greedy failed with Stack Overflow") 30 | } 31 | } 32 | } 33 | 34 | fun findVoyagingPathHeuristics(findVoyagingPathHeuristics: Graph.() -> Path) { 35 | val graph = GraphBuilder().apply { 36 | val a = addVertex("A") 37 | val b = addVertex("B") 38 | val c = addVertex("C") 39 | val d = addVertex("D") 40 | val e = addVertex("E") 41 | val f = addVertex("F") 42 | addConnection(a, b, 10) 43 | addConnection(b, c, 15) 44 | addConnection(c, f, 30) 45 | addConnection(a, d, 20) 46 | addConnection(d, e, 25) 47 | addConnection(e, f, 15) 48 | addConnection(a, f, 40) 49 | addConnection(b, d, 10) 50 | addConnection(c, e, 5) 51 | }.build() 52 | val path = graph.findVoyagingPathHeuristics() 53 | assertEquals(105, path.length) 54 | val vertices = path.vertices 55 | assertEquals(vertices.first(), vertices.last(), "Voyaging path $vertices must be loop!") 56 | val withoutLast = vertices.dropLast(1) 57 | val expected = listOf(graph["A"], graph["D"], graph["B"], graph["C"], graph["E"], graph["F"]) 58 | assertEquals(expected.size, withoutLast.size, "Voyaging path $vertices must travel through all vertices!") 59 | expected.forEach { 60 | assertTrue(it in vertices, "Voyaging path $vertices must travel through all vertices!") 61 | } 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /test/lesson8/HeuristicsTestsJava.kt: -------------------------------------------------------------------------------- 1 | package lesson8 2 | 3 | import kotlin.test.Test 4 | import org.junit.jupiter.api.Tag 5 | 6 | class HeuristicsTestsJava : AbstractHeuristicsTests() { 7 | @Test 8 | @Tag("12") 9 | fun testFillKnapsackCompareWithGreedyTestJava() { 10 | fillKnapsackCompareWithGreedyTest { load, items -> JavaHeuristicsTasks.fillKnapsackHeuristics(load, items) } 11 | } 12 | 13 | @Test 14 | @Tag("12") 15 | fun testFindVoyagingPathHeuristicsJava() { 16 | findVoyagingPathHeuristics { let { JavaHeuristicsTasks.findVoyagingPathHeuristics(it) } } 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /test/lesson8/HeuristicsTestsKotlin.kt: -------------------------------------------------------------------------------- 1 | package lesson8 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.Test 5 | 6 | class HeuristicsTestsKotlin : AbstractHeuristicsTests() { 7 | 8 | @Test 9 | @Tag("12") 10 | fun testFillKnapsackCompareWithGreedyTest() { 11 | fillKnapsackCompareWithGreedyTest { load, items -> fillKnapsackHeuristics(load, items) } 12 | } 13 | 14 | @Test 15 | @Tag("12") 16 | fun testFindVoyagingPathHeuristics() { 17 | findVoyagingPathHeuristics { findVoyagingPathHeuristics() } 18 | } 19 | } -------------------------------------------------------------------------------- /test/lesson8/annealing/AnnealingVoyagingPathSearcherTest.kt: -------------------------------------------------------------------------------- 1 | package lesson8.annealing 2 | 3 | import lesson6.Graph 4 | import lesson6.impl.GraphBuilder 5 | import org.junit.jupiter.api.Tag 6 | import kotlin.test.* 7 | import java.util.* 8 | 9 | class AnnealingVoyagingPathSearcherTest { 10 | 11 | // TODO: this test is very unstable. Do something about it 12 | @Ignore 13 | @Test 14 | @Tag("Example") 15 | fun findVoyagingPath() { 16 | val graph = GraphBuilder().apply { 17 | val a = addVertex("A") 18 | val b = addVertex("B") 19 | val c = addVertex("C") 20 | val d = addVertex("D") 21 | val e = addVertex("E") 22 | val f = addVertex("F") 23 | addConnection(a, b, 10) 24 | addConnection(b, c, 15) 25 | addConnection(c, f, 30) 26 | addConnection(a, d, 20) 27 | addConnection(d, e, 25) 28 | addConnection(e, f, 15) 29 | addConnection(a, f, 40) 30 | addConnection(b, d, 10) 31 | addConnection(c, e, 5) 32 | }.build() 33 | val path = graph.findVoyagingPathAnnealing(startTemperature = 5000, iterationNumber = 2000) 34 | assertEquals(105, path.length) 35 | val vertices = path.vertices 36 | assertEquals(vertices.first(), vertices.last(), "Voyaging path $vertices must be loop!") 37 | val withoutLast = vertices.dropLast(1) 38 | val expected = listOf(graph["A"], graph["D"], graph["B"], graph["C"], graph["E"], graph["F"]) 39 | assertEquals(expected.size, withoutLast.size, "Voyaging path $vertices must travel through all vertices!") 40 | expected.forEach { 41 | assertTrue(it in vertices, "Voyaging path $vertices must travel through all vertices!") 42 | } 43 | } 44 | 45 | @Ignore 46 | @Test 47 | @Tag("Example") 48 | // This test is too long to run in continuous build 49 | fun findRandomVoyagingPath() { 50 | val random = Random() 51 | val graph = GraphBuilder().apply { 52 | val vertices = mutableListOf() 53 | for (i in 0..99) { 54 | vertices += addVertex(i.toString()) 55 | } 56 | for (i in 0..99) { 57 | for (j in i + 1..99) { 58 | addConnection(vertices[i], vertices[j], 1 + random.nextInt(100)) 59 | } 60 | } 61 | }.build() 62 | val path = graph.findVoyagingPathAnnealing(startTemperature = 3000, iterationNumber = 1000) 63 | println(path.length) 64 | println(path) 65 | } 66 | } -------------------------------------------------------------------------------- /test/lesson8/genetic/ChromosomeTest.kt: -------------------------------------------------------------------------------- 1 | package lesson8.genetic 2 | 3 | import org.junit.jupiter.api.Tag 4 | import kotlin.test.* 5 | import java.util.* 6 | 7 | class ChromosomeTest { 8 | private val random = Random() 9 | 10 | private val defaultSize = 1000 11 | 12 | @Test 13 | @Tag("Example") 14 | fun mutate() { 15 | for (i in 1..5000) { 16 | val chromosome = Chromosome(defaultSize, random) 17 | val other = chromosome.mutate(random) 18 | assertEquals(defaultSize, other.visitingOrder.size) 19 | assertEquals(defaultSize, other.visitingOrder.toSet().size) 20 | for (element in other.visitingOrder) { 21 | assertTrue(element in 0 until defaultSize) 22 | } 23 | } 24 | } 25 | 26 | @Test 27 | @Tag("Example") 28 | fun crossBreed() { 29 | for (i in 1..2000) { 30 | val first = Chromosome(defaultSize, random) 31 | val second = Chromosome(defaultSize, random) 32 | val third = first.crossBreed(second, random) 33 | assertEquals(defaultSize, third.visitingOrder.size) 34 | assertEquals(defaultSize, third.visitingOrder.toSet().size) 35 | for (element in third.visitingOrder) { 36 | assertTrue(element in 0 until defaultSize) 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /test/lesson8/genetic/GeneticVoyagingPathSearcherTest.kt: -------------------------------------------------------------------------------- 1 | package lesson8.genetic 2 | 3 | import lesson6.Graph 4 | import lesson6.impl.GraphBuilder 5 | import org.junit.jupiter.api.Tag 6 | import kotlin.test.* 7 | import java.util.* 8 | 9 | class GeneticVoyagingPathSearcherTest { 10 | @Test 11 | @Tag("Example") 12 | fun findVoyagingPath() { 13 | val graph = GraphBuilder().apply { 14 | val a = addVertex("A") 15 | val b = addVertex("B") 16 | val c = addVertex("C") 17 | val d = addVertex("D") 18 | val e = addVertex("E") 19 | val f = addVertex("F") 20 | addConnection(a, b, 10) 21 | addConnection(b, c, 15) 22 | addConnection(c, f, 30) 23 | addConnection(a, d, 20) 24 | addConnection(d, e, 25) 25 | addConnection(e, f, 15) 26 | addConnection(a, f, 40) 27 | addConnection(b, d, 10) 28 | addConnection(c, e, 5) 29 | }.build() 30 | val path = graph.findVoyagingPathGenetically(chromosomeNumber = 30, generationNumber = 50) 31 | assertTrue(path.length <= 115, "Voyaging path length: expected 115 but was ${path.length}") 32 | val vertices = path.vertices 33 | assertEquals(vertices.first(), vertices.last(), "Voyaging path $vertices must be loop!") 34 | val withoutLast = vertices.dropLast(1) 35 | val expected = listOf(graph["A"], graph["D"], graph["B"], graph["C"], graph["E"], graph["F"]) 36 | assertEquals(expected.size, withoutLast.size, "Voyaging path $vertices must travel through all vertices!") 37 | expected.forEach { 38 | assertTrue(it in vertices, "Voyaging path $vertices must travel through all vertices!") 39 | } 40 | } 41 | 42 | @Ignore 43 | @Test 44 | @Tag("Example") 45 | // This test is too long to run in continuous build 46 | fun findRandomVoyagingPath() { 47 | val random = Random() 48 | val graph = GraphBuilder().apply { 49 | val vertices = mutableListOf() 50 | for (i in 0..99) { 51 | vertices += addVertex(i.toString()) 52 | } 53 | for (i in 0..99) { 54 | for (j in i + 1..99) { 55 | addConnection(vertices[i], vertices[j], 1 + random.nextInt(100)) 56 | } 57 | } 58 | }.build() 59 | val path = graph.findVoyagingPathGenetically(chromosomeNumber = 100, generationNumber = 200) 60 | // We just check that some path is found 61 | println(path.length) 62 | println(path) 63 | } 64 | 65 | @Ignore 66 | @Test 67 | @Tag("Example") 68 | // This test is too long to run in continuous build 69 | fun findRandomVoyagingPathWithSmallChromosomeNumber() { 70 | val random = Random() 71 | val graph = GraphBuilder().apply { 72 | val vertices = mutableListOf() 73 | for (i in 0..99) { 74 | vertices += addVertex(i.toString()) 75 | } 76 | for (i in 0..99) { 77 | for (j in i + 1..99) { 78 | addConnection(vertices[i], vertices[j], 1 + random.nextInt(100)) 79 | } 80 | } 81 | }.build() 82 | val path = graph.findVoyagingPathGenetically(chromosomeNumber = 30, generationNumber = 200) 83 | // We just check that some path is found 84 | println(path.length) 85 | println(path) 86 | } 87 | } -------------------------------------------------------------------------------- /test/util/Util.kt: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import org.jetbrains.research.runner.perf.PerfEstimation 4 | import org.jetbrains.research.runner.perf.estimate 5 | 6 | data class PerfResult( 7 | val size: Int = 0, 8 | val time: Long = 0, 9 | val data: T 10 | ) 11 | 12 | fun estimate(data: List>) = estimate(data.map { it.size to it.time }) 13 | 14 | fun estimate(sizes: List, body: (Int) -> PerfResult): PerfEstimation { 15 | val data: MutableList> = mutableListOf() 16 | 17 | for (size in sizes) { 18 | data += body(size) 19 | } 20 | 21 | return estimate(data) 22 | } 23 | --------------------------------------------------------------------------------