diff --git a/homeworks/homework_3/build.sbt b/homeworks/homework_3/build.sbt index bf2ba0d2..8fb65e8b 100644 --- a/homeworks/homework_3/build.sbt +++ b/homeworks/homework_3/build.sbt @@ -1,4 +1,4 @@ -name := "homework_3" +name := "Lecture4" version := "0.1" diff --git a/homeworks/homework_3/homework_3.md b/homeworks/homework_3/homework_3.md index 4ee514c3..141e9f2b 100644 --- a/homeworks/homework_3/homework_3.md +++ b/homeworks/homework_3/homework_3.md @@ -1,46 +1,46 @@ # Домашнее задание №3 (курс Scala, Naumen) -Задания описаны в файле Exercises.scala в sbt проекте, который находится в папке /homeworks/homework_3 -Ниже приводится вспомогательная информация которая поможет вам справится с заданием. -Как всегда - необходимо написать тесты к своим решениям (минимум 3 теста к каждой реализованной функции решения). - -## 1. Определение типа в рантайме - -Для определения простого, не параметризованного типа в рантайме в Scala есть несколько способов: - - использовать x.isInstanceOf[SomeClass] - - паттерн матчинг (https://docs.scala-lang.org/ru/tour/pattern-matching.html) - - использовать x.getClass - - рефлексия - - и другие - - Для приведения типов (type cast) есть 2 способа: - - x.asInstanceof[SomeClass] - - паттерн матчинг - -## 2. Отсутствие правильного значения - -В программировании довольно часто может отсутствовать значение вычисления функции. Напирмер в функции деления, значение деления на 0 не определено. - -Отсутствие верного значения, возвращаемого из какого либо метода или функции, или невозможность верно вычислить результат можно кодировать и обрабатывать в программе разными способами. - -Иногда, для этого используются целочисленные коды ошибки - это распространено в языке Си и системном программировании. - -Иногда для этого используется null, а иногда для этого используется выбрасывание исключения (exception). -Это распространено в современных ООП языках (Java, C#, python, JavaScript). - -В функциональных языках и в Scala в частности - любят кодировать отсуствие значений с помощью специальных контейнерных типов. -Самый простой из них - тип список, или другие коллекции похожие на список (seq, set, array, stream, и др.). Если у нас есть корректные значения которые возвращает функция - мы возвращаем список этих значений. Особенно это удобно, когда верных значений может быть несколько - например в задаче нахождения всех делителей числа. Пустой список - означает отсутсвие таких значений. - -Также есть тип Option. В нем явно кодируется отсутствие значение с помощью объекта None, а наличие значение в виде контейнера Some(x). -Для краткого ознакомления для работы с Option подойдет данная статья - https://www.tutorialspoint.com/scala/scala_options.htm . -Для более глубокого - https://danielwestheide.com/blog/the-neophytes-guide-to-scala-part-5-the-option-type/ . - -## 3. Параметры типов и отношение подтипов - -Для решения задания №3 достаточно обратиться к материалам лекции. - - - - - +Необходимо реализовать класс простой электронной таблицы (класс Table). +

+ Таблица имеет фиксированную ширину и длину (параметры конструктора Table). +
+
Таблица должна быть представлена следующими типами ячеек (базовый интерфейс Cell): +
-Пустая ячейка (класс EmptyCell), +
-Ячейка с 32-битным целым числом (класс NumberCell), +
-Ячейка с текстом (класс StringCell), +
-Ячейка, содержащая ссылку на другую ячейку (класс ReferenceCell). +
+
По умолчанию, все ячейки таблицы являются пустыми (класс "EmptyCell") +
+
Таблица (класс Table) должна предоставлять следующие общедоступные методы: +
-getCell(ix: Int, iy: Int): Option\[Cell\] (возвращает ячейку по индексам строки и столбца, +
либо "None", если ix или iy вне границ таблицы), +
-setCell(ix: Int, iy: Int, cell: Cell): Unit (устанавливает ячейку cell в указанные столбец и строку), +
здесь ix - индекс колонки (ix>=0), iy - индекс строки (iy>=0), +
cell - ячейка таблицы, представленная конкретной реализацией (EmptyCell/NumberCell/StringCell/ReferenceCell). +
+
Таблица хранит коллекцию ячеек. Так как определён метод "setCell", можно использовать мутабельную коллекцию +
(package scala.collection.mutable). +
+
Каждая ячейка должна предоставлять основной конструктор, посредством которого инициализируется значение ячейки. +
Например, class NumberCell(number: Int) extends Cell . +
В случае "EmptyCell" какого-либо конструктора не требуется. +
В случае "ReferenceCell": class ReferenceCell(ix: Int, iy: Int, table: Table) extends Cell, где ix и iy - +
индексы столбца и строки ячейки (на которую ведёт ссылка) таблицы table (которой принадлежит ячейка, на которую ведёт ссылка). +
+
Каждая ячейка (реализация интерфейса Cell) должна предоставлять общедоступный метод toString(): String, +
который возвращает хранящееся в ней значение в виде строки (типа String). +
В случае "EmptyCell" метод "toString" должен возвращать значение "empty" +
В случае "ReferenceCell" метод "toString" должен возвращать значение той ячейки, на которую определена ссылка. +
В случае, если "ReferenceCell" ячейка ссылается на индекс ячейки, находящийся за границами таблицы, метод "toString" +
должен возвращать значение "outOfRange" +
В случае "циклических" ссылок (если, например, "ReferenceCell" ячейка ссылается на другую "ReferenceCell" ячейку, +
которая вновь ссылается на первую), метод "toString" должен возвращать значение "cyclic". +
+
При реализации можно учесть, что двумерный список можно однозначно выразить одномерным: +
i = ix + iy * w, +
где i - индекс одномерного списка, ix - индекс колонки двумерного списка, iy - индекс строки двумерного списка, +
w - ширина (количество колонок) двумерного списка. +
+
Необходимо, чтобы реализация успешно проходила юнит-тесты (src/test/scala/Test.scala) \ No newline at end of file diff --git a/homeworks/homework_4/src/main/scala/Cell.scala b/homeworks/homework_3/src/main/scala/Cell.scala similarity index 100% rename from homeworks/homework_4/src/main/scala/Cell.scala rename to homeworks/homework_3/src/main/scala/Cell.scala diff --git a/homeworks/homework_4/src/main/scala/Table.scala b/homeworks/homework_3/src/main/scala/Table.scala similarity index 100% rename from homeworks/homework_4/src/main/scala/Table.scala rename to homeworks/homework_3/src/main/scala/Table.scala diff --git a/homeworks/homework_3/src/main/scala/homework_3/Exercises.scala b/homeworks/homework_3/src/main/scala/homework_3/Exercises.scala deleted file mode 100644 index c28fecb5..00000000 --- a/homeworks/homework_3/src/main/scala/homework_3/Exercises.scala +++ /dev/null @@ -1,49 +0,0 @@ -package homework_3 - -object Exercises { - - - /** - * Задание №1 - * Реализуйте функцию, которая принимает любой тип и преобразует его в строку. - * Для всех типов кроме Boolean достаточно воспользоваться стандартной функцией .toString. - * Для типа Boolean сделайте особое преобразование: true -> "правда", false -> "ложь". - * - * Реализуйте функцию тремя разными способами, отличающимися тем, как определяется какой тип имеет значение переданное в аргументе. - * Определение типа необходимо для реализации специальной логики работы с Boolean значениями, которая описана в условии выше. - */ - def prettyBooleanFormatter1(x: Any): String = ??? - - def prettyBooleanFormatter2(x: Any): String = ??? - - def prettyBooleanFormatter3(x: Any): String = ??? - - - /** - * Задание №2 - * Реализуйте функцию нахождения максимального числа в переданной коллекции интов (можно использовать все методы стандартной библиотеки). - * - * Реализуйте функцию тремя разными способами, отличающимися тем как функция себя ведет на пустой коллекции. - * Обратите внимание на возвращаемые типы. - */ - def max1(xs: Seq[Int]): Int = ??? - - def max2(xs: Seq[Int]): Seq[Int] = ??? - - def max3(xs: Seq[Int]): Option[Int] = ??? - - /** - * Задание №3 - * Допустим дана функция sumIntegers, которая умеет суммировать числа. - */ - def sumIntegers[CollectionType <: Iterable[Int]](xs: CollectionType): Int = xs.sum - - /** - * Реализуйте на основе нее 3 варианта суммирования 2х чисел, отличающиеся способом передачи этих 2х чисел в функцию sumIntegers. - * Как минимум одна из реализаций должна использовать тип данных (класс) написанный вами самостоятельно. - */ - def sum1(x: Int, y: Int): Int = sumIntegers(???) - def sum2(x: Int, y: Int): Int = sumIntegers(???) - def sum3(x: Int, y: Int): Int = sumIntegers(???) - -} diff --git a/homeworks/homework_3/src/test/scala/Test.scala b/homeworks/homework_3/src/test/scala/Test.scala new file mode 100644 index 00000000..13357759 --- /dev/null +++ b/homeworks/homework_3/src/test/scala/Test.scala @@ -0,0 +1,77 @@ +import utest._ + +object Test extends TestSuite { + val tests = Tests { + 'test_createTable - { + val table = new Table(3, 3) + for (i <- 0 until 9) { + assert(table.getCell(i / 3, i % 3).map(_.toString) == Some("empty")) + } + assert(table.getCell(0, -1).map(_.toString) == None) + assert(table.getCell(-1, 0).map(_.toString) == None) + assert(table.getCell(9, 8).map(_.toString) == None) + assert(table.getCell(8, 9).map(_.toString) == None) + } + 'test_numberCell - { + val table = new Table(2, 2) + val cellInt00 = new NumberCell(5) + val cellInt11 = new NumberCell(2147483647) + table.setCell(0, 0, cellInt00) + table.setCell(1, 1, cellInt11) + assert(table.getCell(0, 0).map(_.toString) == Some("5")) + assert(table.getCell(0, 1).map(_.toString) == Some("empty")) + assert(table.getCell(1, 0).map(_.toString) == Some("empty")) + assert(table.getCell(1, 1).map(_.toString) == Some("2147483647")) + } + 'test_stringCell - { + val table = new Table(2, 2) + val cellStr01 = new StringCell("01") + val cellStr10 = new StringCell("10") + table.setCell(0, 1, cellStr01) + table.setCell(1, 0, cellStr10) + assert(table.getCell(0, 0).map(_.toString) == Some("empty")) + assert(table.getCell(0, 1).map(_.toString) == Some("01")) + assert(table.getCell(1, 0).map(_.toString) == Some("10")) + assert(table.getCell(1, 1).map(_.toString) == Some("empty")) + } + 'test_referenceCell - { + val table = new Table(3, 3) + /*ix = 0*/ + val cellStr00 = new StringCell("00") + val cellRef01 = new ReferenceCell(0, 2, table) + val cellRef02 = new ReferenceCell(0, 1, table) + /*ix = 1*/ + val cellInt10 = new NumberCell(10) + val cellInt11 = new NumberCell(11) + val cellRef12 = new ReferenceCell(0, 0, table) + /*ix = 2*/ + val cellEmpty20 = new EmptyCell + val cellRef21 = new ReferenceCell(1, 1, table) + val cellRef22 = new ReferenceCell(2, 1, table) + table.setCell(0, 0, cellStr00) + table.setCell(0, 1, cellRef01) + table.setCell(0, 2, cellRef02) + table.setCell(1, 0, cellInt10) + table.setCell(1, 1, cellInt11) + table.setCell(1, 2, cellRef12) + table.setCell(2, 0, cellEmpty20) + table.setCell(2, 1, cellRef21) + table.setCell(2, 2, cellRef22) + for (i <- 0 until 9) { + val value = table.getCell(i / 3, i % 3).get.toString + i match { + case 0 => assert(value == "00") + case 1 => assert(value == "cyclic") + case 2 => assert(value == "cyclic") + case 3 => assert(value == "10") + case 4 => assert(value == "11") + case 5 => assert(value == "00") + case 6 => assert(value == "empty") + case 7 => assert(value == "11") + case 8 => assert(value == "11") + case _ => assert(false) + } + } + } + } +} diff --git a/homeworks/homework_3/src/test/scala/homework_3/Test.scala b/homeworks/homework_3/src/test/scala/homework_3/Test.scala deleted file mode 100644 index df188f89..00000000 --- a/homeworks/homework_3/src/test/scala/homework_3/Test.scala +++ /dev/null @@ -1,13 +0,0 @@ -package homework_3 - -import utest._ - -object Test extends TestSuite{ - - val tests = Tests{ - 'test_example - { - val trueStr = "правда" - assert(Exercises.prettyBooleanFormatter1(true) == trueStr) - } - } -} diff --git a/homeworks/homework_4/.gitignore b/homeworks/homework_4/.gitignore index 56b16317..5d8063fd 100644 --- a/homeworks/homework_4/.gitignore +++ b/homeworks/homework_4/.gitignore @@ -1,3 +1,6 @@ -/.idea -/target -project/target \ No newline at end of file +# Project exclude paths +/project/project/target/ +/project/target/ +/target/ +/target/scala-2.12/classes/ +/target/scala-2.12/test-classes/ \ No newline at end of file diff --git a/homeworks/homework_4/build.sbt b/homeworks/homework_4/build.sbt index 8fb65e8b..6f8b73c5 100644 --- a/homeworks/homework_4/build.sbt +++ b/homeworks/homework_4/build.sbt @@ -1,9 +1,12 @@ -name := "Lecture4" +ThisBuild / version := "0.1.0-SNAPSHOT" -version := "0.1" - -scalaVersion := "2.12.10" +ThisBuild / scalaVersion := "2.12.10" libraryDependencies += "com.lihaoyi" %% "utest" % "0.5.3" % "test" -testFrameworks += new TestFramework("utest.runner.Framework") \ No newline at end of file +testFrameworks += new TestFramework("utest.runner.Framework") + +lazy val root = (project in file(".")) + .settings( + name := "homework-1" + ) diff --git a/homeworks/homework_4/homework_4.md b/homeworks/homework_4/homework_4.md index c496401e..930a47ff 100644 --- a/homeworks/homework_4/homework_4.md +++ b/homeworks/homework_4/homework_4.md @@ -1,46 +1,5 @@ # Домашнее задание №4 (курс Scala, Naumen) +Необходимо выполнить задания, описанные в (src/main/scala/Exercises.scala) +Решение должно успешно проходить тесты в (src/test/scala/Test.scala) -Необходимо реализовать класс простой электронной таблицы (класс Table). -

- Таблица имеет фиксированную ширину и длину (параметры конструктора Table). -
-
Таблица должна быть представлена следующими типами ячеек (базовый интерфейс Cell): -
-Пустая ячейка (класс EmptyCell), -
-Ячейка с 32-битным целым числом (класс NumberCell), -
-Ячейка с текстом (класс StringCell), -
-Ячейка, содержащая ссылку на другую ячейку (класс ReferenceCell). -
-
По умолчанию, все ячейки таблицы являются пустыми (класс "EmptyCell") -
-
Таблица (класс Table) должна предоставлять следующие общедоступные методы: -
-getCell(ix: Int, iy: Int): Option\[Cell\] (возвращает ячейку по индексам строки и столбца, -
либо "None", если ix или iy вне границ таблицы), -
-setCell(ix: Int, iy: Int, cell: Cell): Unit (устанавливает ячейку cell в указанные столбец и строку), -
здесь ix - индекс колонки (ix>=0), iy - индекс строки (iy>=0), -
cell - ячейка таблицы, представленная конкретной реализацией (EmptyCell/NumberCell/StringCell/ReferenceCell). -
-
Таблица хранит коллекцию ячеек. Так как определён метод "setCell", можно использовать мутабельную коллекцию -
(package scala.collection.mutable). -
-
Каждая ячейка должна предоставлять основной конструктор, посредством которого инициализируется значение ячейки. -
Например, class NumberCell(number: Int) extends Cell . -
В случае "EmptyCell" какого-либо конструктора не требуется. -
В случае "ReferenceCell": class ReferenceCell(ix: Int, iy: Int, table: Table) extends Cell, где ix и iy - -
индексы столбца и строки ячейки (на которую ведёт ссылка) таблицы table (которой принадлежит ячейка, на которую ведёт ссылка). -
-
Каждая ячейка (реализация интерфейса Cell) должна предоставлять общедоступный метод toString(): String, -
который возвращает хранящееся в ней значение в виде строки (типа String). -
В случае "EmptyCell" метод "toString" должен возвращать значение "empty" -
В случае "ReferenceCell" метод "toString" должен возвращать значение той ячейки, на которую определена ссылка. -
В случае, если "ReferenceCell" ячейка ссылается на индекс ячейки, находящийся за границами таблицы, метод "toString" -
должен возвращать значение "outOfRange" -
В случае "циклических" ссылок (если, например, "ReferenceCell" ячейка ссылается на другую "ReferenceCell" ячейку, -
которая вновь ссылается на первую), метод "toString" должен возвращать значение "cyclic". -
-
При реализации можно учесть, что двумерный список можно однозначно выразить одномерным: -
i = ix + iy * w, -
где i - индекс одномерного списка, ix - индекс колонки двумерного списка, iy - индекс строки двумерного списка, -
w - ширина (количество колонок) двумерного списка. -
-
Необходимо, чтобы реализация успешно проходила юнит-тесты (src/test/scala/Test.scala) \ No newline at end of file diff --git a/homeworks/homework_4/project/build.properties b/homeworks/homework_4/project/build.properties index 010613d5..303541e5 100644 --- a/homeworks/homework_4/project/build.properties +++ b/homeworks/homework_4/project/build.properties @@ -1 +1 @@ -sbt.version = 1.3.3 \ No newline at end of file +sbt.version = 1.9.6 diff --git a/homeworks/homework_4/src/main/scala/Exercises.scala b/homeworks/homework_4/src/main/scala/Exercises.scala new file mode 100644 index 00000000..31ebaddb --- /dev/null +++ b/homeworks/homework_4/src/main/scala/Exercises.scala @@ -0,0 +1,124 @@ + +object Exercises { + + /** + * Задание №1 + * Дана императивная функция findSumImperative. + * Напишите ее аналог (findSumFunctional) в функциональном стиле. + * + * ПОДСКАЗКА + * Стоит воспользоваться методами, которые предоставляет объект List или рекурсией. + * Страница с полезностями List: https://alvinalexander.com/scala/list-class-methods-examples-syntax/ + */ + def findSumImperative(items: List[Int], sumValue: Int): (Int, Int) = { + var result: (Int, Int) = (-1, -1) + for (i <- 0 until items.length) { + for (j <- 0 until items.length) { + if (items(i) + items(j) == sumValue && i != j) { + result = (i, j) + } + } + } + result + } + + def findSumFunctional(items: List[Int], sumValue: Int) = { + (-1, -1) + } + + + /** + * Задание №2 + * + * Дана рекурсивная функция simpleRecursion. + * Перепишите ее так, чтобы получилась хвостовая рекурсивная функция. + * + * Для прохождения теста на большое количество элементов в списке + * используйте анотацию @tailrec к вашей функции. + */ + def simpleRecursion(items: List[Int], index: Int = 1): Int = { + items match { + case head :: tail => + if (head % 2 == 0) { + head * simpleRecursion(tail, index + 1) + index + } else { + -1 * head * simpleRecursion(tail, index + 1) + index + } + case _ => 1 + } + } + + def tailRecRecursion(items: List[Int]): Int = { + 1 + } + + /** + * Задание №3 + * Реализуйте алгоритм бинарного поиска, который соответсвует всем правилам функционального программирования. + * Необходимо возвращать индекс соответствующего элемента в массиве + * Если ответ найден, то возвращается Some(index), если нет, то None + */ + + def functionalBinarySearch(items: List[Int], value: Int): Option[Int] = { + None + } + + /** + * Задание №4 + * Реализуйте функцию, которая генерирует список заданной длинны c именами. + * Функция должна соответствовать всем правилам функционального программирования. + * + * Именем является строка, не содержащая иных символов, кроме буквенных, а также начинающаяся с заглавной буквы. + */ + + def generateNames(namesСount: Int): List[String] = { + if (namesСount < 0) throw new Throwable("Invalid namesCount") + Nil + } + +} + +/** + * Задание №5 + * + * Дана реализация сервиса по смене номера SimpleChangePhoneService с методом changePhone + * Необходимо написать реализацию этого сервиса с учетом правил работы со сторонними эффектами (SideEffects). + * + * Для этого необходимо сначала реализовать собственный сервис работы с телефонными номерами (PhoneServiceSafety), + * используя при этом методы из unsafePhoneService. + * Методы должны быть безопасными, поэтому тип возвращаемых значений необходимо определить самостоятельно. + * Рекомендуется воспользоваться стандартными типами Scala (например Option или Either). + * + * Затем, с использованием нового сервиса, необходимо реализовать "безопасную" версию функции changePhone. + * Функция должна возвращать ok в случае успешного завершения или текст ошибки. + * + * Изменять методы внутри SimplePhoneService не разрешается. + */ + +object SideEffectExercise { + import Utils._ + + class SimpleChangePhoneService(phoneService: SimplePhoneService) extends ChangePhoneService { + override def changePhone(oldPhone: String, newPhone: String): String = { + val oldPhoneRecord = phoneService.findPhoneNumber(oldPhone) + if (oldPhoneRecord != null) { + phoneService.deletePhone(oldPhoneRecord) + } + phoneService.addPhoneToBase(newPhone) + "ok" + } + } + + + class PhoneServiceSafety(unsafePhoneService: SimplePhoneService) { + def findPhoneNumberSafe(num: String) = ??? + + def addPhoneToBaseSafe(phone: String) = ??? + + def deletePhone(phone: String) = ??? + } + + class ChangePhoneServiceSafe(phoneServiceSafety: PhoneServiceSafety) extends ChangePhoneService { + override def changePhone(oldPhone: String, newPhone: String): String = ??? + } +} diff --git a/homeworks/homework_4/src/main/scala/Utils.scala b/homeworks/homework_4/src/main/scala/Utils.scala new file mode 100644 index 00000000..0820ad4d --- /dev/null +++ b/homeworks/homework_4/src/main/scala/Utils.scala @@ -0,0 +1,36 @@ +import scala.collection.mutable + +object Utils { + class PhoneBase(private val phones: mutable.ListBuffer[String]) { + def insert(phone: String): Unit = phones += phone + def list(): List[String] = phones.toList + def delete(phone: String): Unit = phones.filter(_ != phone) + + } + + def checkPhoneNumber(num: String): Boolean = num.matches("^[\\+]?[(]?[0-9]{3}[)]?[-\\s\\.]?[0-9]{3}[-\\s\\.]?[0-9]{4,6}$") + + class SimplePhoneService(phonesBase: PhoneBase) { + + def findPhoneNumber(num: String): String = { + val resulNums = phonesBase.list().filter(_ == num) + if (resulNums.isEmpty) + null + else + resulNums.head + } + + def addPhoneToBase(phone: String): Unit = { + if (checkPhoneNumber(phone)) + phonesBase.insert(phone) + else + throw new InternalError("Invalid phone string") + } + + def deletePhone(phone: String): Unit = phonesBase.delete(phone) + } + + trait ChangePhoneService { + def changePhone(oldPhone: String, newPhone: String): String + } +} diff --git a/homeworks/homework_4/src/test/scala/Test.scala b/homeworks/homework_4/src/test/scala/Test.scala index 13357759..d80a537b 100644 --- a/homeworks/homework_4/src/test/scala/Test.scala +++ b/homeworks/homework_4/src/test/scala/Test.scala @@ -1,76 +1,63 @@ import utest._ +import scala.util.Random + object Test extends TestSuite { - val tests = Tests { - 'test_createTable - { - val table = new Table(3, 3) - for (i <- 0 until 9) { - assert(table.getCell(i / 3, i % 3).map(_.toString) == Some("empty")) - } - assert(table.getCell(0, -1).map(_.toString) == None) - assert(table.getCell(-1, 0).map(_.toString) == None) - assert(table.getCell(9, 8).map(_.toString) == None) - assert(table.getCell(8, 9).map(_.toString) == None) + lazy val randomLength = Random + def generateRandomList(maxListSize: Int) = { + val listLength = Random.nextInt(maxListSize) + List.fill(listLength)(Random.nextInt) + } + override def tests: Tests = Tests { + 'firstTask - (1 to 5).foreach { _ => + val testList = generateRandomList(50) + val sumValue = testList(Random.nextInt(testList.size)) + testList(Random.nextInt(testList.size)) + assert(Exercises.findSumImperative(testList, sumValue) == Exercises.findSumFunctional(testList, sumValue)) } - 'test_numberCell - { - val table = new Table(2, 2) - val cellInt00 = new NumberCell(5) - val cellInt11 = new NumberCell(2147483647) - table.setCell(0, 0, cellInt00) - table.setCell(1, 1, cellInt11) - assert(table.getCell(0, 0).map(_.toString) == Some("5")) - assert(table.getCell(0, 1).map(_.toString) == Some("empty")) - assert(table.getCell(1, 0).map(_.toString) == Some("empty")) - assert(table.getCell(1, 1).map(_.toString) == Some("2147483647")) + + 'recursionTask - { + 'itWorks - { + (1 to 5).foreach { _ => + val testList = generateRandomList(50) + assert(Exercises.simpleRecursion(testList) == Exercises.tailRecRecursion(testList)) + } + } + 'longList - { + val testList = List.fill(10000)(Random.nextInt) + Exercises.tailRecRecursion(testList) + } } - 'test_stringCell - { - val table = new Table(2, 2) - val cellStr01 = new StringCell("01") - val cellStr10 = new StringCell("10") - table.setCell(0, 1, cellStr01) - table.setCell(1, 0, cellStr10) - assert(table.getCell(0, 0).map(_.toString) == Some("empty")) - assert(table.getCell(0, 1).map(_.toString) == Some("01")) - assert(table.getCell(1, 0).map(_.toString) == Some("10")) - assert(table.getCell(1, 1).map(_.toString) == Some("empty")) + + 'binarySearch - { + 'simpleSearch - (1 to 5).foreach { _ => + val testList = generateRandomList(50).distinct.sorted + val result = Random.nextInt(testList.size) + assert(Exercises.functionalBinarySearch(testList, testList(result)).contains(result)) + } + + 'empty - { + assert(Exercises.functionalBinarySearch(Nil, 24).isEmpty) + } + + 'noElement - { + val testList = List.fill(50)(Random.nextInt(50)) + assert(Exercises.functionalBinarySearch(testList, -1).isEmpty) + } } - 'test_referenceCell - { - val table = new Table(3, 3) - /*ix = 0*/ - val cellStr00 = new StringCell("00") - val cellRef01 = new ReferenceCell(0, 2, table) - val cellRef02 = new ReferenceCell(0, 1, table) - /*ix = 1*/ - val cellInt10 = new NumberCell(10) - val cellInt11 = new NumberCell(11) - val cellRef12 = new ReferenceCell(0, 0, table) - /*ix = 2*/ - val cellEmpty20 = new EmptyCell - val cellRef21 = new ReferenceCell(1, 1, table) - val cellRef22 = new ReferenceCell(2, 1, table) - table.setCell(0, 0, cellStr00) - table.setCell(0, 1, cellRef01) - table.setCell(0, 2, cellRef02) - table.setCell(1, 0, cellInt10) - table.setCell(1, 1, cellInt11) - table.setCell(1, 2, cellRef12) - table.setCell(2, 0, cellEmpty20) - table.setCell(2, 1, cellRef21) - table.setCell(2, 2, cellRef22) - for (i <- 0 until 9) { - val value = table.getCell(i / 3, i % 3).get.toString - i match { - case 0 => assert(value == "00") - case 1 => assert(value == "cyclic") - case 2 => assert(value == "cyclic") - case 3 => assert(value == "10") - case 4 => assert(value == "11") - case 5 => assert(value == "00") - case 6 => assert(value == "empty") - case 7 => assert(value == "11") - case 8 => assert(value == "11") - case _ => assert(false) - } + + 'namesList - { + 'nonEmpty - (1 to 5).foreach { _ => + val namesCount = Random.nextInt(50) + val names = Exercises.generateNames(namesCount) + assert( + names.forall(_.matches("([A-Z]|[А-Я])([a-z]|[а-я])*")) && + names.size == namesCount && + names.distinct.size == namesCount + ) + } + + 'empty - { + assert(Exercises.generateNames(0).isEmpty) } } } diff --git a/homeworks/homework_5/build.sbt b/homeworks/homework_5/build.sbt deleted file mode 100644 index a5844cf4..00000000 --- a/homeworks/homework_5/build.sbt +++ /dev/null @@ -1,9 +0,0 @@ -name := "homework_5" - -version := "0.1" - -scalaVersion := "2.12.10" - -libraryDependencies += "com.lihaoyi" %% "utest" % "0.5.3" % "test" - -testFrameworks += new TestFramework("utest.runner.Framework") diff --git a/homeworks/homework_5/homework_5.md b/homeworks/homework_5/homework_5.md deleted file mode 100644 index f32b2d7d..00000000 --- a/homeworks/homework_5/homework_5.md +++ /dev/null @@ -1,39 +0,0 @@ -# Домашнее задание №5 (курс Scala, Naumen) - -## Задание 1 - -Реализуйте класс приюта для животных (`case class Shelter...`), который хранит список (`List`) -животных, которые в нем содержатся. Приют должен быть параметризован типом содержащихся животных. -Например, `Shelter[Cat]` может содержать только котов, а `Shelter[Animal]` любых животных.
-Реализуйте метод `+`, который добавляет в приют животное (метод должен вернуть новый приют, а не модифицировать старый). -Тип полученного приюта должен остаться настолько точным, насколько это возможным. -Например, если в приют с котами добавляют кота, то в результате должен снова получиться приют с котами.
-`val s: Shelter[Cat] = Shelter(List(Cat("Garfield"))) + Cat("Kuzya")`
-Если же в приют с котами добавить собаку, то получится приют с животными.
-`val s: Shelter[Animal] = Shelter(List(Cat("Garfield"))) + Dog("Goofy")`
-Реализовать метод `++`, который производит сложение двух приютов и возвращает приют, -в котором содержатся животные из обоих, участвовавших в сложении. -Тип результата точно так же должен быть настолько точным, насколько это возможно, исходя из -типов приютов, участвовавших в сложении.
-Реализовать метод `getNames`, который возвращает спсок имен животных, содержащихся в приюте.
-Тесты должны компилироваться и успешно проходить. Обратите внимание, что до вполнения второго -задания соответствующая часть тестов не будет компилироваться, так что ее можно закомментировать. - -## Задание 2 - -Реализовать тип еда (`trait Food`), который параметризован типом животных, которые -ее могут есть. Например, `Food[Cat]` могут есть только коты, а -`Food[Animal]` могут есть любые животные. Реализовать объекты (`case object`):
-`Meat` - мясо, могут есть все животные.
-`Milk` - молоко, могут есть коты.
-`Bread` - хлеб, могут есть собаки.
-Определить для еды метод `feed`, который принимает животное того типа, которым параметризована эта еда, -и возвращает строку, содержащую "<имя животного> eats <название еды со строчной буквы>". Например, -`Meat.feed(Cat("Garfield"))` должно вернуть "Garfield eats meat", а `Milk.feed(Dog("Goofy"))` не должно -компилироваться т.к. собаки не едят молоко. -Реализовать для приюта метод, который получает на вход еду, которая подходит для -содержащихся в нем животных, и выводит список результатов применеия метода `Food.feed` ко -всем животным. Обратите внамение, что `Shelter(List(Cat("Garfield"), Dog("Goofy"))).feed(Milk)` не должно -компилироваться т.к. в этом приюте содержатся и кошки и собаки, -следовательно тип этого приюта - `Shelter[Animal]`, а произвольные животные не могут есть молоко. Единственная -еда, которой их можно было бы покормить - мясо. diff --git a/homeworks/homework_5/project/build.properties b/homeworks/homework_5/project/build.properties deleted file mode 100644 index 010613d5..00000000 --- a/homeworks/homework_5/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.3.3 \ No newline at end of file diff --git a/homeworks/homework_5/src/main/scala/Exercises.scala b/homeworks/homework_5/src/main/scala/Exercises.scala deleted file mode 100644 index 2be7d30e..00000000 --- a/homeworks/homework_5/src/main/scala/Exercises.scala +++ /dev/null @@ -1,23 +0,0 @@ -object Exercises { - trait Animal { - def name: String - } - - case class Cat(override val name: String) extends Animal - - case class Dog(override val name: String) extends Animal - - - - case class Shelter ... - - - - trait Food ... - - case object Meat extends Food[Animal] ... - - case object Milk extends Food[Cat] ... - - case object Bread extends Food[Dog] ... -} diff --git a/homeworks/homework_5/src/test/scala/Test.scala b/homeworks/homework_5/src/test/scala/Test.scala deleted file mode 100644 index f8e61f8f..00000000 --- a/homeworks/homework_5/src/test/scala/Test.scala +++ /dev/null @@ -1,58 +0,0 @@ -import Exercises._ -import utest._ - -object Test extends TestSuite { - - val tests = Tests { - - //Test task 1 - - val s1: Shelter[Cat] = Shelter(List(Cat("Garfield"))) - - val s2: Shelter[Dog] = Shelter(List(Dog("Goofy"))) - - val s3: Shelter[Animal] = s1 ++ s2 - - val s4 = s3 + Cat("Kuzya") - - assert(s4.getNames.toSet == Set("Garfield", "Goofy", "Kuzya")) - - val s5: Shelter[Animal] = s1 + Dog("Barbos") - - assert(s5.getNames.toSet == Set("Garfield", "Barbos")) - - val s6: Shelter[Dog] = s2 + Dog("Barbos") - - assert(s6.getNames.toSet == Set("Goofy", "Barbos")) - - //Test task 2 - - val r1 = s1.feed(Meat) - - assert(r1.toSet == Set("Garfield eats meat")) - - val r2 = s1.feed(Milk) - - assert(r2.toSet == Set("Garfield eats milk")) - - val r3 = s2.feed(Meat) - - assert(r3.toSet == Set("Goofy eats meat")) - - val r4 = s2.feed(Bread) - - assert(r4.toSet == Set("Goofy eats bread")) - - val r5 = s4.feed(Meat) - - assert( - r5.toSet == Set( - "Garfield eats meat", - "Goofy eats meat", - "Kuzya eats meat" - ) - ) - - } - -} diff --git a/homeworks/homework_6/.gitignore b/homeworks/homework_6/.gitignore deleted file mode 100644 index 56b16317..00000000 --- a/homeworks/homework_6/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/.idea -/target -project/target \ No newline at end of file diff --git a/homeworks/homework_6/build.sbt b/homeworks/homework_6/build.sbt deleted file mode 100644 index 6f288598..00000000 --- a/homeworks/homework_6/build.sbt +++ /dev/null @@ -1,9 +0,0 @@ -name := "homework_6" - -version := "0.1" - -scalaVersion := "2.12.10" - -libraryDependencies += "com.lihaoyi" %% "utest" % "0.5.3" % "test" - -testFrameworks += new TestFramework("utest.runner.Framework") diff --git a/homeworks/homework_6/homework_6.md b/homeworks/homework_6/homework_6.md deleted file mode 100644 index bc75b952..00000000 --- a/homeworks/homework_6/homework_6.md +++ /dev/null @@ -1,25 +0,0 @@ -# Домашнее задание №6 (курс Scala, Naumen) - -## Задание 1. *reverse* -Реализовать метод реверсии списка. - - -## Задание 2. *fibonacci4Index* -Вычисление значения чисел Фибоначчи. Выводить значение в зависимости от индекса. Индекс - это неотрицательное целое число. -[wiki. Числа Фибоначчи](https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8) - - -## Задание 2. *fibonacci4Index* -То же что и `Задание 2` (только выдаём последовательность). - - -## Задание 3. *morse* -Закодировать текст при помощи Морзе. Приведена таблица `Exercises.MORSE` для латинских букв. На выходе *коды* разделяются пробелами. Если встречается "нелатинская" буква, то выводить этот символ как он был передан. К примеру, в связи с этим условием пробел " " превращается в три пробела " ". - - -## Задание 4. *wordReverse* -На вход передаётся обычный текст. Необходимо развернуть каждое слово (слово - это набор букв, именно букв). Если слово начиналось с заглавной буквы, то развёрнутое должно начинаться с большой буквы. - - ---- -Попробуйте решить задачи, используя `mutable` и `immutable` коллекции. Хотя для большинства задач достаточно использовать `immutable`. diff --git a/homeworks/homework_6/project/build.properties b/homeworks/homework_6/project/build.properties deleted file mode 100644 index 010613d5..00000000 --- a/homeworks/homework_6/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.3.3 \ No newline at end of file diff --git a/homeworks/homework_6/src/main/scala/Exercises.scala b/homeworks/homework_6/src/main/scala/Exercises.scala deleted file mode 100644 index 2e325cbd..00000000 --- a/homeworks/homework_6/src/main/scala/Exercises.scala +++ /dev/null @@ -1,27 +0,0 @@ -object Exercises { - - - def reverse[T](seq: Seq[T]): Seq[T] = ??? - - /** - * https://ru.wikipedia.org/wiki/Числа_Фибоначчи - * - * @param idx - * @return - */ - def fibonacci4Index(idx: Int): Int = ??? - - def fibonacci(idx: Int): Seq[Int] = ??? - - lazy val MORSE = Map("A" -> ".-", "B" -> "-...", "C" -> "-.-.", "D" -> "-..", "E" -> ".", "F" -> "..-.", - "G" -> "--.", "H" -> "....", "I" -> "..", "J" -> ".---", "K" -> "-.-", "L" -> ".-..", - "M" -> "--", "N" -> "-.", "O" -> "---", "P" -> ".--.", "Q" -> "--.-", "R" -> ".-.", - "S" -> "...", "T" -> "-", "U" -> "..-", "V" -> "...-", "W" -> ".--", "X" -> "-..-", - "Y" -> "-.--", "Z" -> "--..") - - def morse(text: String): String = ??? - - - def wordReverse(text: String): String = ??? - -} diff --git a/homeworks/homework_6/src/test/scala/Test.scala b/homeworks/homework_6/src/test/scala/Test.scala deleted file mode 100644 index 62d9396e..00000000 --- a/homeworks/homework_6/src/test/scala/Test.scala +++ /dev/null @@ -1,33 +0,0 @@ -import utest._ - - -object Test extends TestSuite{ - - val tests = Tests{ - 'reverse - { - assert(Exercises.reverse(Seq(1, 2, 3)) == Seq(3, 2, 1)) - assert(Exercises.reverse(Seq(-1, -2, -3)) == Seq(-3, -2, -1)) - } - - 'fibonacci4Index - { - assert(Exercises.fibonacci4Index(2) == 1) - assert(Exercises.fibonacci4Index(5) == 5) - } - - 'fibonacci - { - assert(Exercises.fibonacci(2) == Seq(0, 1, 1)) - assert(Exercises.fibonacci(5) == Seq(0, 1, 1, 2, 3, 5)) - } - - 'morse - { - assert(Exercises.morse("SOS") == "... --- ...") - assert(Exercises.morse("Hello world!") == ".... . .-.. .-.. --- .-- --- .-. .-.. -..!") - } - - 'wordReverse - { - assert(Exercises.wordReverse("Зима!.. Крестьянин, торжествуя...") == "Амиз!.. Ниняьтсерк, яувтсежрот...") - } - - - } -} diff --git a/homeworks/homework_7/.gitignore b/homeworks/homework_7/.gitignore deleted file mode 100644 index 56b16317..00000000 --- a/homeworks/homework_7/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/.idea -/target -project/target \ No newline at end of file diff --git a/homeworks/homework_7/build.sbt b/homeworks/homework_7/build.sbt deleted file mode 100644 index 299e0e3d..00000000 --- a/homeworks/homework_7/build.sbt +++ /dev/null @@ -1,11 +0,0 @@ -name := "homework_7" - -version := "0.1" - -scalaVersion := "2.12.10" - -libraryDependencies += "com.lihaoyi" %% "utest" % "0.5.3" % "test" - -scalacOptions ++= Seq("-language:higherKinds") - -testFrameworks += new TestFramework("utest.runner.Framework") \ No newline at end of file diff --git a/homeworks/homework_7/homework_7.md b/homeworks/homework_7/homework_7.md deleted file mode 100644 index 3d7bb2df..00000000 --- a/homeworks/homework_7/homework_7.md +++ /dev/null @@ -1,3 +0,0 @@ -# Домашнее задание №7 (курс Scala, Naumen) - -Необходимо реализовать объявления функций в файле "MonadFunctor.scala" в соответствии с тестами (файл "Test.scala") diff --git a/homeworks/homework_7/project/build.properties b/homeworks/homework_7/project/build.properties deleted file mode 100644 index 010613d5..00000000 --- a/homeworks/homework_7/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.3.3 \ No newline at end of file diff --git a/homeworks/homework_7/src/main/scala/MonadFunctor.scala b/homeworks/homework_7/src/main/scala/MonadFunctor.scala deleted file mode 100644 index c90951a2..00000000 --- a/homeworks/homework_7/src/main/scala/MonadFunctor.scala +++ /dev/null @@ -1,23 +0,0 @@ - -trait Monad[F[_]] { - - def pure[A](a: A): F[A] - - def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] - - def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] = ??? - - def sequence[A](fas: List[F[A]]): F[List[A]] = ??? - - def compose[A, B, C](f: A => F[B])(g: B => F[C]): A => F[C] = ??? -} - -trait Functor[F[_]] { - def map[A, B](a: F[A])(f: A => B): F[B] -} - -object Functor { - def functorFromMonad[F[_]](M: Monad[F]): Functor[F] = new Functor[F] { - def map[A, B](a: F[A])(f: A => B): F[B] = ??? - } -} diff --git a/homeworks/homework_7/src/test/scala/Test.scala b/homeworks/homework_7/src/test/scala/Test.scala deleted file mode 100644 index 343e203a..00000000 --- a/homeworks/homework_7/src/test/scala/Test.scala +++ /dev/null @@ -1,33 +0,0 @@ -import utest._ - -object Test extends TestSuite { - val tupleMonad: Monad[Tuple1] = new Monad[Tuple1] { - def pure[A](a: A): Tuple1[A] = Tuple1(a) - - def flatMap[A, B](fa: Tuple1[A])(f: A => Tuple1[B]): Tuple1[B] = - f(fa._1) - } - - val tests: Tests = Tests { - 'test_CombineTwoMonadic - { - assert(tupleMonad.map2(Tuple1(1), Tuple1(2))((a, b) => a + b) == Tuple1(3)) - } - 'test_Sequence - { - assert(tupleMonad.sequence(List(Tuple1(1), Tuple1(2), Tuple1(3))) == Tuple1(List(1,2,3))) - } - 'test_Compose - { - val f: Int => Tuple1[Double] = a => Tuple1(a / 2.0) - val g: Double => Tuple1[String] = a => Tuple1(a.toString) - assert(tupleMonad.compose(f)(g)(3) == Tuple1("1.5")) - } - 'test_FunctorFromMonad - { - val funcVal = Functor.functorFromMonad[Option](new Monad[Option] { - def pure[A](a: A): Option[A] = Some(a) - def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] = - fa.flatMap(f) - }).map[Int, String](Some(3))(_.toString) - - assert(funcVal.contains("3")) - } - } -} diff --git a/homeworks/homework_8/.gitignore b/homeworks/homework_8/.gitignore deleted file mode 100644 index 56b16317..00000000 --- a/homeworks/homework_8/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/.idea -/target -project/target \ No newline at end of file diff --git a/homeworks/homework_8/build.sbt b/homeworks/homework_8/build.sbt deleted file mode 100644 index 26a9e968..00000000 --- a/homeworks/homework_8/build.sbt +++ /dev/null @@ -1,9 +0,0 @@ -name := "homework_8" - -version := "0.1" - -scalaVersion := "2.12.10" - -libraryDependencies += "com.lihaoyi" %% "utest" % "0.5.3" % "test" - -testFrameworks += new TestFramework("utest.runner.Framework") diff --git a/homeworks/homework_8/homework_8.md b/homeworks/homework_8/homework_8.md deleted file mode 100644 index 4e41675d..00000000 --- a/homeworks/homework_8/homework_8.md +++ /dev/null @@ -1,16 +0,0 @@ -# Домашнее задание №8 (курс Scala, Naumen) - -## Задание 1. *Read* -Реализовать тайпкласс Read, который позволяет прочитать значение типа T, реализующего тайпкласс, из строки. -Тайпкласс должен иметь метод read, который на вход принимает строку, а на выходе выдает Either[String, T], -где в случае, если чтение было успешно, будет Right с нужным значением, если неуспешным, то Left со строкой, -поясняющей ошибку. - -Реализовать для данного тайпкласса интерфейс с использованием неявных параметров и обогащающий класс. -Должны работать следующие синтаксисы: Read.read[T]("...") и "...".read[T] - -Реализовать для данного тайпкласса инстансы для типов: String, Int и Option[T], где тип Т уже имеет инстанс Read. -Для типа String операция чтения всегда успешна и возвращает саму строку. -Для типа Int операция возвращает число, если поданная на вход строка является корректым представлением числа, или ошибку. -Для типа Option[T] операция возвращает None, если на вход подана строка "None", Some(<результат чтения внутреннего выражения>), -если на вход подана строка вида "Some(...)" и выражение в скобках было корректно прочитано в тип T, и ошибку во всех остальных случаях. diff --git a/homeworks/homework_8/project/build.properties b/homeworks/homework_8/project/build.properties deleted file mode 100644 index 010613d5..00000000 --- a/homeworks/homework_8/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.3.3 \ No newline at end of file diff --git a/homeworks/homework_8/src/main/scala/Exercises.scala b/homeworks/homework_8/src/main/scala/Exercises.scala deleted file mode 100644 index dc5d3ccf..00000000 --- a/homeworks/homework_8/src/main/scala/Exercises.scala +++ /dev/null @@ -1,3 +0,0 @@ -import scala.util.Try -object Exercises { -} diff --git a/homeworks/homework_8/src/test/scala/Test.scala b/homeworks/homework_8/src/test/scala/Test.scala deleted file mode 100644 index 394c5b40..00000000 --- a/homeworks/homework_8/src/test/scala/Test.scala +++ /dev/null @@ -1,45 +0,0 @@ -import utest._ - -import Exercises._ - -object Test extends TestSuite { - - val tests = Tests { - 'string - { - val success = Read.read[String]("test") - assert(success == Right("test")) - } - - 'int - { - val success = "123".read[Int] - assert(success == Right(123)) - val failure = "test".read[Int] - assert(failure.isLeft) - } - - 'option - { - val none1 = "None".read[Option[String]] - assert(none1 == Right(None)) - val someString = "Some(test)".read[Option[String]] - assert(someString == Right(Some("test"))) - - val none2 = "None".read[Option[Int]] - assert(none2 == Right(None)) - val someInt = "Some(123)".read[Option[Int]] - assert(someInt == Right(Some(123))) - - val failure = "test".read[Option[String]] - assert(failure.isLeft) - val someFailure = "Some(test)".read[Option[Int]] - assert(someFailure.isLeft) - - val multipleSome = - "Some(Some(Some(Some(123))))".read[Option[Option[Option[Option[Int]]]]] - assert(multipleSome == Right(Some(Some(Some(Some(123)))))) - val multipleNone = "Some(Some(None))".read[Option[Option[Option[String]]]] - assert(multipleNone == Right(Some(Some(None)))) - val lessNone = "Some(None)".read[Option[Option[Option[Int]]]] - assert(lessNone == Right(Some(None))) - } - } -} diff --git a/homeworks/homework_9/.gitignore b/homeworks/homework_9/.gitignore deleted file mode 100644 index 56b16317..00000000 --- a/homeworks/homework_9/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/.idea -/target -project/target \ No newline at end of file diff --git a/homeworks/homework_9/build.sbt b/homeworks/homework_9/build.sbt deleted file mode 100644 index d2f156c8..00000000 --- a/homeworks/homework_9/build.sbt +++ /dev/null @@ -1,7 +0,0 @@ -name := "FP" - -version := "0.1" - -scalaVersion := "2.13.7" - -libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.10" % Test diff --git a/homeworks/homework_9/homework_9.md b/homeworks/homework_9/homework_9.md deleted file mode 100644 index c0e41cea..00000000 --- a/homeworks/homework_9/homework_9.md +++ /dev/null @@ -1,3 +0,0 @@ -# Домашнее задание №9 (курс Scala, Naumen) - -Необходимо реализовать объявления функций в файле "ListOps.scala" в соответствии с тестами (файл "Test.scala") diff --git a/homeworks/homework_9/project/build.properties b/homeworks/homework_9/project/build.properties deleted file mode 100644 index 302b6be1..00000000 --- a/homeworks/homework_9/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version = 1.3.13 \ No newline at end of file diff --git a/homeworks/homework_9/src/main/scala/DataList.scala b/homeworks/homework_9/src/main/scala/DataList.scala deleted file mode 100644 index 660993da..00000000 --- a/homeworks/homework_9/src/main/scala/DataList.scala +++ /dev/null @@ -1,11 +0,0 @@ -sealed trait DataList[+T] - -object DataList { - final case class NonEmptyList[+T](head: T, tail: DataList[T]) extends DataList[T] - case object EmptyList extends DataList[Nothing] - - def apply[T](x: T*): DataList[T] = x.toList match { - case head :: tail => NonEmptyList(head, apply(tail: _*)) - case _ => EmptyList - } -} diff --git a/homeworks/homework_9/src/main/scala/ListOps.scala b/homeworks/homework_9/src/main/scala/ListOps.scala deleted file mode 100644 index 826c38f8..00000000 --- a/homeworks/homework_9/src/main/scala/ListOps.scala +++ /dev/null @@ -1,48 +0,0 @@ -import scala.annotation.tailrec - -object ListOps { - - /** - * Функция fold "сворачивает" список из Т в один элемент типа Т. - * Если в списке лишь один элемент, то он и вернётся, два - вернётся результат применения f к этим элементам, - * больше двух - результат применения к f(f(f(...), a[i - 1]), a[i]) - * @param f функция свёртывания. Применяется попарно к предыдущему результату применения и i-ому элементу списка - * @return None - если список пустой - */ - def foldOption[T](f: (T, T) => T): DataList[T] => Option[T] = ??? - - - /** - * Используя foldOption[T](f: (T, T) => T) реализуйте суммирование всех элементов списка. - * @return Если список пустой, то 0 - */ - def sum[T : Numeric](list: DataList[T]): T = { - /** - * Используйте для суммирования двух чисел любого типа (Int, Long, Double, Float etc) - */ - def sumT(a: T, b: T) = implicitly[Numeric[T]].plus(a, b) - - ??? - } - - /** - * Фильтрация списка. Хвостовая рекурсия - * @param f - фильтрующее правило (если f(a[i]) == true, то элемент остаётся в списке) - */ - @tailrec - private def filterImpl[T](f: T => Boolean)(buffer: DataList[T])(l: DataList[T]): DataList[T] = ??? - - final def filter[T](f: T => Boolean): DataList[T] => DataList[T] = filterImpl(f)(DataList.EmptyList) - - final def map[A, B](f: A => B): DataList[A] => DataList[B] = { - case DataList.EmptyList => DataList.EmptyList - case DataList.NonEmptyList(head, tail) => DataList.NonEmptyList(f(head), map(f)(tail)) - } - - /** - * Используя композицию функций реализуйте collect. Collect - комбинация filter и map. - * В качестве фильтрующего правила нужно использовать f.isDefinedAt - */ - def collect[A, B](f: PartialFunction[A, B]): DataList[A] => DataList[B] = ??? - -} \ No newline at end of file diff --git a/homeworks/homework_9/src/test/scala/Test.scala b/homeworks/homework_9/src/test/scala/Test.scala deleted file mode 100644 index 7bc561eb..00000000 --- a/homeworks/homework_9/src/test/scala/Test.scala +++ /dev/null @@ -1,29 +0,0 @@ -import org.scalatest._ -import flatspec._ -import matchers._ - -class Test extends AnyFlatSpec with should.Matchers { - - "foldOption" should "return None on empty list" in { - ListOps.foldOption[Any](_ == _)(DataList.EmptyList) should be (None) - } - - "foldOption" should "work correct on non empty list" in { - ListOps.foldOption[String](_ ++ _)(DataList("1", "2", "3")) should be (Some("123")) - } - - "sum" should "work correctly" in { - ListOps.sum[Int](DataList(1, 2, 3)) should be (6) - } - - "filter" should "work correctly" in { - ListOps.filter[Int](_ % 2 == 0)(DataList((0 to 4).toList: _*)) should be (DataList(0, 2, 4)) - } - - "collect" should "work correctly" in { - ListOps.collect[Int, String] { - case i: Int if i % 2 == 0 => i.toString - }(DataList((0 to 4).toList: _*)) should be (DataList("0", "2", "4")) - } - -} diff --git a/index.md b/index.md index e62b5070..6fbe6af9 100644 --- a/index.md +++ b/index.md @@ -1,13 +1,17 @@ --- layout: default --- -# naumen.scala.course.2023.spring +# naumen.scala.course.2023.autumn ### Лекции * Лекция 1. [Что такое Scala?](lectures/scala_lecture_1.html) +* Лекция 4. [Функциональное программирование. Концепция](PowerPoint)](lectures/scala_lecture_4.pptx) ### Домашние задания * [Инструкция по предоставлению результатов](https://github.com/naumen-student/naumen.scala.course.2023.autumn#%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%80%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%D0%BE%D0%B2) -* [Задание 1](homeworks/homework_1/homework_1.md) [папка в GitHub](https://github.com/naumen-student/naumen.scala.course.2023.spring/tree/master/homeworks/homework_1) \ No newline at end of file +* [Задание 1](homeworks/homework_1/homework_1.md) [папка в GitHub](https://github.com/naumen-student/naumen.scala.course.2023.autumn/tree/master/homeworks/homework_1) +* [Задание 2](homeworks/homework_2/homework_2.md) [папка в GitHub](https://github.com/naumen-student/naumen.scala.course.2023.autumn/tree/master/homeworks/homework_2) +* [Задание 3](homeworks/homework_3/homework_3.md) [папка в GitHub](https://github.com/naumen-student/naumen.scala.course.2023.autumn/tree/master/homeworks/homework_3) +* [Задание 4](homeworks/homework_4/homework_4.md) [папка в GitHub](https://github.com/naumen-student/naumen.scala.course.2023.autumn/tree/master/homeworks/homework_4) \ No newline at end of file diff --git a/lectures/scala_lecture_4.pptx b/lectures/scala_lecture_4.pptx new file mode 100644 index 00000000..4d3a3adc Binary files /dev/null and b/lectures/scala_lecture_4.pptx differ