mirror of
https://github.com/VyunSergey/tinkoff-interview.git
synced 2025-12-06 11:36:54 +03:00
Initial Commit
This commit is contained in:
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Project exclude paths
|
||||||
|
/.bsp
|
||||||
|
/.idea
|
||||||
|
/project/target/
|
||||||
|
/project/project/target/
|
||||||
|
/target/
|
||||||
|
/target/scala-2.13/classes/
|
||||||
5
build.sbt
Normal file
5
build.sbt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
name := "tinkoff-pr"
|
||||||
|
|
||||||
|
version := "0.1"
|
||||||
|
|
||||||
|
scalaVersion := "2.13.6"
|
||||||
1
project/build.properties
Normal file
1
project/build.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
sbt.version = 1.4.7
|
||||||
31
src/main/scala/test1.scala
Normal file
31
src/main/scala/test1.scala
Normal file
@@ -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)
|
||||||
|
}
|
||||||
53
src/main/scala/test2.scala
Normal file
53
src/main/scala/test2.scala
Normal file
@@ -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))
|
||||||
|
}
|
||||||
36
src/main/scala/test3.scala
Normal file
36
src/main/scala/test3.scala
Normal file
@@ -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)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user