commit c1c84c992f549afe08b65856a30dea8eda0b8f92 Author: VyunSergey Date: Thu Jun 10 13:50:37 2021 +0300 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c94718 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Project exclude paths +/.bsp +/.idea +/project/target/ +/project/project/target/ +/target/ +/target/scala-2.13/classes/ diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..997afab --- /dev/null +++ b/build.sbt @@ -0,0 +1,5 @@ +name := "tinkoff-pr" + +version := "0.1" + +scalaVersion := "2.13.6" diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..97a7ea7 --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version = 1.4.7 \ No newline at end of file diff --git a/src/main/scala/test1.scala b/src/main/scala/test1.scala new file mode 100644 index 0000000..f012815 --- /dev/null +++ b/src/main/scala/test1.scala @@ -0,0 +1,31 @@ +object test1 extends App { + /** + * 1) Сжать последовательность целых чисел + * Seq(1, 2, 2, 3, 4, 3, 3, 3) => Seq((1, 1), (2, 2), (3, 1), (4, 1), (3, 3)) + * Ответ выдать в виде Seq[(Int, Int)] (число из последовательности и число последовательных повторений) + * 2) восстановить исходную последовательность из сжатой + */ + + def collectP(seq: Seq[Int]): Seq[(Int, Int)] = + seq.foldLeft(Seq.empty[(Int, Int)]) { + case ((elm, cnt) :: tail, int) if elm == int => + (int, cnt + 1) +: tail + case (acc, int) => + (int, 1) +: acc + case (Nil, int) => Seq((int, 1)) + } + + def explodeP(seq: Seq[(Int, Int)]): Seq[Int] = { + seq.flatMap { case (i, cnt) => Seq.fill(cnt)(i) } + } + + val seq = Seq(1, 2, 2, 3, 4, 3, 3, 3) + val res = collectP(seq).reverse + val res2 = explodeP(res) + + println(res) + assert(res == Seq((1, 1), (2, 2), (3, 1), (4, 1), (3, 3))) + + println(res2) + assert(res2 == seq) +} diff --git a/src/main/scala/test2.scala b/src/main/scala/test2.scala new file mode 100644 index 0000000..d3af8a0 --- /dev/null +++ b/src/main/scala/test2.scala @@ -0,0 +1,53 @@ +import scala.concurrent.{Await, ExecutionContext, Future} +import scala.concurrent.duration._ +import scala.util.control.NonFatal + +object test2 extends App { + /** + * На входе получаем последовательность асинхронных вызовов + * с сигнатурой Seq[Future[String]] + * Получить Future[(Seq[String], Seq[Throwable]) - результат агрегации + * выполненных Future и исключений + */ + def sequenceF(seq: Seq[Future[String]]) + (implicit ec: ExecutionContext): Future[(Seq[String], Seq[Throwable])] = { + Future.sequence( + seq.map { ftr => + ftr.map(Right(_)).recover { case NonFatal(e) => Left(e) } + } + ).map { seq => + seq.foldLeft((Seq.empty[String], Seq.empty[Throwable])) { + case ((res, errs), Left(e)) => (res, errs :+ e) + case ((res, errs), Right(str)) => (res :+ str, errs) + } + } + } + + import scala.concurrent.ExecutionContext.Implicits.global + + val (exp1, exp2, exp3) = ( + new RuntimeException("exception1"), + new RuntimeException("exception2"), + new RuntimeException("exception3") + ) + val talk = Seq( + Future { + Thread.sleep(1000) + "red" + }, + Future.failed(exp1), + Future.successful("blue"), + Future.failed(exp2), + Future.successful("green"), + Future.failed(exp3) + ) + + val resF = sequenceF(talk) + val (res, errs) = Await.result(resF, 1.minute) + + println(res) + assert(res == Seq("red", "blue", "green")) + + println(errs) + assert(errs == Seq(exp1, exp2, exp3)) +} diff --git a/src/main/scala/test3.scala b/src/main/scala/test3.scala new file mode 100644 index 0000000..2a07643 --- /dev/null +++ b/src/main/scala/test3.scala @@ -0,0 +1,36 @@ +object test3 extends App { + /** + * Transformation Chain + * Дан набор возможных трансформаций: type Transformation[T] = T => Option[T] + * Написать функцию преобразования последовательности трансформаций в возможную трансформацию. + * Новая трансформация это результат работы всей цепочки трансформаций, которые не вернули None. + * Если все вернули None, то общий результат None. + */ + + type Transformation[T] = T => Option[T] + + def transformationChain[T](chain: Seq[Transformation[T]]): Transformation[T] = + (t: T) => { + chain.foldLeft(Option.empty[T]) { (acc, trm) => + acc.flatMap { t => + trm(t) match { + case s: Some[T] => s + case None => Some(t) + } + }.orElse(trm(t)) + } + } + + val t1: Transformation[Int] = t => Some(t + t) + val t2: Transformation[Int] = _ => None + val t3: Transformation[Int] = t => if(t > 2) Some(t * t) else None + + val tc1 = transformationChain(Seq(t1,t2,t3)) + val tc2 = transformationChain(Seq(t2,t3)) + + println(tc1(2), tc1(1), tc2(1)) + + assert(tc1(2).contains(16)) + assert(tc1(1).contains(2)) + assert(tc2(1).isEmpty) +}