├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
4 |
5 |
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 super T> 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> assertSorted(arr: List, prefix: String) {
22 | for (i in 0 until arr.size - 1) {
23 | assertTrue(
24 | arr[i] <= arr[i + 1],
25 | prefix + " ERROR: i = " + i + " a[i] = " + arr[i] + " a[i+1] = " + arr[i + 1]
26 | )
27 | }
28 | }
29 |
30 | @Test
31 | @Tag("Example")
32 | fun insertionSort() {
33 | val arr = mutableListOf(3, 7, 5, 9, 1, 6, 19, 13)
34 | insertionSort(arr)
35 | assertSorted(arr, "INSERTION SORT")
36 | }
37 |
38 | @Test
39 | @Tag("Example")
40 | fun insertionSortStrings() {
41 | val arr = mutableListOf("beta", "omega", "alpha", "", "!!!", "teta", "O")
42 | insertionSort(arr)
43 | assertSorted(arr, "INSERTION SORT")
44 | }
45 |
46 | @Test
47 | @Tag("Example")
48 | fun mergeSort() {
49 | val arr = intArrayOf(3, 7, 5, 9, 1, 6, 19, 13)
50 | mergeSort(arr)
51 | assertSorted(arr, "MERGE SORT")
52 | }
53 |
54 | @Test
55 | @Tag("Example")
56 | fun longInsertionSort() {
57 | val length = 65536
58 | val arr = MutableList(length) { r.nextInt() }
59 | insertionSort(arr)
60 | assertSorted(arr, "INSERTION SORT LONG")
61 | }
62 |
63 | @Test
64 | @Tag("Example")
65 | fun longMergeSort() {
66 | val length = 65536
67 | val arr = IntArray(length)
68 | for (i in 0 until length) {
69 | arr[i] = r.nextInt()
70 | }
71 | mergeSort(arr)
72 | assertSorted(arr, "MERGE SORT LONG")
73 | }
74 |
75 | @Test
76 | @Tag("Example")
77 | fun longHeapSort() {
78 | val length = 65536
79 | val arr = IntArray(length)
80 | for (i in 0 until length) {
81 | arr[i] = r.nextInt()
82 | }
83 | heapSort(arr)
84 | assertSorted(arr, "HEAP SORT LONG")
85 | }
86 |
87 | @Test
88 | @Tag("Example")
89 | fun quickSort() {
90 | val arr = intArrayOf(3, 7, 5, 9, 1, 6, 19, 13)
91 | quickSort(arr)
92 | assertSorted(arr, "QUICK SORT")
93 | }
94 |
95 | @Test
96 | @Tag("Example")
97 | fun longQuickSort() {
98 | val length = 65536
99 | val arr = IntArray(length)
100 | for (i in 0 until length) {
101 | arr[i] = r.nextInt()
102 | }
103 | quickSort(arr)
104 | assertSorted(arr, "QUICK SORT LONG")
105 | }
106 |
107 | @Test
108 | @Tag("Example")
109 | fun longCountingSort() {
110 | val length = 65536
111 | val limit = 262144
112 | val arr = IntArray(length)
113 | for (i in 0 until length) {
114 | arr[i] = r.nextInt(limit)
115 | }
116 | val result = countingSort(arr, limit - 1)
117 | assertSorted(result, "COUNTING SORT LONG")
118 | quickSort(arr)
119 | assertArrayEquals(arr, result)
120 | }
121 |
122 | @Test
123 | @Tag("Example")
124 | fun longLibrarySortForImmutable() {
125 | val length = 65536
126 | val arr = IntArray(length)
127 | for (i in 0 until length) {
128 | arr[i] = r.nextInt()
129 | }
130 | val list = arr.toList()
131 | val sortedList = librarySortForImmutable(list)
132 | assertSorted(sortedList, "LIBRARY SORT FOR IMMUTABLE")
133 | }
134 |
135 | @Test
136 | @Tag("Example")
137 | fun longLibrarySortForMutable() {
138 | val length = 65536
139 | val arr = IntArray(length)
140 | for (i in 0 until length) {
141 | arr[i] = r.nextInt()
142 | }
143 | val list = arr.toMutableList()
144 | librarySortForMutable(list)
145 | assertSorted(list, "LIBRARY SORT FOR MUTABLE")
146 | }
147 | }
--------------------------------------------------------------------------------
/test/lesson1/TaskTestsJava.kt:
--------------------------------------------------------------------------------
1 | package lesson1
2 |
3 | import org.junit.jupiter.api.Tag
4 | import kotlin.test.Test
5 |
6 | class TaskTestsJava : AbstractTaskTests() {
7 |
8 | @Test
9 | @Tag("3")
10 | fun testSortTimesJava() {
11 | sortTimes { inputName, outputName -> 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 |
--------------------------------------------------------------------------------
| | |