├── .gitignore
├── .idea
└── inspectionProfiles
│ └── Project_Default.xml
├── License.md
├── README.md
├── input
├── align_in1.txt
├── center_in1.txt
├── chaotic_in1.txt
├── empty.txt
├── expr_in1.txt
├── expr_in2.txt
├── expr_in3.txt
├── expr_in4.txt
├── expr_in5.txt
├── expr_in6.txt
├── markdown_lists.md
├── markdown_simple.md
├── onegin.txt
├── sibilants_in1.txt
├── substrings_in1.txt
├── top20.txt
├── trans_in1.txt
└── width_in1.txt
├── pom.xml
├── src
├── lesson1
│ └── task1
│ │ └── Simple.kt
├── lesson10
│ ├── task1
│ │ └── Regex.kt
│ └── task2
│ │ └── Html.kt
├── lesson2
│ ├── task1
│ │ └── IfElse.kt
│ └── task2
│ │ └── Logical.kt
├── lesson3
│ └── task1
│ │ └── Loop.kt
├── lesson4
│ └── task1
│ │ └── List.kt
├── lesson5
│ └── task1
│ │ └── Map.kt
├── lesson6
│ └── task1
│ │ └── Parse.kt
├── lesson7
│ └── task1
│ │ └── Files.kt
├── lesson8
│ ├── task1
│ │ └── Geometry.kt
│ ├── task2
│ │ └── Chess.kt
│ └── task3
│ │ └── Graph.kt
└── lesson9
│ ├── task1
│ └── Matrix.kt
│ └── task2
│ └── Matrices.kt
├── test
├── lesson1
│ └── task1
│ │ └── Tests.kt
├── lesson10
│ ├── task1
│ │ └── Tests.kt
│ └── task2
│ │ └── Tests.kt
├── lesson2
│ ├── task1
│ │ └── Tests.kt
│ └── task2
│ │ └── Tests.kt
├── lesson3
│ └── task1
│ │ └── Tests.kt
├── lesson4
│ └── task1
│ │ └── Tests.kt
├── lesson5
│ └── task1
│ │ └── Tests.kt
├── lesson6
│ └── task1
│ │ └── Tests.kt
├── lesson7
│ └── task1
│ │ └── Tests.kt
├── lesson8
│ ├── task1
│ │ └── Tests.kt
│ ├── task2
│ │ └── Tests.kt
│ └── task3
│ │ └── Tests.kt
└── lesson9
│ ├── task1
│ └── Tests.kt
│ └── task2
│ └── Tests.kt
└── tutorial
├── chapter00.adoc
├── chapter01.adoc
├── chapter02.adoc
├── chapter03.adoc
├── chapter04.adoc
├── chapter04_5.adoc
├── chapter05.adoc
├── chapter06.adoc
├── chapter06_5.adoc
├── chapter07.adoc
├── chapter08.adoc
├── chapter08_5.adoc
├── chapter09.adoc
└── chapter10.adoc
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 |
3 |
4 | .idea/*.xml
5 | .idea/copyright
6 | .idea/libraries
7 | .idea/shelf
8 | target
9 | out
10 |
11 | *.iml
12 | *.ipr
13 | *.iws
14 | *.zip
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Котлин как первый язык программирования
2 |
3 | Решите приведённые в проекте задачи, чтобы научиться программировать на Котлине. Сейчас доступны девять групп задач (уроков).
4 |
5 | 1. Простые функции.
6 | 2. Ветвления.
7 | 3. Циклы.
8 | 4. Работа со списками.
9 | 5. Работа с ассоциативными массивами (Maps).
10 | 6. Разбор строк.
11 | 7. Работа с файлами.
12 | 8. Простые классы.
13 | 9. Сложные классы на примере матриц.
14 |
15 | В директории tutorial имеется учебное пособие по Котлину на русском языке.
16 | Оно содержит введение и восемь разделов, каждый из которых относится к соотвествующему уроку в проекте.
17 | Также пособие включает дополнительные разделы, не включающие задач:
18 |
19 | * 4.5 (про организацию памяти)
20 | * 6.5 (про регулярные выражения)
21 | * 8.5 (про графы и графовые алгоритмы)
22 | * 10 (про синтаксический разбор и Kotlin DSL)
23 |
24 | ## Список использованных источников
25 |
26 | Формулировки многих задач взяты из следующей книги:
27 |
28 | * А. Юркин. Задачник по программированию. СПб.: Питер, 2002. - 192 с. ISBN 5-318-00399-0.
29 |
30 | Материалы по языку Kotlin:
31 |
32 | * http://kotlinlang.org/docs/reference
33 |
--------------------------------------------------------------------------------
/input/align_in1.txt:
--------------------------------------------------------------------------------
1 | Для написания разных видов программ сейчас применяются разные языки программирования.
2 | Например, в сфере мобильных программ сейчас правят бал языки Swift (мобильные устройства под управлением iOS)
3 | и Java (устройства под управлением Android).
4 | Системные программы, как правило, пишутся на языках C или {cpp}.
5 | Эти же языки долгое время использовались и для создания встраиваемых программ,
6 | но в последние годы в этой области набирает популярность язык Java.
7 | Для написания web-клиентов часто используется JavaScript, а в простых случаях -- язык разметки страниц HTML.
8 | Web-серверы используют опять-таки Java (в сложных случаях), а также Python и PHP (в более простых).
9 | Наконец, простые desktop-программы сейчас могут быть написаны на самых разных языках,
10 | и выбор во многом зависит от сложности программы, области её использования, предполагаемой операционной системы.
11 | В первую очередь следует назвать языки Java, {cpp}, C#, Python, Visual Basic, Ruby, Swift.
12 |
13 | Самым универсальным и одновременно самым распространённым языком программирования
14 | на данный момент следует считать язык Java.
15 | Java в широком смысле -- не только язык, но и платформа для выполнения программ
16 | под самыми разными операционными системами и на разной аппаратуре.
17 | Такая универсальность обеспечивается наличием виртуальной машины Java --
18 | системной программы, интерпретирующей Java байт-код в машинные коды конкретного компьютера или системы.
19 | Java также включает богатейший набор библиотек для разработки.
20 |
--------------------------------------------------------------------------------
/input/center_in1.txt:
--------------------------------------------------------------------------------
1 | Съешь же ещё этих мягких французских булок, да выпей чаю.
2 | Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства.
3 | Тест
4 |
5 | Hello World
6 | Во входном файле с именем inputName содержится некоторый текст.
7 | Вывести его в выходной файл с именем outputName, выровняв по центру.
--------------------------------------------------------------------------------
/input/chaotic_in1.txt:
--------------------------------------------------------------------------------
1 | Карминовый
2 | Боязливый
3 | Некрасивый
4 | Остроумный
5 | БелогЛазый
6 | ФиолетОвый
7 |
--------------------------------------------------------------------------------
/input/empty.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kotlin-Polytech/KotlinAsFirst2018/4a11d744e49f77c1e39d3dec5a74f334e08d5820/input/empty.txt
--------------------------------------------------------------------------------
/input/expr_in1.txt:
--------------------------------------------------------------------------------
1 | 3*x*x - 2 / x + 7 -x
--------------------------------------------------------------------------------
/input/expr_in2.txt:
--------------------------------------------------------------------------------
1 | (4 * x - 3) / (x - 2)
--------------------------------------------------------------------------------
/input/expr_in3.txt:
--------------------------------------------------------------------------------
1 | alpha
--------------------------------------------------------------------------------
/input/expr_in4.txt:
--------------------------------------------------------------------------------
1 | -x *(x *x -x)
--------------------------------------------------------------------------------
/input/expr_in5.txt:
--------------------------------------------------------------------------------
1 | (4845 * x - 388) / (x - 264)
--------------------------------------------------------------------------------
/input/expr_in6.txt:
--------------------------------------------------------------------------------
1 | 1 - x * x - x
--------------------------------------------------------------------------------
/input/markdown_lists.md:
--------------------------------------------------------------------------------
1 | * Утка по-пекински
2 | * Утка
3 | * Соус
4 | * Салат Оливье
5 | 1. Мясо
6 | * Или колбаса
7 | 2. Майонез
8 | 3. Картофель
9 | 4. Что-то там ещё
10 | * Помидоры
11 | * Фрукты
12 | 1. Бананы
13 | 23. Яблоки
14 | 1. Красные
15 | 2. Зелёные
16 |
--------------------------------------------------------------------------------
/input/markdown_simple.md:
--------------------------------------------------------------------------------
1 | Lorem ipsum *dolor sit amet*, consectetur **adipiscing** elit.
2 | Vestibulum lobortis. ~~Est vehicula rutrum *suscipit*~~, ipsum ~~lib~~ero *placerat **tortor***.
3 |
4 | Suspendisse ~~et elit in enim tempus iaculis~~.
5 |
--------------------------------------------------------------------------------
/input/sibilants_in1.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * Простая
3 | *
4 | * В русском языке, как правило, после букв Ж, Ч, Ш, Щ пишется И, А, У, а не Ы, Я, Ю.
5 | * Во входном файле с именем inputName содержытся некоторый текст.
6 | * Проверить текст во входном файле на соблюдение данного правила и вывести в выходной
7 | * файл outputName текст с исправленными ошыбками.
8 | *
9 | * Регистр заменённых букв следует сохранять.
10 | *
11 | * Исключения (жЮри, броШЮра, параШют) в рамках данного задания обрабатывать не нужно
12 | *
13 | * жЫ шЫ ЖИ Ши ЖЯ шЯ Жа ша жу шу жю щю чя шю щю щя жя жи жы жю чю чя
14 | */
--------------------------------------------------------------------------------
/input/substrings_in1.txt:
--------------------------------------------------------------------------------
1 | /**
2 | * Средняя
3 | *
4 | * Во входном файле с именем inputName имеется словарь с одним словом в каждой строчке.
5 | * Выбрать из данного словаря наиболее длинное слово,
6 | * в котором все буквы разные, например: Неряшливость, Четырёхдюймовка.
7 | * Вывести его в выходной файл с именем outputName.
8 | * Если во входном файле имеется несколько слов с одинаковой длиной, в которых все буквы разные,
9 | * в выходной файл следует вывести их все через запятую.
10 | * Регистр букв игнорировать, то есть буквы е и Е считать одинаковыми.
11 | *
12 | * Пример входного файла:
13 | * Карминовый
14 | * Боязливый
15 | * Некрасивый
16 | * Остроумный
17 | * БелогЛазый
18 | * ФиолетОвый
19 |
20 | * Соответствующий выходной файл:
21 | * Карминовый, Некрасивый
22 | *
23 | * Обратите внимание: данная функция не имеет возвращаемого значения
24 | */
--------------------------------------------------------------------------------
/input/top20.txt:
--------------------------------------------------------------------------------
1 | Привет, привет42, привет!!! -привет?!
2 |
3 | Всё!!! Ведь все русские буквы очень понятные, кроме одной - и это буква Ё вместо Е. Все остальные хорошие и красивые.
4 |
5 | Чёрные аисты летели по белому небу прямо, прямо, прямо, ...
6 |
7 | Let 4us4 write some english text with 1digits1 to test this side of a function. Let us write some more digits!!
8 |
9 | Ну и все всё наконец поняли?!
--------------------------------------------------------------------------------
/input/trans_in1.txt:
--------------------------------------------------------------------------------
1 | Здравствуй,
2 | мир!
--------------------------------------------------------------------------------
/input/width_in1.txt:
--------------------------------------------------------------------------------
1 | Простая
2 |
3 | Во входном файле с именем inputName содержится некоторый текст.
4 | Вывести его в выходной файл с именем outputName, выровняв по левому и правому краю относительно
5 | самой длинной строки.
6 | Выравнивание производить, вставляя дополнительные пробелы между словами: равномерно по всей строке
7 |
8 | Слова внутри строки отделяются друг от друга одним или более пробелом.
9 |
10 | Следующие правила должны быть выполнены:
11 | 1) Каждая строка входного и выходного файла не должна заканчиваться пробелом.
12 | 2) Пустые строки или строки из пробелов во входном файле должны превратиться в пустые строки в выходном файле.
13 | 3) Число строк в выходном файле должно быть равно числу строк во входном (в т. ч. пустых).
14 |
15 | Равномерность определяется следующими формальными правилами:
16 | 1) Число пробелов между каждыми двумя парами соседних слов не должно отличаться более, чем на 1.
17 | 2) Число пробелов между более левой парой соседних слов должно быть больше или равно числу пробелов
18 | между более правой парой соседних слов.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | ru.spbstu
8 | kfirst
9 | 0.1.14
10 |
11 |
12 |
13 | UTF-8
14 |
15 |
16 | UTF-8
17 |
18 |
19 | 1.2.51
20 | 0.6.11
21 | 5.0.0
22 | 4.12.0
23 | 1.0.0
24 |
25 |
26 |
27 |
28 | org.jetbrains.kotlin
29 | kotlin-stdlib
30 | ${kotlin.version}
31 |
32 |
33 | org.jetbrains.kotlin
34 | kotlin-reflect
35 | ${kotlin.version}
36 |
37 |
38 | org.jetbrains.kotlin
39 | kotlin-runtime
40 | ${kotlin.version}
41 |
42 |
43 |
44 | org.junit.jupiter
45 | junit-jupiter-api
46 | ${junit.jupiter.version}
47 | test
48 |
49 |
50 | org.junit.jupiter
51 | junit-jupiter-engine
52 | ${junit.jupiter.version}
53 | test
54 |
55 |
56 | org.junit.vintage
57 | junit-vintage-engine
58 | ${junit.vintage.version}
59 | test
60 |
61 |
62 | org.jetbrains.kotlinx
63 | kotlinx-html-jvm
64 | ${kotlinx.html.version}
65 |
66 |
67 |
68 | src
69 | test
70 |
71 |
72 | org.apache.maven.plugins
73 | maven-compiler-plugin
74 | 3.5.1
75 |
76 | 1.8
77 | 1.8
78 | 1.8
79 | 1.8
80 |
81 |
82 |
83 | maven-surefire-plugin
84 | 2.19.1
85 |
86 | true
87 |
88 |
89 |
90 | org.junit.platform
91 |
92 | junit-platform-surefire-provider
93 |
94 | ${junit.platform.version}
95 |
96 |
97 |
98 |
99 | kotlin-maven-plugin
100 | org.jetbrains.kotlin
101 | ${kotlin.version}
102 |
103 |
104 | compile
105 | process-sources
106 |
107 | compile
108 |
109 |
110 |
111 | test-compile
112 | process-test-sources
113 |
114 | test-compile
115 |
116 |
117 |
118 |
119 |
120 | kfirst-runner-plugin
121 | org.jetbrains.research
122 | 0.1.17
123 |
124 |
125 | lesson1.task1
126 |
127 | lesson2.task1
128 | lesson2.task2
129 |
130 | lesson3.task1
131 | lesson4.task1
132 | lesson5.task1
133 | lesson6.task1
134 | lesson7.task1
135 |
136 | lesson8.task1
137 | lesson8.task2
138 | lesson8.task3
139 |
140 | lesson9.task1
141 | lesson9.task2
142 |
143 | lesson10.task1
144 | lesson10.task2
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | jcenter
154 | jcenter
155 | https://jcenter.bintray.com
156 |
157 |
158 |
159 |
160 |
161 | bintray-vorpal-research-kotlin-maven
162 | vorpal-research-kotlin-maven
163 | http://dl.bintray.com/vorpal-research/kotlin-maven
164 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/src/lesson1/task1/Simple.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson1.task1
3 |
4 | import kotlin.math.*
5 |
6 | /**
7 | * Пример
8 | *
9 | * Вычисление квадрата целого числа
10 | */
11 | fun sqr(x: Int) = x * x
12 |
13 | /**
14 | * Пример
15 | *
16 | * Вычисление квадрата вещественного числа
17 | */
18 | fun sqr(x: Double) = x * x
19 |
20 | /**
21 | * Пример
22 | *
23 | * Вычисление дискриминанта квадратного уравнения
24 | */
25 | fun discriminant(a: Double, b: Double, c: Double) = sqr(b) - 4 * a * c
26 |
27 | /**
28 | * Пример
29 | *
30 | * Поиск одного из корней квадратного уравнения
31 | */
32 | fun quadraticEquationRoot(a: Double, b: Double, c: Double) =
33 | (-b + sqrt(discriminant(a, b, c))) / (2 * a)
34 |
35 | /**
36 | * Пример
37 | *
38 | * Поиск произведения корней квадратного уравнения
39 | */
40 | fun quadraticRootProduct(a: Double, b: Double, c: Double): Double {
41 | val sd = sqrt(discriminant(a, b, c))
42 | val x1 = (-b + sd) / (2 * a)
43 | val x2 = (-b - sd) / (2 * a)
44 | return x1 * x2 // Результат
45 | }
46 |
47 | /**
48 | * Пример главной функции
49 | */
50 | fun main(args: Array) {
51 | val x1x2 = quadraticRootProduct(1.0, 13.0, 42.0)
52 | println("Root product: $x1x2")
53 | }
54 |
55 | /**
56 | * Тривиальная
57 | *
58 | * Пользователь задает время в часах, минутах и секундах, например, 8:20:35.
59 | * Рассчитать время в секундах, прошедшее с начала суток (30035 в данном случае).
60 | */
61 | fun seconds(hours: Int, minutes: Int, seconds: Int): Int = TODO()
62 |
63 | /**
64 | * Тривиальная
65 | *
66 | * Пользователь задает длину отрезка в саженях, аршинах и вершках (например, 8 саженей 2 аршина 11 вершков).
67 | * Определить длину того же отрезка в метрах (в данном случае 18.98).
68 | * 1 сажень = 3 аршина = 48 вершков, 1 вершок = 4.445 см.
69 | */
70 | fun lengthInMeters(sagenes: Int, arshins: Int, vershoks: Int): Double = TODO()
71 |
72 | /**
73 | * Тривиальная
74 | *
75 | * Пользователь задает угол в градусах, минутах и секундах (например, 36 градусов 14 минут 35 секунд).
76 | * Вывести значение того же угла в радианах (например, 0.63256).
77 | */
78 | fun angleInRadian(grad: Int, min: Int, sec: Int): Double = TODO()
79 |
80 | /**
81 | * Тривиальная
82 | *
83 | * Найти длину отрезка, соединяющего точки на плоскости с координатами (x1, y1) и (x2, y2).
84 | * Например, расстояние между (3, 0) и (0, 4) равно 5
85 | */
86 | fun trackLength(x1: Double, y1: Double, x2: Double, y2: Double): Double = TODO()
87 |
88 | /**
89 | * Простая
90 | *
91 | * Пользователь задает целое число, большее 100 (например, 3801).
92 | * Определить третью цифру справа в этом числе (в данном случае 8).
93 | */
94 | fun thirdDigit(number: Int): Int = TODO()
95 |
96 | /**
97 | * Простая
98 | *
99 | * Поезд вышел со станции отправления в h1 часов m1 минут (например в 9:25) и
100 | * прибыл на станцию назначения в h2 часов m2 минут того же дня (например в 13:01).
101 | * Определите время поезда в пути в минутах (в данном случае 216).
102 | */
103 | fun travelMinutes(hoursDepart: Int, minutesDepart: Int, hoursArrive: Int, minutesArrive: Int): Int = TODO()
104 |
105 | /**
106 | * Простая
107 | *
108 | * Человек положил в банк сумму в s рублей под p% годовых (проценты начисляются в конце года).
109 | * Сколько денег будет на счету через 3 года (с учётом сложных процентов)?
110 | * Например, 100 рублей под 10% годовых превратятся в 133.1 рубля
111 | */
112 | fun accountInThreeYears(initial: Int, percent: Int): Double = TODO()
113 |
114 | /**
115 | * Простая
116 | *
117 | * Пользователь задает целое трехзначное число (например, 478).
118 | * Необходимо вывести число, полученное из заданного перестановкой цифр в обратном порядке (например, 874).
119 | */
120 | fun numberRevert(number: Int): Int = TODO()
121 |
--------------------------------------------------------------------------------
/src/lesson10/task1/Regex.kt:
--------------------------------------------------------------------------------
1 | package lesson10.task1
2 |
3 | import lesson10.task1.Expression.Operation.*
4 | import java.io.File
5 | import java.util.regex.Pattern
6 |
7 | /**
8 | * Пример
9 | *
10 | * Во входном файле с именем inputName
11 | * содержится строчка, содержащая описание функции от x, например:
12 | *
13 | * 3*x*x - 2 / x + 7 -x
14 | *
15 | * В списке values содержатся целочисленные значения аргумента x, например, (1, 2, -1)
16 | *
17 | * Вернуть ассоциативный массив (map), содержащий отображение заданных значений аргумента
18 | * в значение заданной в файле функции, в данном случае
19 | *
20 | * (1 to 7, 2 to 16, -1 to 13)
21 | *
22 | * В функции могут присутствовать четыре арифметических действия и круглые скобки.
23 | * Обратите внимание, что функция является целочисленной,
24 | * то есть деление также следует трактовать как целочисленное.
25 | */
26 | fun parseExpr(inputName: String, values: List): Map {
27 | val expr = File(inputName).readLines().firstOrNull()?.parseExpr() ?: throw IllegalArgumentException()
28 | val result = mutableMapOf()
29 | for (value in values) {
30 | result[value] = expr.calculate(value)
31 | }
32 | return result
33 | }
34 |
35 | fun String.parseExpr(): Expression {
36 | val pattern = Pattern.compile("""x|\+|-|\*|/|\(|\)|\d+| +?|.+?""")
37 | val matcher = pattern.matcher(this)
38 | val groups = mutableListOf()
39 | while (matcher.find()) {
40 | val group = matcher.group()
41 | if (group[0] != ' ') {
42 | groups.add(group)
43 | }
44 | }
45 | return Parser(groups).parse()
46 | }
47 |
48 | sealed class Expression {
49 | object Variable : Expression()
50 |
51 | class Constant(val value: Int) : Expression()
52 |
53 | enum class Operation {
54 | PLUS,
55 | MINUS,
56 | TIMES,
57 | DIV;
58 | }
59 |
60 | class Binary(val left: Expression, val op: Operation, val right: Expression) : Expression()
61 |
62 | class Negate(val arg: Expression) : Expression()
63 |
64 | fun calculate(x: Int): Int = when (this) {
65 | Variable -> x
66 | is Constant -> value
67 | is Binary -> when (op) {
68 | PLUS -> left.calculate(x) + right.calculate(x)
69 | MINUS -> left.calculate(x) - right.calculate(x)
70 | TIMES -> left.calculate(x) * right.calculate(x)
71 | DIV -> left.calculate(x) / right.calculate(x)
72 | }
73 | is Negate -> -arg.calculate(x)
74 | }
75 | }
76 |
77 | class Parser(private val groups: List) {
78 | private var pos = 0
79 |
80 | fun parse(): Expression {
81 | val result = parseExpression()
82 | if (pos < groups.size) {
83 | throw IllegalStateException("Unexpected expression remainder: ${groups.subList(pos, groups.size)}")
84 | }
85 | return result
86 | }
87 |
88 | private fun parseExpression(): Expression {
89 | var left = parseItem()
90 | while (pos < groups.size) {
91 | val op = operationMap[groups[pos]]
92 | when (op) {
93 | PLUS, MINUS -> {
94 | pos++
95 | val right = parseItem()
96 | left = Expression.Binary(left, op, right)
97 | }
98 | else -> return left
99 | }
100 | }
101 | return left
102 | }
103 |
104 | private fun parseItem(): Expression {
105 | var left = parseFactor()
106 | while (pos < groups.size) {
107 | val op = operationMap[groups[pos]]
108 | when (op) {
109 | TIMES, DIV -> {
110 | pos++
111 | val right = parseFactor()
112 | left = Expression.Binary(left, op, right)
113 | }
114 | else -> return left
115 | }
116 | }
117 | return left
118 | }
119 |
120 | private fun parseFactor(): Expression =
121 | if (pos >= groups.size) throw IllegalStateException("Unexpected expression end")
122 | else {
123 | val group = groups[pos++]
124 | when (group) {
125 | "x" -> Expression.Variable
126 | "-" -> Expression.Negate(parseFactor())
127 | "(" -> {
128 | val arg = parseExpression()
129 | val next = groups[pos++]
130 | if (next == ")") arg
131 | else throw IllegalStateException(") expected instead of $next")
132 | }
133 | else -> Expression.Constant(group.toInt())
134 | }
135 | }
136 |
137 | private val operationMap = mapOf("+" to PLUS, "-" to MINUS, "*" to TIMES, "/" to DIV)
138 | }
--------------------------------------------------------------------------------
/src/lesson10/task2/Html.kt:
--------------------------------------------------------------------------------
1 | package lesson10.task2
2 |
3 | import kotlinx.html.*
4 | import kotlinx.html.stream.appendHTML
5 |
6 | /**
7 | * Пример: преобразование списка списков в HTML таблицу
8 | */
9 | fun List>.convertToHtmlTable(): String {
10 | val sb = StringBuilder()
11 | sb.append("")
12 | sb.append("")
13 | sb.append("
")
14 | for (row in this) {
15 | sb.append("
")
16 | for (data in row) {
17 | sb.append("
")
18 | sb.append(data)
19 | sb.append("
")
20 | }
21 | sb.append("
")
22 | }
23 | sb.append("
")
24 | sb.append("")
25 | sb.append("")
26 | return sb.toString()
27 | }
28 |
29 | fun List>.convertToHtmlTableUsingKotlinxHtml(): String {
30 | val inputList = this
31 | val sb = StringBuilder()
32 | sb.appendHTML().html {
33 | body {
34 | table {
35 | for (row in inputList) {
36 | tr {
37 | for (data in row) {
38 | td { +data }
39 | }
40 | }
41 | }
42 | }
43 | }
44 | }
45 | return sb.toString()
46 | }
47 |
48 | fun generateSimpleHtml(s: String): String {
49 | val sb = StringBuilder()
50 | sb.myHtml {
51 | myBody {
52 | +s
53 | }
54 | }
55 | return sb.toString()
56 | }
57 |
58 | private class HTML(val sb: StringBuilder) {
59 | fun myBody(init: HTMLBody.() -> Unit): HTMLBody {
60 | val body = HTMLBody(sb)
61 | sb.append("")
62 | body.init()
63 | sb.append("")
64 | return body
65 | }
66 | }
67 |
68 | private class HTMLBody(val sb: StringBuilder) {
69 | operator fun String.unaryPlus() {
70 | sb.append(this)
71 | }
72 | }
73 |
74 | private fun StringBuilder.myHtml(init: HTML.() -> Unit): HTML {
75 | val html = HTML(this)
76 | append("")
77 | html.init()
78 | append("")
79 | return html
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/src/lesson2/task1/IfElse.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson2.task1
3 |
4 | import lesson1.task1.discriminant
5 | import kotlin.math.max
6 | import kotlin.math.sqrt
7 |
8 | /**
9 | * Пример
10 | *
11 | * Найти число корней квадратного уравнения ax^2 + bx + c = 0
12 | */
13 | fun quadraticRootNumber(a: Double, b: Double, c: Double): Int {
14 | val discriminant = discriminant(a, b, c)
15 | return when {
16 | discriminant > 0.0 -> 2
17 | discriminant == 0.0 -> 1
18 | else -> 0
19 | }
20 | }
21 |
22 | /**
23 | * Пример
24 | *
25 | * Получить строковую нотацию для оценки по пятибалльной системе
26 | */
27 | fun gradeNotation(grade: Int): String = when (grade) {
28 | 5 -> "отлично"
29 | 4 -> "хорошо"
30 | 3 -> "удовлетворительно"
31 | 2 -> "неудовлетворительно"
32 | else -> "несуществующая оценка $grade"
33 | }
34 |
35 | /**
36 | * Пример
37 | *
38 | * Найти наименьший корень биквадратного уравнения ax^4 + bx^2 + c = 0
39 | */
40 | fun minBiRoot(a: Double, b: Double, c: Double): Double {
41 | // 1: в главной ветке if выполняется НЕСКОЛЬКО операторов
42 | if (a == 0.0) {
43 | if (b == 0.0) return Double.NaN // ... и ничего больше не делать
44 | val bc = -c / b
45 | if (bc < 0.0) return Double.NaN // ... и ничего больше не делать
46 | return -sqrt(bc)
47 | // Дальше функция при a == 0.0 не идёт
48 | }
49 | val d = discriminant(a, b, c) // 2
50 | if (d < 0.0) return Double.NaN // 3
51 | // 4
52 | val y1 = (-b + sqrt(d)) / (2 * a)
53 | val y2 = (-b - sqrt(d)) / (2 * a)
54 | val y3 = max(y1, y2) // 5
55 | if (y3 < 0.0) return Double.NaN // 6
56 | return -sqrt(y3) // 7
57 | }
58 |
59 | /**
60 | * Простая
61 | *
62 | * Мой возраст. Для заданного 0 < n < 200, рассматриваемого как возраст человека,
63 | * вернуть строку вида: «21 год», «32 года», «12 лет».
64 | */
65 | fun ageDescription(age: Int): String = TODO()
66 |
67 | /**
68 | * Простая
69 | *
70 | * Путник двигался t1 часов со скоростью v1 км/час, затем t2 часов — со скоростью v2 км/час
71 | * и t3 часов — со скоростью v3 км/час.
72 | * Определить, за какое время он одолел первую половину пути?
73 | */
74 | fun timeForHalfWay(t1: Double, v1: Double,
75 | t2: Double, v2: Double,
76 | t3: Double, v3: Double): Double = TODO()
77 |
78 | /**
79 | * Простая
80 | *
81 | * Нa шахматной доске стоят черный король и две белые ладьи (ладья бьет по горизонтали и вертикали).
82 | * Определить, не находится ли король под боем, а если есть угроза, то от кого именно.
83 | * Вернуть 0, если угрозы нет, 1, если угроза только от первой ладьи, 2, если только от второй ладьи,
84 | * и 3, если угроза от обеих ладей.
85 | * Считать, что ладьи не могут загораживать друг друга
86 | */
87 | fun whichRookThreatens(kingX: Int, kingY: Int,
88 | rookX1: Int, rookY1: Int,
89 | rookX2: Int, rookY2: Int): Int = TODO()
90 |
91 | /**
92 | * Простая
93 | *
94 | * На шахматной доске стоят черный король и белые ладья и слон
95 | * (ладья бьет по горизонтали и вертикали, слон — по диагоналям).
96 | * Проверить, есть ли угроза королю и если есть, то от кого именно.
97 | * Вернуть 0, если угрозы нет, 1, если угроза только от ладьи, 2, если только от слона,
98 | * и 3, если угроза есть и от ладьи и от слона.
99 | * Считать, что ладья и слон не могут загораживать друг друга.
100 | */
101 | fun rookOrBishopThreatens(kingX: Int, kingY: Int,
102 | rookX: Int, rookY: Int,
103 | bishopX: Int, bishopY: Int): Int = TODO()
104 |
105 | /**
106 | * Простая
107 | *
108 | * Треугольник задан длинами своих сторон a, b, c.
109 | * Проверить, является ли данный треугольник остроугольным (вернуть 0),
110 | * прямоугольным (вернуть 1) или тупоугольным (вернуть 2).
111 | * Если такой треугольник не существует, вернуть -1.
112 | */
113 | fun triangleKind(a: Double, b: Double, c: Double): Int = TODO()
114 |
115 | /**
116 | * Средняя
117 | *
118 | * Даны четыре точки на одной прямой: A, B, C и D.
119 | * Координаты точек a, b, c, d соответственно, b >= a, d >= c.
120 | * Найти длину пересечения отрезков AB и CD.
121 | * Если пересечения нет, вернуть -1.
122 | */
123 | fun segmentLength(a: Int, b: Int, c: Int, d: Int): Int = TODO()
124 |
--------------------------------------------------------------------------------
/src/lesson2/task2/Logical.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson2.task2
3 |
4 | import lesson1.task1.sqr
5 |
6 | /**
7 | * Пример
8 | *
9 | * Лежит ли точка (x, y) внутри окружности с центром в (x0, y0) и радиусом r?
10 | */
11 | fun pointInsideCircle(x: Double, y: Double, x0: Double, y0: Double, r: Double) =
12 | sqr(x - x0) + sqr(y - y0) <= sqr(r)
13 |
14 | /**
15 | * Простая
16 | *
17 | * Четырехзначное число назовем счастливым, если сумма первых двух ее цифр равна сумме двух последних.
18 | * Определить, счастливое ли заданное число, вернуть true, если это так.
19 | */
20 | fun isNumberHappy(number: Int): Boolean = TODO()
21 |
22 | /**
23 | * Простая
24 | *
25 | * На шахматной доске стоят два ферзя (ферзь бьет по вертикали, горизонтали и диагоналям).
26 | * Определить, угрожают ли они друг другу. Вернуть true, если угрожают.
27 | * Считать, что ферзи не могут загораживать друг друга.
28 | */
29 | fun queenThreatens(x1: Int, y1: Int, x2: Int, y2: Int): Boolean = TODO()
30 |
31 |
32 | /**
33 | * Простая
34 | *
35 | * Дан номер месяца (от 1 до 12 включительно) и год (положительный).
36 | * Вернуть число дней в этом месяце этого года по григорианскому календарю.
37 | */
38 | fun daysInMonth(month: Int, year: Int): Int = TODO()
39 |
40 | /**
41 | * Средняя
42 | *
43 | * Проверить, лежит ли окружность с центром в (x1, y1) и радиусом r1 целиком внутри
44 | * окружности с центром в (x2, y2) и радиусом r2.
45 | * Вернуть true, если утверждение верно
46 | */
47 | fun circleInside(x1: Double, y1: Double, r1: Double,
48 | x2: Double, y2: Double, r2: Double): Boolean = TODO()
49 |
50 | /**
51 | * Средняя
52 | *
53 | * Определить, пройдет ли кирпич со сторонами а, b, c сквозь прямоугольное отверстие в стене со сторонами r и s.
54 | * Стороны отверстия должны быть параллельны граням кирпича.
55 | * Считать, что совпадения длин сторон достаточно для прохождения кирпича, т.е., например,
56 | * кирпич 4 х 4 х 4 пройдёт через отверстие 4 х 4.
57 | * Вернуть true, если кирпич пройдёт
58 | */
59 | fun brickPasses(a: Int, b: Int, c: Int, r: Int, s: Int): Boolean = TODO()
60 |
--------------------------------------------------------------------------------
/src/lesson3/task1/Loop.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson3.task1
3 |
4 | import kotlin.math.sqrt
5 |
6 | /**
7 | * Пример
8 | *
9 | * Вычисление факториала
10 | */
11 | fun factorial(n: Int): Double {
12 | var result = 1.0
13 | for (i in 1..n) {
14 | result = result * i // Please do not fix in master
15 | }
16 | return result
17 | }
18 |
19 | /**
20 | * Пример
21 | *
22 | * Проверка числа на простоту -- результат true, если число простое
23 | */
24 | fun isPrime(n: Int): Boolean {
25 | if (n < 2) return false
26 | if (n == 2) return true
27 | if (n % 2 == 0) return false
28 | for (m in 3..sqrt(n.toDouble()).toInt() step 2) {
29 | if (n % m == 0) return false
30 | }
31 | return true
32 | }
33 |
34 | /**
35 | * Пример
36 | *
37 | * Проверка числа на совершенность -- результат true, если число совершенное
38 | */
39 | fun isPerfect(n: Int): Boolean {
40 | var sum = 1
41 | for (m in 2..n/2) {
42 | if (n % m > 0) continue
43 | sum += m
44 | if (sum > n) break
45 | }
46 | return sum == n
47 | }
48 |
49 | /**
50 | * Пример
51 | *
52 | * Найти число вхождений цифры m в число n
53 | */
54 | fun digitCountInNumber(n: Int, m: Int): Int =
55 | when {
56 | n == m -> 1
57 | n < 10 -> 0
58 | else -> digitCountInNumber(n / 10, m) + digitCountInNumber(n % 10, m)
59 | }
60 |
61 | /**
62 | * Тривиальная
63 | *
64 | * Найти количество цифр в заданном числе n.
65 | * Например, число 1 содержит 1 цифру, 456 -- 3 цифры, 65536 -- 5 цифр.
66 | *
67 | * Использовать операции со строками в этой задаче запрещается.
68 | */
69 | fun digitNumber(n: Int): Int = TODO()
70 |
71 | /**
72 | * Простая
73 | *
74 | * Найти число Фибоначчи из ряда 1, 1, 2, 3, 5, 8, 13, 21, ... с номером n.
75 | * Ряд Фибоначчи определён следующим образом: fib(1) = 1, fib(2) = 1, fib(n+2) = fib(n) + fib(n+1)
76 | */
77 | fun fib(n: Int): Int = TODO()
78 |
79 | /**
80 | * Простая
81 | *
82 | * Для заданных чисел m и n найти наименьшее общее кратное, то есть,
83 | * минимальное число k, которое делится и на m и на n без остатка
84 | */
85 | fun lcm(m: Int, n: Int): Int = TODO()
86 |
87 | /**
88 | * Простая
89 | *
90 | * Для заданного числа n > 1 найти минимальный делитель, превышающий 1
91 | */
92 | fun minDivisor(n: Int): Int = TODO()
93 |
94 | /**
95 | * Простая
96 | *
97 | * Для заданного числа n > 1 найти максимальный делитель, меньший n
98 | */
99 | fun maxDivisor(n: Int): Int = TODO()
100 |
101 | /**
102 | * Простая
103 | *
104 | * Определить, являются ли два заданных числа m и n взаимно простыми.
105 | * Взаимно простые числа не имеют общих делителей, кроме 1.
106 | * Например, 25 и 49 взаимно простые, а 6 и 8 -- нет.
107 | */
108 | fun isCoPrime(m: Int, n: Int): Boolean = TODO()
109 |
110 | /**
111 | * Простая
112 | *
113 | * Для заданных чисел m и n, m <= n, определить, имеется ли хотя бы один точный квадрат между m и n,
114 | * то есть, существует ли такое целое k, что m <= k*k <= n.
115 | * Например, для интервала 21..28 21 <= 5*5 <= 28, а для интервала 51..61 квадрата не существует.
116 | */
117 | fun squareBetweenExists(m: Int, n: Int): Boolean = TODO()
118 |
119 | /**
120 | * Средняя
121 | *
122 | * Гипотеза Коллатца. Рекуррентная последовательность чисел задана следующим образом:
123 | *
124 | * ЕСЛИ (X четное)
125 | * Xслед = X /2
126 | * ИНАЧЕ
127 | * Xслед = 3 * X + 1
128 | *
129 | * например
130 | * 15 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1 4 2 1 4 2 1 ...
131 | * Данная последовательность рано или поздно встречает X == 1.
132 | * Написать функцию, которая находит, сколько шагов требуется для
133 | * этого для какого-либо начального X > 0.
134 | */
135 | fun collatzSteps(x: Int): Int = TODO()
136 |
137 | /**
138 | * Средняя
139 | *
140 | * Для заданного x рассчитать с заданной точностью eps
141 | * sin(x) = x - x^3 / 3! + x^5 / 5! - x^7 / 7! + ...
142 | * Нужную точность считать достигнутой, если очередной член ряда меньше eps по модулю
143 | */
144 | fun sin(x: Double, eps: Double): Double = TODO()
145 |
146 | /**
147 | * Средняя
148 | *
149 | * Для заданного x рассчитать с заданной точностью eps
150 | * cos(x) = 1 - x^2 / 2! + x^4 / 4! - x^6 / 6! + ...
151 | * Нужную точность считать достигнутой, если очередной член ряда меньше eps по модулю
152 | */
153 | fun cos(x: Double, eps: Double): Double = TODO()
154 |
155 | /**
156 | * Средняя
157 | *
158 | * Поменять порядок цифр заданного числа n на обратный: 13478 -> 87431.
159 | *
160 | * Использовать операции со строками в этой задаче запрещается.
161 | */
162 | fun revert(n: Int): Int = TODO()
163 |
164 | /**
165 | * Средняя
166 | *
167 | * Проверить, является ли заданное число n палиндромом:
168 | * первая цифра равна последней, вторая -- предпоследней и так далее.
169 | * 15751 -- палиндром, 3653 -- нет.
170 | *
171 | * Использовать операции со строками в этой задаче запрещается.
172 | */
173 | fun isPalindrome(n: Int): Boolean = TODO()
174 |
175 | /**
176 | * Средняя
177 | *
178 | * Для заданного числа n определить, содержит ли оно различающиеся цифры.
179 | * Например, 54 и 323 состоят из разных цифр, а 111 и 0 из одинаковых.
180 | *
181 | * Использовать операции со строками в этой задаче запрещается.
182 | */
183 | fun hasDifferentDigits(n: Int): Boolean = TODO()
184 |
185 | /**
186 | * Сложная
187 | *
188 | * Найти n-ю цифру последовательности из квадратов целых чисел:
189 | * 149162536496481100121144...
190 | * Например, 2-я цифра равна 4, 7-я 5, 12-я 6.
191 | *
192 | * Использовать операции со строками в этой задаче запрещается.
193 | */
194 | fun squareSequenceDigit(n: Int): Int = TODO()
195 |
196 | /**
197 | * Сложная
198 | *
199 | * Найти n-ю цифру последовательности из чисел Фибоначчи (см. функцию fib выше):
200 | * 1123581321345589144...
201 | * Например, 2-я цифра равна 1, 9-я 2, 14-я 5.
202 | *
203 | * Использовать операции со строками в этой задаче запрещается.
204 | */
205 | fun fibSequenceDigit(n: Int): Int = TODO()
206 |
--------------------------------------------------------------------------------
/src/lesson4/task1/List.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER", "ConvertCallChainIntoSequence")
2 |
3 | package lesson4.task1
4 |
5 | import lesson1.task1.discriminant
6 | import kotlin.math.sqrt
7 |
8 | /**
9 | * Пример
10 | *
11 | * Найти все корни уравнения x^2 = y
12 | */
13 | fun sqRoots(y: Double) =
14 | when {
15 | y < 0 -> listOf()
16 | y == 0.0 -> listOf(0.0)
17 | else -> {
18 | val root = sqrt(y)
19 | // Результат!
20 | listOf(-root, root)
21 | }
22 | }
23 |
24 | /**
25 | * Пример
26 | *
27 | * Найти все корни биквадратного уравнения ax^4 + bx^2 + c = 0.
28 | * Вернуть список корней (пустой, если корней нет)
29 | */
30 | fun biRoots(a: Double, b: Double, c: Double): List {
31 | if (a == 0.0) {
32 | return if (b == 0.0) listOf()
33 | else sqRoots(-c / b)
34 | }
35 | val d = discriminant(a, b, c)
36 | if (d < 0.0) return listOf()
37 | if (d == 0.0) return sqRoots(-b / (2 * a))
38 | val y1 = (-b + sqrt(d)) / (2 * a)
39 | val y2 = (-b - sqrt(d)) / (2 * a)
40 | return sqRoots(y1) + sqRoots(y2)
41 | }
42 |
43 | /**
44 | * Пример
45 | *
46 | * Выделить в список отрицательные элементы из заданного списка
47 | */
48 | fun negativeList(list: List): List {
49 | val result = mutableListOf()
50 | for (element in list) {
51 | if (element < 0) {
52 | result.add(element)
53 | }
54 | }
55 | return result
56 | }
57 |
58 | /**
59 | * Пример
60 | *
61 | * Изменить знак для всех положительных элементов списка
62 | */
63 | fun invertPositives(list: MutableList) {
64 | for (i in 0 until list.size) {
65 | val element = list[i]
66 | if (element > 0) {
67 | list[i] = -element
68 | }
69 | }
70 | }
71 |
72 | /**
73 | * Пример
74 | *
75 | * Из имеющегося списка целых чисел, сформировать список их квадратов
76 | */
77 | fun squares(list: List) = list.map { it * it }
78 |
79 | /**
80 | * Пример
81 | *
82 | * Из имеющихся целых чисел, заданного через vararg-параметр, сформировать массив их квадратов
83 | */
84 | fun squares(vararg array: Int) = squares(array.toList()).toTypedArray()
85 |
86 | /**
87 | * Пример
88 | *
89 | * По заданной строке str определить, является ли она палиндромом.
90 | * В палиндроме первый символ должен быть равен последнему, второй предпоследнему и т.д.
91 | * Одни и те же буквы в разном регистре следует считать равными с точки зрения данной задачи.
92 | * Пробелы не следует принимать во внимание при сравнении символов, например, строка
93 | * "А роза упала на лапу Азора" является палиндромом.
94 | */
95 | fun isPalindrome(str: String): Boolean {
96 | val lowerCase = str.toLowerCase().filter { it != ' ' }
97 | for (i in 0..lowerCase.length / 2) {
98 | if (lowerCase[i] != lowerCase[lowerCase.length - i - 1]) return false
99 | }
100 | return true
101 | }
102 |
103 | /**
104 | * Пример
105 | *
106 | * По имеющемуся списку целых чисел, например [3, 6, 5, 4, 9], построить строку с примером их суммирования:
107 | * 3 + 6 + 5 + 4 + 9 = 27 в данном случае.
108 | */
109 | fun buildSumExample(list: List) = list.joinToString(separator = " + ", postfix = " = ${list.sum()}")
110 |
111 | /**
112 | * Простая
113 | *
114 | * Найти модуль заданного вектора, представленного в виде списка v,
115 | * по формуле abs = sqrt(a1^2 + a2^2 + ... + aN^2).
116 | * Модуль пустого вектора считать равным 0.0.
117 | */
118 | fun abs(v: List): Double = TODO()
119 |
120 | /**
121 | * Простая
122 | *
123 | * Рассчитать среднее арифметическое элементов списка list. Вернуть 0.0, если список пуст
124 | */
125 | fun mean(list: List): Double = TODO()
126 |
127 | /**
128 | * Средняя
129 | *
130 | * Центрировать заданный список list, уменьшив каждый элемент на среднее арифметическое всех элементов.
131 | * Если список пуст, не делать ничего. Вернуть изменённый список.
132 | *
133 | * Обратите внимание, что данная функция должна изменять содержание списка list, а не его копии.
134 | */
135 | fun center(list: MutableList): MutableList = TODO()
136 |
137 | /**
138 | * Средняя
139 | *
140 | * Найти скалярное произведение двух векторов равной размерности,
141 | * представленные в виде списков a и b. Скалярное произведение считать по формуле:
142 | * C = a1b1 + a2b2 + ... + aNbN. Произведение пустых векторов считать равным 0.0.
143 | */
144 | fun times(a: List, b: List): Double = TODO()
145 |
146 | /**
147 | * Средняя
148 | *
149 | * Рассчитать значение многочлена при заданном x:
150 | * p(x) = p0 + p1*x + p2*x^2 + p3*x^3 + ... + pN*x^N.
151 | * Коэффициенты многочлена заданы списком p: (p0, p1, p2, p3, ..., pN).
152 | * Значение пустого многочлена равно 0.0 при любом x.
153 | */
154 | fun polynom(p: List, x: Double): Double = TODO()
155 |
156 | /**
157 | * Средняя
158 | *
159 | * В заданном списке list каждый элемент, кроме первого, заменить
160 | * суммой данного элемента и всех предыдущих.
161 | * Например: 1, 2, 3, 4 -> 1, 3, 6, 10.
162 | * Пустой список не следует изменять. Вернуть изменённый список.
163 | *
164 | * Обратите внимание, что данная функция должна изменять содержание списка list, а не его копии.
165 | */
166 | fun accumulate(list: MutableList): MutableList = TODO()
167 |
168 | /**
169 | * Средняя
170 | *
171 | * Разложить заданное натуральное число n > 1 на простые множители.
172 | * Результат разложения вернуть в виде списка множителей, например 75 -> (3, 5, 5).
173 | * Множители в списке должны располагаться по возрастанию.
174 | */
175 | fun factorize(n: Int): List = TODO()
176 |
177 | /**
178 | * Сложная
179 | *
180 | * Разложить заданное натуральное число n > 1 на простые множители.
181 | * Результат разложения вернуть в виде строки, например 75 -> 3*5*5
182 | * Множители в результирующей строке должны располагаться по возрастанию.
183 | */
184 | fun factorizeToString(n: Int): String = TODO()
185 |
186 | /**
187 | * Средняя
188 | *
189 | * Перевести заданное целое число n >= 0 в систему счисления с основанием base > 1.
190 | * Результат перевода вернуть в виде списка цифр в base-ичной системе от старшей к младшей,
191 | * например: n = 100, base = 4 -> (1, 2, 1, 0) или n = 250, base = 14 -> (1, 3, 12)
192 | */
193 | fun convert(n: Int, base: Int): List = TODO()
194 |
195 | /**
196 | * Сложная
197 | *
198 | * Перевести заданное целое число n >= 0 в систему счисления с основанием 1 < base < 37.
199 | * Результат перевода вернуть в виде строки, цифры более 9 представлять латинскими
200 | * строчными буквами: 10 -> a, 11 -> b, 12 -> c и так далее.
201 | * Например: n = 100, base = 4 -> 1210, n = 250, base = 14 -> 13c
202 | */
203 | fun convertToString(n: Int, base: Int): String = TODO()
204 |
205 | /**
206 | * Средняя
207 | *
208 | * Перевести число, представленное списком цифр digits от старшей к младшей,
209 | * из системы счисления с основанием base в десятичную.
210 | * Например: digits = (1, 3, 12), base = 14 -> 250
211 | */
212 | fun decimal(digits: List, base: Int): Int = TODO()
213 |
214 | /**
215 | * Сложная
216 | *
217 | * Перевести число, представленное цифровой строкой str,
218 | * из системы счисления с основанием base в десятичную.
219 | * Цифры более 9 представляются латинскими строчными буквами:
220 | * 10 -> a, 11 -> b, 12 -> c и так далее.
221 | * Например: str = "13c", base = 14 -> 250
222 | */
223 | fun decimalFromString(str: String, base: Int): Int = TODO()
224 |
225 | /**
226 | * Сложная
227 | *
228 | * Перевести натуральное число n > 0 в римскую систему.
229 | * Римские цифры: 1 = I, 4 = IV, 5 = V, 9 = IX, 10 = X, 40 = XL, 50 = L,
230 | * 90 = XC, 100 = C, 400 = CD, 500 = D, 900 = CM, 1000 = M.
231 | * Например: 23 = XXIII, 44 = XLIV, 100 = C
232 | */
233 | fun roman(n: Int): String = TODO()
234 |
235 | /**
236 | * Очень сложная
237 | *
238 | * Записать заданное натуральное число 1..999999 прописью по-русски.
239 | * Например, 375 = "триста семьдесят пять",
240 | * 23964 = "двадцать три тысячи девятьсот шестьдесят четыре"
241 | */
242 | fun russian(n: Int): String = TODO()
--------------------------------------------------------------------------------
/src/lesson5/task1/Map.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER", "ConvertCallChainIntoSequence")
2 |
3 | package lesson5.task1
4 |
5 | /**
6 | * Пример
7 | *
8 | * Для заданного списка покупок `shoppingList` посчитать его общую стоимость
9 | * на основе цен из `costs`. В случае неизвестной цены считать, что товар
10 | * игнорируется.
11 | */
12 | fun shoppingListCost(
13 | shoppingList: List,
14 | costs: Map): Double {
15 | var totalCost = 0.0
16 |
17 | for (item in shoppingList) {
18 | val itemCost = costs[item]
19 | if (itemCost != null) {
20 | totalCost += itemCost
21 | }
22 | }
23 |
24 | return totalCost
25 | }
26 |
27 | /**
28 | * Пример
29 | *
30 | * Для набора "имя"-"номер телефона" `phoneBook` оставить только такие пары,
31 | * для которых телефон начинается с заданного кода страны `countryCode`
32 | */
33 | fun filterByCountryCode(
34 | phoneBook: MutableMap,
35 | countryCode: String) {
36 | val namesToRemove = mutableListOf()
37 |
38 | for ((name, phone) in phoneBook) {
39 | if (!phone.startsWith(countryCode)) {
40 | namesToRemove.add(name)
41 | }
42 | }
43 |
44 | for (name in namesToRemove) {
45 | phoneBook.remove(name)
46 | }
47 | }
48 |
49 | /**
50 | * Пример
51 | *
52 | * Для заданного текста `text` убрать заданные слова-паразиты `fillerWords`
53 | * и вернуть отфильтрованный текст
54 | */
55 | fun removeFillerWords(
56 | text: List,
57 | vararg fillerWords: String): List {
58 | val fillerWordSet = setOf(*fillerWords)
59 |
60 | val res = mutableListOf()
61 | for (word in text) {
62 | if (word !in fillerWordSet) {
63 | res += word
64 | }
65 | }
66 | return res
67 | }
68 |
69 | /**
70 | * Пример
71 | *
72 | * Для заданного текста `text` построить множество встречающихся в нем слов
73 | */
74 | fun buildWordSet(text: List): MutableSet {
75 | val res = mutableSetOf()
76 | for (word in text) res.add(word)
77 | return res
78 | }
79 |
80 | /**
81 | * Средняя
82 | *
83 | * Объединить два ассоциативных массива `mapA` и `mapB` с парами
84 | * "имя"-"номер телефона" в итоговый ассоциативный массив, склеивая
85 | * значения для повторяющихся ключей через запятую.
86 | * В случае повторяющихся *ключей* значение из mapA должно быть
87 | * перед значением из mapB.
88 | *
89 | * Повторяющиеся *значения* следует добавлять только один раз.
90 | *
91 | * Например:
92 | * mergePhoneBooks(
93 | * mapOf("Emergency" to "112", "Police" to "02"),
94 | * mapOf("Emergency" to "911", "Police" to "02")
95 | * ) -> mapOf("Emergency" to "112, 911", "Police" to "02")
96 | */
97 | fun mergePhoneBooks(mapA: Map, mapB: Map): Map = TODO()
98 |
99 | /**
100 | * Простая
101 | *
102 | * По заданному ассоциативному массиву "студент"-"оценка за экзамен" построить
103 | * обратный массив "оценка за экзамен"-"список студентов с этой оценкой".
104 | *
105 | * Например:
106 | * buildGrades(mapOf("Марат" to 3, "Семён" to 5, "Михаил" to 5))
107 | * -> mapOf(5 to listOf("Семён", "Михаил"), 3 to listOf("Марат"))
108 | */
109 | fun buildGrades(grades: Map): Map> = TODO()
110 |
111 | /**
112 | * Простая
113 | *
114 | * Определить, входит ли ассоциативный массив a в ассоциативный массив b;
115 | * это выполняется, если все ключи из a содержатся в b с такими же значениями.
116 | *
117 | * Например:
118 | * containsIn(mapOf("a" to "z"), mapOf("a" to "z", "b" to "sweet")) -> true
119 | * containsIn(mapOf("a" to "z"), mapOf("a" to "zee", "b" to "sweet")) -> false
120 | */
121 | fun containsIn(a: Map, b: Map): Boolean = TODO()
122 |
123 | /**
124 | * Средняя
125 | *
126 | * Для заданного списка пар "акция"-"стоимость" вернуть ассоциативный массив,
127 | * содержащий для каждой акции ее усредненную стоимость.
128 | *
129 | * Например:
130 | * averageStockPrice(listOf("MSFT" to 100.0, "MSFT" to 200.0, "NFLX" to 40.0))
131 | * -> mapOf("MSFT" to 150.0, "NFLX" to 40.0)
132 | */
133 | fun averageStockPrice(stockPrices: List>): Map = TODO()
134 |
135 | /**
136 | * Средняя
137 | *
138 | * Входными данными является ассоциативный массив
139 | * "название товара"-"пара (тип товара, цена товара)"
140 | * и тип интересующего нас товара.
141 | * Необходимо вернуть название товара заданного типа с минимальной стоимостью
142 | * или null в случае, если товаров такого типа нет.
143 | *
144 | * Например:
145 | * findCheapestStuff(
146 | * mapOf("Мария" to ("печенье" to 20.0), "Орео" to ("печенье" to 100.0)),
147 | * "печенье"
148 | * ) -> "Мария"
149 | */
150 | fun findCheapestStuff(stuff: Map>, kind: String): String? = TODO()
151 |
152 | /**
153 | * Сложная
154 | *
155 | * Для заданного ассоциативного массива знакомых через одно рукопожатие `friends`
156 | * необходимо построить его максимальное расширение по рукопожатиям, то есть,
157 | * для каждого человека найти всех людей, с которыми он знаком через любое
158 | * количество рукопожатий.
159 | * Считать, что все имена людей являются уникальными, а также что рукопожатия
160 | * являются направленными, то есть, если Марат знает Свету, то это не означает,
161 | * что Света знает Марата.
162 | *
163 | * Например:
164 | * propagateHandshakes(
165 | * mapOf(
166 | * "Marat" to setOf("Mikhail", "Sveta"),
167 | * "Sveta" to setOf("Marat"),
168 | * "Mikhail" to setOf("Sveta")
169 | * )
170 | * ) -> mapOf(
171 | * "Marat" to setOf("Mikhail", "Sveta"),
172 | * "Sveta" to setOf("Marat", "Mikhail"),
173 | * "Mikhail" to setOf("Sveta", "Marat")
174 | * )
175 | */
176 | fun propagateHandshakes(friends: Map>): Map> = TODO()
177 |
178 | /**
179 | * Простая
180 | *
181 | * Удалить из изменяемого ассоциативного массива все записи,
182 | * которые встречаются в заданном ассоциативном массиве.
183 | * Записи считать одинаковыми, если и ключи, и значения совпадают.
184 | *
185 | * ВАЖНО: необходимо изменить переданный в качестве аргумента
186 | * изменяемый ассоциативный массив
187 | *
188 | * Например:
189 | * subtractOf(a = mutableMapOf("a" to "z"), mapOf("a" to "z"))
190 | * -> a changes to mutableMapOf() aka becomes empty
191 | */
192 | fun subtractOf(a: MutableMap, b: Map): Unit = TODO()
193 |
194 | /**
195 | * Простая
196 | *
197 | * Для двух списков людей найти людей, встречающихся в обоих списках
198 | */
199 | fun whoAreInBoth(a: List, b: List): List = TODO()
200 |
201 | /**
202 | * Средняя
203 | *
204 | * Для заданного набора символов определить, можно ли составить из него
205 | * указанное слово (регистр символов игнорируется)
206 | *
207 | * Например:
208 | * canBuildFrom(listOf('a', 'b', 'o'), "baobab") -> true
209 | */
210 | fun canBuildFrom(chars: List, word: String): Boolean = TODO()
211 |
212 | /**
213 | * Средняя
214 | *
215 | * Найти в заданном списке повторяющиеся элементы и вернуть
216 | * ассоциативный массив с информацией о числе повторений
217 | * для каждого повторяющегося элемента.
218 | * Если элемент встречается только один раз, включать его в результат
219 | * не следует.
220 | *
221 | * Например:
222 | * extractRepeats(listOf("a", "b", "a")) -> mapOf("a" to 2)
223 | */
224 | fun extractRepeats(list: List): Map = TODO()
225 |
226 | /**
227 | * Средняя
228 | *
229 | * Для заданного списка слов определить, содержит ли он анаграммы
230 | * (два слова являются анаграммами, если одно можно составить из второго)
231 | *
232 | * Например:
233 | * hasAnagrams(listOf("тор", "свет", "рот")) -> true
234 | */
235 | fun hasAnagrams(words: List): Boolean = TODO()
236 |
237 | /**
238 | * Сложная
239 | *
240 | * Для заданного списка неотрицательных чисел и числа определить,
241 | * есть ли в списке пара чисел таких, что их сумма равна заданному числу.
242 | * Если да, верните их индексы в виде Pair;
243 | * если нет, верните пару Pair(-1, -1).
244 | *
245 | * Индексы в результате должны следовать в порядке (меньший, больший).
246 | *
247 | * Постарайтесь сделать ваше решение как можно более эффективным,
248 | * используя то, что вы узнали в данном уроке.
249 | *
250 | * Например:
251 | * findSumOfTwo(listOf(1, 2, 3), 4) -> Pair(0, 2)
252 | * findSumOfTwo(listOf(1, 2, 3), 6) -> Pair(-1, -1)
253 | */
254 | fun findSumOfTwo(list: List, number: Int): Pair = TODO()
255 |
256 | /**
257 | * Очень сложная
258 | *
259 | * Входными данными является ассоциативный массив
260 | * "название сокровища"-"пара (вес сокровища, цена сокровища)"
261 | * и вместимость вашего рюкзака.
262 | * Необходимо вернуть множество сокровищ с максимальной суммарной стоимостью,
263 | * которые вы можете унести в рюкзаке.
264 | *
265 | * Например:
266 | * bagPacking(
267 | * mapOf("Кубок" to (500 to 2000), "Слиток" to (1000 to 5000)),
268 | * 850
269 | * ) -> setOf("Кубок")
270 | * bagPacking(
271 | * mapOf("Кубок" to (500 to 2000), "Слиток" to (1000 to 5000)),
272 | * 450
273 | * ) -> emptySet()
274 | */
275 | fun bagPacking(treasures: Map>, capacity: Int): Set = TODO()
276 |
--------------------------------------------------------------------------------
/src/lesson6/task1/Parse.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER", "ConvertCallChainIntoSequence")
2 |
3 | package lesson6.task1
4 |
5 | /**
6 | * Пример
7 | *
8 | * Время представлено строкой вида "11:34:45", содержащей часы, минуты и секунды, разделённые двоеточием.
9 | * Разобрать эту строку и рассчитать количество секунд, прошедшее с начала дня.
10 | */
11 | fun timeStrToSeconds(str: String): Int {
12 | val parts = str.split(":")
13 | var result = 0
14 | for (part in parts) {
15 | val number = part.toInt()
16 | result = result * 60 + number
17 | }
18 | return result
19 | }
20 |
21 | /**
22 | * Пример
23 | *
24 | * Дано число n от 0 до 99.
25 | * Вернуть его же в виде двухсимвольной строки, от "00" до "99"
26 | */
27 | fun twoDigitStr(n: Int) = if (n in 0..9) "0$n" else "$n"
28 |
29 | /**
30 | * Пример
31 | *
32 | * Дано seconds -- время в секундах, прошедшее с начала дня.
33 | * Вернуть текущее время в виде строки в формате "ЧЧ:ММ:СС".
34 | */
35 | fun timeSecondsToStr(seconds: Int): String {
36 | val hour = seconds / 3600
37 | val minute = (seconds % 3600) / 60
38 | val second = seconds % 60
39 | return String.format("%02d:%02d:%02d", hour, minute, second)
40 | }
41 |
42 | /**
43 | * Пример: консольный ввод
44 | */
45 | fun main(args: Array) {
46 | println("Введите время в формате ЧЧ:ММ:СС")
47 | val line = readLine()
48 | if (line != null) {
49 | val seconds = timeStrToSeconds(line)
50 | if (seconds == -1) {
51 | println("Введённая строка $line не соответствует формату ЧЧ:ММ:СС")
52 | }
53 | else {
54 | println("Прошло секунд с начала суток: $seconds")
55 | }
56 | }
57 | else {
58 | println("Достигнут <конец файла> в процессе чтения строки. Программа прервана")
59 | }
60 | }
61 |
62 |
63 | /**
64 | * Средняя
65 | *
66 | * Дата представлена строкой вида "15 июля 2016".
67 | * Перевести её в цифровой формат "15.07.2016".
68 | * День и месяц всегда представлять двумя цифрами, например: 03.04.2011.
69 | * При неверном формате входной строки вернуть пустую строку.
70 | *
71 | * Обратите внимание: некорректная с точки зрения календаря дата (например, 30.02.2009) считается неверными
72 | * входными данными.
73 | */
74 | fun dateStrToDigit(str: String): String = TODO()
75 |
76 | /**
77 | * Средняя
78 | *
79 | * Дата представлена строкой вида "15.07.2016".
80 | * Перевести её в строковый формат вида "15 июля 2016".
81 | * При неверном формате входной строки вернуть пустую строку
82 | *
83 | * Обратите внимание: некорректная с точки зрения календаря дата (например, 30 февраля 2009) считается неверными
84 | * входными данными.
85 | */
86 | fun dateDigitToStr(digital: String): String = TODO()
87 |
88 | /**
89 | * Средняя
90 | *
91 | * Номер телефона задан строкой вида "+7 (921) 123-45-67".
92 | * Префикс (+7) может отсутствовать, код города (в скобках) также может отсутствовать.
93 | * Может присутствовать неограниченное количество пробелов и чёрточек,
94 | * например, номер 12 -- 34- 5 -- 67 -89 тоже следует считать легальным.
95 | * Перевести номер в формат без скобок, пробелов и чёрточек (но с +), например,
96 | * "+79211234567" или "123456789" для приведённых примеров.
97 | * Все символы в номере, кроме цифр, пробелов и +-(), считать недопустимыми.
98 | * При неверном формате вернуть пустую строку
99 | */
100 | fun flattenPhoneNumber(phone: String): String = TODO()
101 |
102 | /**
103 | * Средняя
104 | *
105 | * Результаты спортсмена на соревнованиях в прыжках в длину представлены строкой вида
106 | * "706 - % 717 % 703".
107 | * В строке могут присутствовать числа, черточки - и знаки процента %, разделённые пробелами;
108 | * число соответствует удачному прыжку, - пропущенной попытке, % заступу.
109 | * Прочитать строку и вернуть максимальное присутствующее в ней число (717 в примере).
110 | * При нарушении формата входной строки или при отсутствии в ней чисел, вернуть -1.
111 | */
112 | fun bestLongJump(jumps: String): Int = TODO()
113 |
114 | /**
115 | * Сложная
116 | *
117 | * Результаты спортсмена на соревнованиях в прыжках в высоту представлены строкой вида
118 | * "220 + 224 %+ 228 %- 230 + 232 %%- 234 %".
119 | * Здесь + соответствует удачной попытке, % неудачной, - пропущенной.
120 | * Высота и соответствующие ей попытки разделяются пробелом.
121 | * Прочитать строку и вернуть максимальную взятую высоту (230 в примере).
122 | * При нарушении формата входной строки вернуть -1.
123 | */
124 | fun bestHighJump(jumps: String): Int = TODO()
125 |
126 | /**
127 | * Сложная
128 | *
129 | * В строке представлено выражение вида "2 + 31 - 40 + 13",
130 | * использующее целые положительные числа, плюсы и минусы, разделённые пробелами.
131 | * Наличие двух знаков подряд "13 + + 10" или двух чисел подряд "1 2" не допускается.
132 | * Вернуть значение выражения (6 для примера).
133 | * Про нарушении формата входной строки бросить исключение IllegalArgumentException
134 | */
135 | fun plusMinus(expression: String): Int = TODO()
136 |
137 | /**
138 | * Сложная
139 | *
140 | * Строка состоит из набора слов, отделённых друг от друга одним пробелом.
141 | * Определить, имеются ли в строке повторяющиеся слова, идущие друг за другом.
142 | * Слова, отличающиеся только регистром, считать совпадающими.
143 | * Вернуть индекс начала первого повторяющегося слова, или -1, если повторов нет.
144 | * Пример: "Он пошёл в в школу" => результат 9 (индекс первого 'в')
145 | */
146 | fun firstDuplicateIndex(str: String): Int = TODO()
147 |
148 | /**
149 | * Сложная
150 | *
151 | * Строка содержит названия товаров и цены на них в формате вида
152 | * "Хлеб 39.9; Молоко 62; Курица 184.0; Конфеты 89.9".
153 | * То есть, название товара отделено от цены пробелом,
154 | * а цена отделена от названия следующего товара точкой с запятой и пробелом.
155 | * Вернуть название самого дорогого товара в списке (в примере это Курица),
156 | * или пустую строку при нарушении формата строки.
157 | * Все цены должны быть больше либо равны нуля.
158 | */
159 | fun mostExpensive(description: String): String = TODO()
160 |
161 | /**
162 | * Сложная
163 | *
164 | * Перевести число roman, заданное в римской системе счисления,
165 | * в десятичную систему и вернуть как результат.
166 | * Римские цифры: 1 = I, 4 = IV, 5 = V, 9 = IX, 10 = X, 40 = XL, 50 = L,
167 | * 90 = XC, 100 = C, 400 = CD, 500 = D, 900 = CM, 1000 = M.
168 | * Например: XXIII = 23, XLIV = 44, C = 100
169 | *
170 | * Вернуть -1, если roman не является корректным римским числом
171 | */
172 | fun fromRoman(roman: String): Int = TODO()
173 |
174 | /**
175 | * Очень сложная
176 | *
177 | * Имеется специальное устройство, представляющее собой
178 | * конвейер из cells ячеек (нумеруются от 0 до cells - 1 слева направо) и датчик, двигающийся над этим конвейером.
179 | * Строка commands содержит последовательность команд, выполняемых данным устройством, например +>+>+>+>+
180 | * Каждая команда кодируется одним специальным символом:
181 | * > - сдвиг датчика вправо на 1 ячейку;
182 | * < - сдвиг датчика влево на 1 ячейку;
183 | * + - увеличение значения в ячейке под датчиком на 1 ед.;
184 | * - - уменьшение значения в ячейке под датчиком на 1 ед.;
185 | * [ - если значение под датчиком равно 0, в качестве следующей команды следует воспринимать
186 | * не следующую по порядку, а идущую за соответствующей следующей командой ']' (с учётом вложенности);
187 | * ] - если значение под датчиком не равно 0, в качестве следующей команды следует воспринимать
188 | * не следующую по порядку, а идущую за соответствующей предыдущей командой '[' (с учётом вложенности);
189 | * (комбинация [] имитирует цикл)
190 | * пробел - пустая команда
191 | *
192 | * Изначально все ячейки заполнены значением 0 и датчик стоит на ячейке с номером N/2 (округлять вниз)
193 | *
194 | * После выполнения limit команд или всех команд из commands следует прекратить выполнение последовательности команд.
195 | * Учитываются все команды, в том числе несостоявшиеся переходы ("[" при значении под датчиком не равном 0 и "]" при
196 | * значении под датчиком равном 0) и пробелы.
197 | *
198 | * Вернуть список размера cells, содержащий элементы ячеек устройства после завершения выполнения последовательности.
199 | * Например, для 10 ячеек и командной строки +>+>+>+>+ результат должен быть 0,0,0,0,0,1,1,1,1,1
200 | *
201 | * Все прочие символы следует считать ошибочными и формировать исключение IllegalArgumentException.
202 | * То же исключение формируется, если у символов [ ] не оказывается пары.
203 | * Выход за границу конвейера также следует считать ошибкой и формировать исключение IllegalStateException.
204 | * Считать, что ошибочные символы и непарные скобки являются более приоритетной ошибкой чем выход за границу ленты,
205 | * то есть если в программе присутствует некорректный символ или непарная скобка, то должно быть выброшено
206 | * IllegalArgumentException.
207 | * IllegalArgumentException должен бросаться даже если ошибочная команда не была достигнута в ходе выполнения.
208 | *
209 | */
210 | fun computeDeviceCells(cells: Int, commands: String, limit: Int): List = TODO()
211 |
--------------------------------------------------------------------------------
/src/lesson8/task1/Geometry.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson8.task1
3 |
4 | import lesson1.task1.sqr
5 | import kotlin.math.PI
6 | import kotlin.math.cos
7 | import kotlin.math.sin
8 | import kotlin.math.sqrt
9 |
10 | /**
11 | * Точка на плоскости
12 | */
13 | data class Point(val x: Double, val y: Double) {
14 | /**
15 | * Пример
16 | *
17 | * Рассчитать (по известной формуле) расстояние между двумя точками
18 | */
19 | fun distance(other: Point): Double = sqrt(sqr(x - other.x) + sqr(y - other.y))
20 | }
21 |
22 | /**
23 | * Треугольник, заданный тремя точками (a, b, c, см. constructor ниже).
24 | * Эти три точки хранятся в множестве points, их порядок не имеет значения.
25 | */
26 | class Triangle private constructor(private val points: Set) {
27 |
28 | private val pointList = points.toList()
29 |
30 | val a: Point get() = pointList[0]
31 |
32 | val b: Point get() = pointList[1]
33 |
34 | val c: Point get() = pointList[2]
35 |
36 | constructor(a: Point, b: Point, c: Point): this(linkedSetOf(a, b, c))
37 | /**
38 | * Пример: полупериметр
39 | */
40 | fun halfPerimeter() = (a.distance(b) + b.distance(c) + c.distance(a)) / 2.0
41 |
42 | /**
43 | * Пример: площадь
44 | */
45 | fun area(): Double {
46 | val p = halfPerimeter()
47 | return sqrt(p * (p - a.distance(b)) * (p - b.distance(c)) * (p - c.distance(a)))
48 | }
49 |
50 | /**
51 | * Пример: треугольник содержит точку
52 | */
53 | fun contains(p: Point): Boolean {
54 | val abp = Triangle(a, b, p)
55 | val bcp = Triangle(b, c, p)
56 | val cap = Triangle(c, a, p)
57 | return abp.area() + bcp.area() + cap.area() <= area()
58 | }
59 |
60 | override fun equals(other: Any?) = other is Triangle && points == other.points
61 |
62 | override fun hashCode() = points.hashCode()
63 |
64 | override fun toString() = "Triangle(a = $a, b = $b, c = $c)"
65 | }
66 |
67 | /**
68 | * Окружность с заданным центром и радиусом
69 | */
70 | data class Circle(val center: Point, val radius: Double) {
71 | /**
72 | * Простая
73 | *
74 | * Рассчитать расстояние между двумя окружностями.
75 | * Расстояние между непересекающимися окружностями рассчитывается как
76 | * расстояние между их центрами минус сумма их радиусов.
77 | * Расстояние между пересекающимися окружностями считать равным 0.0.
78 | */
79 | fun distance(other: Circle): Double = TODO()
80 |
81 | /**
82 | * Тривиальная
83 | *
84 | * Вернуть true, если и только если окружность содержит данную точку НА себе или ВНУТРИ себя
85 | */
86 | fun contains(p: Point): Boolean = TODO()
87 | }
88 |
89 | /**
90 | * Отрезок между двумя точками
91 | */
92 | data class Segment(val begin: Point, val end: Point) {
93 | override fun equals(other: Any?) =
94 | other is Segment && (begin == other.begin && end == other.end || end == other.begin && begin == other.end)
95 |
96 | override fun hashCode() =
97 | begin.hashCode() + end.hashCode()
98 | }
99 |
100 | /**
101 | * Средняя
102 | *
103 | * Дано множество точек. Вернуть отрезок, соединяющий две наиболее удалённые из них.
104 | * Если в множестве менее двух точек, бросить IllegalArgumentException
105 | */
106 | fun diameter(vararg points: Point): Segment = TODO()
107 |
108 | /**
109 | * Простая
110 | *
111 | * Построить окружность по её диаметру, заданному двумя точками
112 | * Центр её должен находиться посередине между точками, а радиус составлять половину расстояния между ними
113 | */
114 | fun circleByDiameter(diameter: Segment): Circle = TODO()
115 |
116 | /**
117 | * Прямая, заданная точкой point и углом наклона angle (в радианах) по отношению к оси X.
118 | * Уравнение прямой: (y - point.y) * cos(angle) = (x - point.x) * sin(angle)
119 | * или: y * cos(angle) = x * sin(angle) + b, где b = point.y * cos(angle) - point.x * sin(angle).
120 | * Угол наклона обязан находиться в диапазоне от 0 (включительно) до PI (исключительно).
121 | */
122 | class Line private constructor(val b: Double, val angle: Double) {
123 | init {
124 | require(angle >= 0 && angle < PI) { "Incorrect line angle: $angle" }
125 | }
126 |
127 | constructor(point: Point, angle: Double): this(point.y * cos(angle) - point.x * sin(angle), angle)
128 |
129 | /**
130 | * Средняя
131 | *
132 | * Найти точку пересечения с другой линией.
133 | * Для этого необходимо составить и решить систему из двух уравнений (каждое для своей прямой)
134 | */
135 | fun crossPoint(other: Line): Point = TODO()
136 |
137 | override fun equals(other: Any?) = other is Line && angle == other.angle && b == other.b
138 |
139 | override fun hashCode(): Int {
140 | var result = b.hashCode()
141 | result = 31 * result + angle.hashCode()
142 | return result
143 | }
144 |
145 | override fun toString() = "Line(${cos(angle)} * y = ${sin(angle)} * x + $b)"
146 | }
147 |
148 | /**
149 | * Средняя
150 | *
151 | * Построить прямую по отрезку
152 | */
153 | fun lineBySegment(s: Segment): Line = TODO()
154 |
155 | /**
156 | * Средняя
157 | *
158 | * Построить прямую по двум точкам
159 | */
160 | fun lineByPoints(a: Point, b: Point): Line = TODO()
161 |
162 | /**
163 | * Сложная
164 | *
165 | * Построить серединный перпендикуляр по отрезку или по двум точкам
166 | */
167 | fun bisectorByPoints(a: Point, b: Point): Line = TODO()
168 |
169 | /**
170 | * Средняя
171 | *
172 | * Задан список из n окружностей на плоскости. Найти пару наименее удалённых из них.
173 | * Если в списке менее двух окружностей, бросить IllegalArgumentException
174 | */
175 | fun findNearestCirclePair(vararg circles: Circle): Pair = TODO()
176 |
177 | /**
178 | * Сложная
179 | *
180 | * Дано три различные точки. Построить окружность, проходящую через них
181 | * (все три точки должны лежать НА, а не ВНУТРИ, окружности).
182 | * Описание алгоритмов см. в Интернете
183 | * (построить окружность по трём точкам, или
184 | * построить окружность, описанную вокруг треугольника - эквивалентная задача).
185 | */
186 | fun circleByThreePoints(a: Point, b: Point, c: Point): Circle = TODO()
187 |
188 | /**
189 | * Очень сложная
190 | *
191 | * Дано множество точек на плоскости. Найти круг минимального радиуса,
192 | * содержащий все эти точки. Если множество пустое, бросить IllegalArgumentException.
193 | * Если множество содержит одну точку, вернуть круг нулевого радиуса с центром в данной точке.
194 | *
195 | * Примечание: в зависимости от ситуации, такая окружность может либо проходить через какие-либо
196 | * три точки данного множества, либо иметь своим диаметром отрезок,
197 | * соединяющий две самые удалённые точки в данном множестве.
198 | */
199 | fun minContainingCircle(vararg points: Point): Circle = TODO()
200 |
201 |
--------------------------------------------------------------------------------
/src/lesson8/task2/Chess.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson8.task2
3 |
4 | /**
5 | * Клетка шахматной доски. Шахматная доска квадратная и имеет 8 х 8 клеток.
6 | * Поэтому, обе координаты клетки (горизонталь row, вертикаль column) могут находиться в пределах от 1 до 8.
7 | * Горизонтали нумеруются снизу вверх, вертикали слева направо.
8 | */
9 | data class Square(val column: Int, val row: Int) {
10 | /**
11 | * Пример
12 | *
13 | * Возвращает true, если клетка находится в пределах доски
14 | */
15 | fun inside(): Boolean = column in 1..8 && row in 1..8
16 |
17 | /**
18 | * Простая
19 | *
20 | * Возвращает строковую нотацию для клетки.
21 | * В нотации, колонки обозначаются латинскими буквами от a до h, а ряды -- цифрами от 1 до 8.
22 | * Для клетки не в пределах доски вернуть пустую строку
23 | */
24 | fun notation(): String = TODO()
25 | }
26 |
27 | /**
28 | * Простая
29 | *
30 | * Создаёт клетку по строковой нотации.
31 | * В нотации, колонки обозначаются латинскими буквами от a до h, а ряды -- цифрами от 1 до 8.
32 | * Если нотация некорректна, бросить IllegalArgumentException
33 | */
34 | fun square(notation: String): Square = TODO()
35 |
36 | /**
37 | * Простая
38 | *
39 | * Определить число ходов, за которое шахматная ладья пройдёт из клетки start в клетку end.
40 | * Шахматная ладья может за один ход переместиться на любую другую клетку
41 | * по вертикали или горизонтали.
42 | * Ниже точками выделены возможные ходы ладьи, а крестиками -- невозможные:
43 | *
44 | * xx.xxххх
45 | * xх.хxххх
46 | * ..Л.....
47 | * xх.хxххх
48 | * xx.xxххх
49 | * xx.xxххх
50 | * xx.xxххх
51 | * xx.xxххх
52 | *
53 | * Если клетки start и end совпадают, вернуть 0.
54 | * Если любая из клеток некорректна, бросить IllegalArgumentException().
55 | *
56 | * Пример: rookMoveNumber(Square(3, 1), Square(6, 3)) = 2
57 | * Ладья может пройти через клетку (3, 3) или через клетку (6, 1) к клетке (6, 3).
58 | */
59 | fun rookMoveNumber(start: Square, end: Square): Int = TODO()
60 |
61 | /**
62 | * Средняя
63 | *
64 | * Вернуть список из клеток, по которым шахматная ладья может быстрее всего попасть из клетки start в клетку end.
65 | * Описание ходов ладьи см. предыдущую задачу.
66 | * Список всегда включает в себя клетку start. Клетка end включается, если она не совпадает со start.
67 | * Между ними должны находиться промежуточные клетки, по порядку от start до end.
68 | * Примеры: rookTrajectory(Square(3, 3), Square(3, 3)) = listOf(Square(3, 3))
69 | * (здесь возможен ещё один вариант)
70 | * rookTrajectory(Square(3, 1), Square(6, 3)) = listOf(Square(3, 1), Square(3, 3), Square(6, 3))
71 | * (здесь возможен единственный вариант)
72 | * rookTrajectory(Square(3, 5), Square(8, 5)) = listOf(Square(3, 5), Square(8, 5))
73 | * Если возможно несколько вариантов самой быстрой траектории, вернуть любой из них.
74 | */
75 | fun rookTrajectory(start: Square, end: Square): List = TODO()
76 |
77 | /**
78 | * Простая
79 | *
80 | * Определить число ходов, за которое шахматный слон пройдёт из клетки start в клетку end.
81 | * Шахматный слон может за один ход переместиться на любую другую клетку по диагонали.
82 | * Ниже точками выделены возможные ходы слона, а крестиками -- невозможные:
83 | *
84 | * .xxx.ххх
85 | * x.x.xххх
86 | * xxСxxxxx
87 | * x.x.xххх
88 | * .xxx.ххх
89 | * xxxxx.хх
90 | * xxxxxх.х
91 | * xxxxxхх.
92 | *
93 | * Если клетки start и end совпадают, вернуть 0.
94 | * Если клетка end недостижима для слона, вернуть -1.
95 | * Если любая из клеток некорректна, бросить IllegalArgumentException().
96 | *
97 | * Примеры: bishopMoveNumber(Square(3, 1), Square(6, 3)) = -1; bishopMoveNumber(Square(3, 1), Square(3, 7)) = 2.
98 | * Слон может пройти через клетку (6, 4) к клетке (3, 7).
99 | */
100 | fun bishopMoveNumber(start: Square, end: Square): Int = TODO()
101 |
102 | /**
103 | * Сложная
104 | *
105 | * Вернуть список из клеток, по которым шахматный слон может быстрее всего попасть из клетки start в клетку end.
106 | * Описание ходов слона см. предыдущую задачу.
107 | *
108 | * Если клетка end недостижима для слона, вернуть пустой список.
109 | *
110 | * Если клетка достижима:
111 | * - список всегда включает в себя клетку start
112 | * - клетка end включается, если она не совпадает со start.
113 | * - между ними должны находиться промежуточные клетки, по порядку от start до end.
114 | *
115 | * Примеры: bishopTrajectory(Square(3, 3), Square(3, 3)) = listOf(Square(3, 3))
116 | * bishopTrajectory(Square(3, 1), Square(3, 7)) = listOf(Square(3, 1), Square(6, 4), Square(3, 7))
117 | * bishopTrajectory(Square(1, 3), Square(6, 8)) = listOf(Square(1, 3), Square(6, 8))
118 | * Если возможно несколько вариантов самой быстрой траектории, вернуть любой из них.
119 | */
120 | fun bishopTrajectory(start: Square, end: Square): List = TODO()
121 |
122 | /**
123 | * Средняя
124 | *
125 | * Определить число ходов, за которое шахматный король пройдёт из клетки start в клетку end.
126 | * Шахматный король одним ходом может переместиться из клетки, в которой стоит,
127 | * на любую соседнюю по вертикали, горизонтали или диагонали.
128 | * Ниже точками выделены возможные ходы короля, а крестиками -- невозможные:
129 | *
130 | * xxxxx
131 | * x...x
132 | * x.K.x
133 | * x...x
134 | * xxxxx
135 | *
136 | * Если клетки start и end совпадают, вернуть 0.
137 | * Если любая из клеток некорректна, бросить IllegalArgumentException().
138 | *
139 | * Пример: kingMoveNumber(Square(3, 1), Square(6, 3)) = 3.
140 | * Король может последовательно пройти через клетки (4, 2) и (5, 2) к клетке (6, 3).
141 | */
142 | fun kingMoveNumber(start: Square, end: Square): Int = TODO()
143 |
144 | /**
145 | * Сложная
146 | *
147 | * Вернуть список из клеток, по которым шахматный король может быстрее всего попасть из клетки start в клетку end.
148 | * Описание ходов короля см. предыдущую задачу.
149 | * Список всегда включает в себя клетку start. Клетка end включается, если она не совпадает со start.
150 | * Между ними должны находиться промежуточные клетки, по порядку от start до end.
151 | * Примеры: kingTrajectory(Square(3, 3), Square(3, 3)) = listOf(Square(3, 3))
152 | * (здесь возможны другие варианты)
153 | * kingTrajectory(Square(3, 1), Square(6, 3)) = listOf(Square(3, 1), Square(4, 2), Square(5, 2), Square(6, 3))
154 | * (здесь возможен единственный вариант)
155 | * kingTrajectory(Square(3, 5), Square(6, 2)) = listOf(Square(3, 5), Square(4, 4), Square(5, 3), Square(6, 2))
156 | * Если возможно несколько вариантов самой быстрой траектории, вернуть любой из них.
157 | */
158 | fun kingTrajectory(start: Square, end: Square): List = TODO()
159 |
160 | /**
161 | * Сложная
162 | *
163 | * Определить число ходов, за которое шахматный конь пройдёт из клетки start в клетку end.
164 | * Шахматный конь одним ходом вначале передвигается ровно на 2 клетки по горизонтали или вертикали,
165 | * а затем ещё на 1 клетку под прямым углом, образуя букву "Г".
166 | * Ниже точками выделены возможные ходы коня, а крестиками -- невозможные:
167 | *
168 | * .xxx.xxx
169 | * xxKxxxxx
170 | * .xxx.xxx
171 | * x.x.xxxx
172 | * xxxxxxxx
173 | * xxxxxxxx
174 | * xxxxxxxx
175 | * xxxxxxxx
176 | *
177 | * Если клетки start и end совпадают, вернуть 0.
178 | * Если любая из клеток некорректна, бросить IllegalArgumentException().
179 | *
180 | * Пример: knightMoveNumber(Square(3, 1), Square(6, 3)) = 3.
181 | * Конь может последовательно пройти через клетки (5, 2) и (4, 4) к клетке (6, 3).
182 | */
183 | fun knightMoveNumber(start: Square, end: Square): Int = TODO()
184 |
185 | /**
186 | * Очень сложная
187 | *
188 | * Вернуть список из клеток, по которым шахматный конь может быстрее всего попасть из клетки start в клетку end.
189 | * Описание ходов коня см. предыдущую задачу.
190 | * Список всегда включает в себя клетку start. Клетка end включается, если она не совпадает со start.
191 | * Между ними должны находиться промежуточные клетки, по порядку от start до end.
192 | * Примеры:
193 | *
194 | * knightTrajectory(Square(3, 3), Square(3, 3)) = listOf(Square(3, 3))
195 | * здесь возможны другие варианты)
196 | * knightTrajectory(Square(3, 1), Square(6, 3)) = listOf(Square(3, 1), Square(5, 2), Square(4, 4), Square(6, 3))
197 | * (здесь возможен единственный вариант)
198 | * knightTrajectory(Square(3, 5), Square(5, 6)) = listOf(Square(3, 5), Square(5, 6))
199 | * (здесь опять возможны другие варианты)
200 | * knightTrajectory(Square(7, 7), Square(8, 8)) =
201 | * listOf(Square(7, 7), Square(5, 8), Square(4, 6), Square(6, 7), Square(8, 8))
202 | *
203 | * Если возможно несколько вариантов самой быстрой траектории, вернуть любой из них.
204 | */
205 | fun knightTrajectory(start: Square, end: Square): List = TODO()
206 |
--------------------------------------------------------------------------------
/src/lesson8/task3/Graph.kt:
--------------------------------------------------------------------------------
1 | package lesson8.task3
2 |
3 | import java.util.*
4 |
5 | class Graph {
6 | private data class Vertex(val name: String) {
7 | val neighbors = mutableSetOf()
8 | }
9 |
10 | private val vertices = mutableMapOf()
11 |
12 | private operator fun get(name: String) = vertices[name] ?: throw IllegalArgumentException()
13 |
14 | fun addVertex(name: String) {
15 | vertices[name] = Vertex(name)
16 | }
17 |
18 | private fun connect(first: Vertex, second: Vertex) {
19 | first.neighbors.add(second)
20 | second.neighbors.add(first)
21 | }
22 |
23 | fun connect(first: String, second: String) = connect(this[first], this[second])
24 |
25 | /**
26 | * Пример
27 | *
28 | * По двум вершинам рассчитать расстояние между ними = число дуг на самом коротком пути между ними.
29 | * Вернуть -1, если пути между вершинами не существует.
30 | *
31 | * Используется поиск в ширину
32 | */
33 | fun bfs(start: String, finish: String) = bfs(this[start], this[finish])
34 |
35 | private fun bfs(start: Vertex, finish: Vertex): Int {
36 | val queue = ArrayDeque()
37 | queue.add(start)
38 | val visited = mutableMapOf(start to 0)
39 | while (queue.isNotEmpty()) {
40 | val next = queue.poll()
41 | val distance = visited[next]!!
42 | if (next == finish) return distance
43 | for (neighbor in next.neighbors) {
44 | if (neighbor in visited) continue
45 | visited.put(neighbor, distance + 1)
46 | queue.add(neighbor)
47 | }
48 | }
49 | return -1
50 | }
51 |
52 | /**
53 | * Пример
54 | *
55 | * По двум вершинам рассчитать расстояние между ними = число дуг на самом коротком пути между ними.
56 | * Вернуть -1, если пути между вершинами не существует.
57 | *
58 | * Используется поиск в глубину
59 | */
60 | fun dfs(start: String, finish: String): Int = dfs(this[start], this[finish], setOf()) ?: -1
61 |
62 | private fun dfs(start: Vertex, finish: Vertex, visited: Set): Int? =
63 | if (start == finish) 0
64 | else {
65 | val min = start.neighbors
66 | .filter { it !in visited }
67 | .mapNotNull { dfs(it, finish, visited + start) }
68 | .min()
69 | if (min == null) null else min + 1
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/lesson9/task1/Matrix.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER", "unused")
2 | package lesson9.task1
3 |
4 | /**
5 | * Ячейка матрицы: row = ряд, column = колонка
6 | */
7 | data class Cell(val row: Int, val column: Int)
8 |
9 | /**
10 | * Интерфейс, описывающий возможности матрицы. E = тип элемента матрицы
11 | */
12 | interface Matrix {
13 | /** Высота */
14 | val height: Int
15 |
16 | /** Ширина */
17 | val width: Int
18 |
19 | /**
20 | * Доступ к ячейке.
21 | * Методы могут бросить исключение, если ячейка не существует или пуста
22 | */
23 | operator fun get(row: Int, column: Int): E
24 | operator fun get(cell: Cell): E
25 |
26 | /**
27 | * Запись в ячейку.
28 | * Методы могут бросить исключение, если ячейка не существует
29 | */
30 | operator fun set(row: Int, column: Int, value: E)
31 | operator fun set(cell: Cell, value: E)
32 | }
33 |
34 | /**
35 | * Простая
36 | *
37 | * Метод для создания матрицы, должен вернуть РЕАЛИЗАЦИЮ Matrix.
38 | * height = высота, width = ширина, e = чем заполнить элементы.
39 | * Бросить исключение IllegalArgumentException, если height или width <= 0.
40 | */
41 | fun createMatrix(height: Int, width: Int, e: E): Matrix = TODO()
42 |
43 | /**
44 | * Средняя сложность
45 | *
46 | * Реализация интерфейса "матрица"
47 | */
48 | class MatrixImpl : Matrix {
49 | override val height: Int = TODO()
50 |
51 | override val width: Int = TODO()
52 |
53 | override fun get(row: Int, column: Int): E = TODO()
54 |
55 | override fun get(cell: Cell): E = TODO()
56 |
57 | override fun set(row: Int, column: Int, value: E) {
58 | TODO()
59 | }
60 |
61 | override fun set(cell: Cell, value: E) {
62 | TODO()
63 | }
64 |
65 | override fun equals(other: Any?) = TODO()
66 |
67 | override fun toString(): String = TODO()
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/src/lesson9/task2/Matrices.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 | package lesson9.task2
3 |
4 | import lesson9.task1.Matrix
5 | import lesson9.task1.createMatrix
6 |
7 | // Все задачи в этом файле требуют наличия реализации интерфейса "Матрица" в Matrix.kt
8 |
9 | /**
10 | * Пример
11 | *
12 | * Транспонировать заданную матрицу matrix.
13 | * При транспонировании строки матрицы становятся столбцами и наоборот:
14 | *
15 | * 1 2 3 1 4 6 3
16 | * 4 5 6 ==> 2 5 5 2
17 | * 6 5 4 3 6 4 1
18 | * 3 2 1
19 | */
20 | fun transpose(matrix: Matrix): Matrix {
21 | if (matrix.width < 1 || matrix.height < 1) return matrix
22 | val result = createMatrix(height = matrix.width, width = matrix.height, e = matrix[0, 0])
23 | for (i in 0 until matrix.width) {
24 | for (j in 0 until matrix.height) {
25 | result[i, j] = matrix[j, i]
26 | }
27 | }
28 | return result
29 | }
30 |
31 | /**
32 | * Пример
33 | *
34 | * Сложить две заданные матрицы друг с другом.
35 | * Складывать можно только матрицы совпадающего размера -- в противном случае бросить IllegalArgumentException.
36 | * При сложении попарно складываются соответствующие элементы матриц
37 | */
38 | operator fun Matrix.plus(other: Matrix): Matrix {
39 | if (width != other.width || height != other.height) throw IllegalArgumentException()
40 | if (width < 1 || height < 1) return this
41 | val result = createMatrix(height, width, this[0, 0])
42 | for (i in 0 until height) {
43 | for (j in 0 until width) {
44 | result[i, j] = this[i, j] + other[i, j]
45 | }
46 | }
47 | return result
48 | }
49 |
50 | /**
51 | * Сложная
52 | *
53 | * Заполнить матрицу заданной высоты height и ширины width
54 | * натуральными числами от 1 до m*n по спирали,
55 | * начинающейся в левом верхнем углу и закрученной по часовой стрелке.
56 | *
57 | * Пример для height = 3, width = 4:
58 | * 1 2 3 4
59 | * 10 11 12 5
60 | * 9 8 7 6
61 | */
62 | fun generateSpiral(height: Int, width: Int): Matrix = TODO()
63 |
64 | /**
65 | * Сложная
66 | *
67 | * Заполнить матрицу заданной высоты height и ширины width следующим образом.
68 | * Элементам, находящимся на периферии (по периметру матрицы), присвоить значение 1;
69 | * периметру оставшейся подматрицы – значение 2 и так далее до заполнения всей матрицы.
70 | *
71 | * Пример для height = 5, width = 6:
72 | * 1 1 1 1 1 1
73 | * 1 2 2 2 2 1
74 | * 1 2 3 3 2 1
75 | * 1 2 2 2 2 1
76 | * 1 1 1 1 1 1
77 | */
78 | fun generateRectangles(height: Int, width: Int): Matrix = TODO()
79 |
80 | /**
81 | * Сложная
82 | *
83 | * Заполнить матрицу заданной высоты height и ширины width диагональной змейкой:
84 | * в левый верхний угол 1, во вторую от угла диагональ 2 и 3 сверху вниз, в третью 4-6 сверху вниз и так далее.
85 | *
86 | * Пример для height = 5, width = 4:
87 | * 1 2 4 7
88 | * 3 5 8 11
89 | * 6 9 12 15
90 | * 10 13 16 18
91 | * 14 17 19 20
92 | */
93 | fun generateSnake(height: Int, width: Int): Matrix = TODO()
94 |
95 | /**
96 | * Средняя
97 | *
98 | * Содержимое квадратной матрицы matrix (с произвольным содержимым) повернуть на 90 градусов по часовой стрелке.
99 | * Если height != width, бросить IllegalArgumentException.
100 | *
101 | * Пример: Станет:
102 | * 1 2 3 7 4 1
103 | * 4 5 6 8 5 2
104 | * 7 8 9 9 6 3
105 | */
106 | fun rotate(matrix: Matrix): Matrix = TODO()
107 |
108 | /**
109 | * Сложная
110 | *
111 | * Проверить, является ли квадратная целочисленная матрица matrix латинским квадратом.
112 | * Латинским квадратом называется матрица размером n x n,
113 | * каждая строка и каждый столбец которой содержат все числа от 1 до n.
114 | * Если height != width, вернуть false.
115 | *
116 | * Пример латинского квадрата 3х3:
117 | * 2 3 1
118 | * 1 2 3
119 | * 3 1 2
120 | */
121 | fun isLatinSquare(matrix: Matrix): Boolean = TODO()
122 |
123 | /**
124 | * Средняя
125 | *
126 | * В матрице matrix каждый элемент заменить суммой непосредственно примыкающих к нему
127 | * элементов по вертикали, горизонтали и диагоналям.
128 | *
129 | * Пример для матрицы 4 x 3: (11=2+4+5, 19=1+3+4+5+6, ...)
130 | * 1 2 3 11 19 13
131 | * 4 5 6 ===> 19 31 19
132 | * 6 5 4 19 31 19
133 | * 3 2 1 13 19 11
134 | *
135 | * Поскольку в матрице 1 х 1 примыкающие элементы отсутствуют,
136 | * для неё следует вернуть как результат нулевую матрицу:
137 | *
138 | * 42 ===> 0
139 | */
140 | fun sumNeighbours(matrix: Matrix): Matrix = TODO()
141 |
142 | /**
143 | * Средняя
144 | *
145 | * Целочисленная матрица matrix состоит из "дырок" (на их месте стоит 0) и "кирпичей" (на их месте стоит 1).
146 | * Найти в этой матрице все ряды и колонки, целиком состоящие из "дырок".
147 | * Результат вернуть в виде Holes(rows = список дырчатых рядов, columns = список дырчатых колонок).
148 | * Ряды и колонки нумеруются с нуля. Любой из спискоов rows / columns может оказаться пустым.
149 | *
150 | * Пример для матрицы 5 х 4:
151 | * 1 0 1 0
152 | * 0 0 1 0
153 | * 1 0 0 0 ==> результат: Holes(rows = listOf(4), columns = listOf(1, 3)): 4-й ряд, 1-я и 3-я колонки
154 | * 0 0 1 0
155 | * 0 0 0 0
156 | */
157 | fun findHoles(matrix: Matrix): Holes = TODO()
158 |
159 | /**
160 | * Класс для описания местонахождения "дырок" в матрице
161 | */
162 | data class Holes(val rows: List, val columns: List)
163 |
164 | /**
165 | * Средняя
166 | *
167 | * В целочисленной матрице matrix каждый элемент заменить суммой элементов подматрицы,
168 | * расположенной в левом верхнем углу матрицы matrix и ограниченной справа-снизу данным элементом.
169 | *
170 | * Пример для матрицы 3 х 3:
171 | *
172 | * 1 2 3 1 3 6
173 | * 4 5 6 => 5 12 21
174 | * 7 8 9 12 27 45
175 | *
176 | * К примеру, центральный элемент 12 = 1 + 2 + 4 + 5, элемент в левом нижнем углу 12 = 1 + 4 + 7 и так далее.
177 | */
178 | fun sumSubMatrix(matrix: Matrix): Matrix = TODO()
179 |
180 | /**
181 | * Сложная
182 | *
183 | * Даны мозаичные изображения замочной скважины и ключа. Пройдет ли ключ в скважину?
184 | * То есть даны две матрицы key и lock, key.height <= lock.height, key.width <= lock.width, состоящие из нулей и единиц.
185 | *
186 | * Проверить, можно ли наложить матрицу key на матрицу lock (без поворота, разрешается только сдвиг) так,
187 | * чтобы каждой единице в матрице lock (штырь) соответствовал ноль в матрице key (прорезь),
188 | * а каждому нулю в матрице lock (дырка) соответствовала, наоборот, единица в матрице key (штырь).
189 | * Ключ при сдвиге не может выходить за пределы замка.
190 | *
191 | * Пример: ключ подойдёт, если его сдвинуть на 1 по ширине
192 | * lock key
193 | * 1 0 1 1 0
194 | * 0 1 0 0 1
195 | * 1 1 1
196 | *
197 | * Вернуть тройку (Triple) -- (да/нет, требуемый сдвиг по высоте, требуемый сдвиг по ширине).
198 | * Если наложение невозможно, то первый элемент тройки "нет" и сдвиги могут быть любыми.
199 | */
200 | fun canOpenLock(key: Matrix, lock: Matrix): Triple = TODO()
201 |
202 | /**
203 | * Простая
204 | *
205 | * Инвертировать заданную матрицу.
206 | * При инвертировании знак каждого элемента матрицы следует заменить на обратный
207 | */
208 | operator fun Matrix.unaryMinus(): Matrix = TODO(this.toString())
209 |
210 | /**
211 | * Средняя
212 | *
213 | * Перемножить две заданные матрицы друг с другом.
214 | * Матрицы можно умножать, только если ширина первой матрицы совпадает с высотой второй матрицы.
215 | * В противном случае бросить IllegalArgumentException.
216 | * Подробно про порядок умножения см. статью Википедии "Умножение матриц".
217 | */
218 | operator fun Matrix.times(other: Matrix): Matrix = TODO(this.toString())
219 |
220 | /**
221 | * Сложная
222 | *
223 | * В матрице matrix размером 4х4 дана исходная позиция для игры в 15, например
224 | * 5 7 9 1
225 | * 2 12 14 15
226 | * 3 4 6 8
227 | * 10 11 13 0
228 | *
229 | * Здесь 0 обозначает пустую клетку, а 1-15 – фишки с соответствующими номерами.
230 | * Напомним, что "игра в 15" имеет квадратное поле 4х4, по которому двигается 15 фишек,
231 | * одна клетка всегда остаётся пустой. Цель игры -- упорядочить фишки на игровом поле.
232 | *
233 | * В списке moves задана последовательность ходов, например [8, 6, 13, 11, 10, 3].
234 | * Ход задаётся номером фишки, которая передвигается на пустое место (то есть, меняется местами с нулём).
235 | * Фишка должна примыкать к пустому месту по горизонтали или вертикали, иначе ход не будет возможным.
236 | * Все номера должны быть в пределах от 1 до 15.
237 | * Определить финальную позицию после выполнения всех ходов и вернуть её.
238 | * Если какой-либо ход является невозможным или список содержит неверные номера,
239 | * бросить IllegalStateException.
240 | *
241 | * В данном случае должно получиться
242 | * 5 7 9 1
243 | * 2 12 14 15
244 | * 0 4 13 6
245 | * 3 10 11 8
246 | */
247 | fun fifteenGameMoves(matrix: Matrix, moves: List): Matrix = TODO()
248 |
249 | /**
250 | * Очень сложная
251 | *
252 | * В матрице matrix размером 4х4 дана исходная позиция для игры в 15, например
253 | * 5 7 9 2
254 | * 1 12 14 15
255 | * 3 4 6 8
256 | * 10 11 13 0
257 | *
258 | * Здесь 0 обозначает пустую клетку, а 1-15 – фишки с соответствующими номерами.
259 | * Напомним, что "игра в 15" имеет квадратное поле 4х4, по которому двигается 15 фишек,
260 | * одна клетка всегда остаётся пустой.
261 | *
262 | * Цель игры -- упорядочить фишки на игровом поле, приведя позицию к одному из следующих двух состояний:
263 | *
264 | * 1 2 3 4 1 2 3 4
265 | * 5 6 7 8 ИЛИ 5 6 7 8
266 | * 9 10 11 12 9 10 11 12
267 | * 13 14 15 0 13 15 14 0
268 | *
269 | * Можно математически доказать, что РОВНО ОДНО из этих двух состояний достижимо из любой исходной позиции.
270 | *
271 | * Вернуть решение -- список ходов, приводящих исходную позицию к одной из двух упорядоченных.
272 | * Каждый ход -- это перемена мест фишки с заданным номером с пустой клеткой (0),
273 | * при этом заданная фишка должна по горизонтали или по вертикали примыкать к пустой клетке (но НЕ по диагонали).
274 | * К примеру, ход 13 в исходной позиции меняет местами 13 и 0, а ход 11 в той же позиции невозможен.
275 | *
276 | * Одно из решений исходной позиции:
277 | *
278 | * [8, 6, 14, 12, 4, 11, 13, 14, 12, 4,
279 | * 7, 5, 1, 3, 11, 7, 3, 11, 7, 12, 6,
280 | * 15, 4, 9, 2, 4, 9, 3, 5, 2, 3, 9,
281 | * 15, 8, 14, 13, 12, 7, 11, 5, 7, 6,
282 | * 9, 15, 8, 14, 13, 9, 15, 7, 6, 12,
283 | * 9, 13, 14, 15, 12, 11, 10, 9, 13, 14,
284 | * 15, 12, 11, 10, 9, 13, 14, 15]
285 | *
286 | * Перед решением этой задачи НЕОБХОДИМО решить предыдущую
287 | */
288 | fun fifteenGameSolution(matrix: Matrix): List = TODO()
289 |
--------------------------------------------------------------------------------
/test/lesson1/task1/Tests.kt:
--------------------------------------------------------------------------------
1 | package lesson1.task1
2 |
3 | import org.junit.jupiter.api.Assertions.assertEquals
4 | import org.junit.jupiter.api.Tag
5 | import org.junit.jupiter.api.Test
6 | import kotlin.math.PI
7 |
8 | class Tests {
9 | @Test
10 | @Tag("Example")
11 | fun sqr() {
12 | assertEquals(0, sqr(0))
13 | assertEquals(4, sqr(2))
14 | assertEquals(9, sqr(-3))
15 | }
16 |
17 | @Test
18 | @Tag("Example")
19 | fun sqrDouble() {
20 | assertEquals(0.0, sqr(0.0), 1e-13)
21 | assertEquals(4.0, sqr(2.0), 1e-13)
22 | assertEquals(9.0, sqr(-3.0), 1e-13)
23 | }
24 |
25 | @Test
26 | @Tag("Example")
27 | fun discriminant() {
28 | assertEquals(0.0, discriminant(0.0, 0.0, 0.0), 1e-13)
29 | assertEquals(0.0, discriminant(1.0, -2.0, 1.0), 1e-13)
30 | assertEquals(1.0, discriminant(1.0, 3.0, 2.0), 1e-13)
31 | }
32 |
33 | @Test
34 | @Tag("Example")
35 | fun quadraticEquationRoot() {
36 | assertEquals(2.0, quadraticEquationRoot(1.0, -3.0, 2.0), 1e-13)
37 | assertEquals(1.0, quadraticEquationRoot(1.0, -2.0, 1.0), 1e-13)
38 | assertEquals(-3.0, quadraticEquationRoot(1.0, 6.0, 9.0), 1e-13)
39 | }
40 |
41 | @Test
42 | @Tag("Example")
43 | fun quadraticRootProduct() {
44 | assertEquals(1.0, quadraticRootProduct(1.0, -2.0, 1.0), 1e-13)
45 | assertEquals(9.0, quadraticRootProduct(1.0, 6.0, 9.0), 1e-13)
46 | assertEquals(2.0, quadraticRootProduct(1.0, 3.0, 2.0), 1e-13)
47 | }
48 |
49 | @Test
50 | @Tag("Trivial")
51 | fun seconds() {
52 | assertEquals(30035, seconds(8, 20, 35))
53 | assertEquals(86400, seconds(24, 0, 0))
54 | assertEquals(13, seconds(0, 0, 13))
55 | }
56 |
57 | @Test
58 | @Tag("Trivial")
59 | fun lengthInMeters() {
60 | assertEquals(18.98, lengthInMeters(8, 2, 11), 1e-2)
61 | assertEquals(2.13, lengthInMeters(1, 0, 0), 1e-2)
62 | }
63 |
64 | @Test
65 | @Tag("Trivial")
66 | fun angleInRadian() {
67 | assertEquals(0.63256, angleInRadian(36, 14, 35), 1e-5)
68 | assertEquals(PI / 2.0, angleInRadian(90, 0, 0), 1e-5)
69 | }
70 |
71 | @Test
72 | @Tag("Trivial")
73 | fun trackLength() {
74 | assertEquals(5.0, trackLength(3.0, 0.0, 0.0, 4.0), 1e-5)
75 | assertEquals(1.0, trackLength(0.0, 1.0, -1.0, 1.0), 1e-5)
76 | assertEquals(1.41, trackLength(1.0, 1.0, 2.0, 2.0), 1e-2)
77 | }
78 |
79 | @Test
80 | @Tag("Easy")
81 | fun thirdDigit() {
82 | assertEquals(8, thirdDigit(3801))
83 | assertEquals(1, thirdDigit(100))
84 | assertEquals(0, thirdDigit(1000))
85 | }
86 |
87 | @Test
88 | @Tag("Easy")
89 | fun travelMinutes() {
90 | assertEquals(216, travelMinutes(9, 25, 13, 1))
91 | assertEquals(1, travelMinutes(21, 59, 22, 0))
92 | }
93 |
94 | @Test
95 | @Tag("Easy")
96 | fun accountInThreeYears() {
97 | assertEquals(133.1, accountInThreeYears(100, 10), 1e-2)
98 | assertEquals(1.0, accountInThreeYears(1, 0), 1e-2)
99 | assertEquals(104.0, accountInThreeYears(13, 100), 1e-2)
100 | }
101 |
102 | @Test
103 | @Tag("Easy")
104 | fun numberRevert() {
105 | assertEquals(874, numberRevert(478))
106 | assertEquals(201, numberRevert(102))
107 | }
108 | }
--------------------------------------------------------------------------------
/test/lesson10/task1/Tests.kt:
--------------------------------------------------------------------------------
1 | package lesson10.task1
2 |
3 | import org.junit.jupiter.api.Tag
4 | import org.junit.jupiter.api.Test
5 | import org.junit.jupiter.api.Assertions.*
6 |
7 | class Tests {
8 | @Test
9 | @Tag("Example")
10 | fun parseExpr() {
11 | assertEquals(mapOf(1 to 7, 2 to 16, -1 to 13), parseExpr("input/expr_in1.txt", listOf(1, 2, -1)))
12 | assertEquals(mapOf(1 to -1, 3 to 9, 4 to 6), parseExpr("input/expr_in2.txt", listOf(1, 3, 4)))
13 | try {
14 | parseExpr("input/expr_in3.txt", listOf(0))
15 | throw AssertionError("NumberFormatException expected")
16 | }
17 | catch (e: NumberFormatException) {}
18 | assertEquals(mapOf(-2 to 12, -1 to 2, 0 to 0, 1 to 0, 2 to -4), parseExpr("input/expr_in4.txt", listOf(-2, -1, 0, 1, 2)))
19 | assertEquals(mapOf(1 to -16, 3 to -54, 4 to -73), parseExpr("input/expr_in5.txt", listOf(1, 3, 4)))
20 | assertEquals(mapOf(0 to 1, 1 to -1, -1 to 1), parseExpr("input/expr_in6.txt", listOf(0, 1, -1)))
21 | }
22 | }
--------------------------------------------------------------------------------
/test/lesson10/task2/Tests.kt:
--------------------------------------------------------------------------------
1 | package lesson10.task2
2 |
3 | import org.junit.jupiter.api.Test
4 |
5 | import org.junit.jupiter.api.Assertions.*
6 | import org.junit.jupiter.api.Tag
7 |
8 | class Tests {
9 | @Test
10 | @Tag("Example")
11 | fun convertToHtmlTable() {
12 | val data = listOf(listOf("1", "2", "3"), listOf("4", "5", "6"))
13 | assertEquals("