diff --git a/02/practice/src/main/scala/org/spbsu/mkn/scala/IntList.scala b/02/practice/src/main/scala/org/spbsu/mkn/scala/IntList.scala index 64ce1d5..e3494ae 100644 --- a/02/practice/src/main/scala/org/spbsu/mkn/scala/IntList.scala +++ b/02/practice/src/main/scala/org/spbsu/mkn/scala/IntList.scala @@ -1,21 +1,91 @@ package org.spbsu.mkn.scala import org.spbsu.mkn.scala.IntList._ +import scala.annotation.tailrec sealed trait IntList { def head: Int + def tail: IntList + def drop(n: Int): IntList + def take(n: Int): IntList + def map(f: Int => Int): IntList - def ::(elem: Int): IntList = ??? + + def ::(elem: Int): IntList = IntCons(elem, this) } -object IntList { +case object IntList { def undef: Nothing = throw new UnsupportedOperationException("operation is undefined") - def fromSeq(seq: Seq[Int]): IntList = ??? - def sum(intList: IntList): Int = ??? - def size(intList: IntList): Int = ??? + + def fromSeq(seq: Seq[Int]): IntList = seq.foldRight[IntList](IntNil) { (x, list) => IntCons(x, list) } + + def sum(intList: IntList): Int = { + intList match { + case IntNil => undef + case _ => foldLeft(intList, 0) {_ + _} + } + } + + def size(intList: IntList): Int = { + intList match { + case IntNil => 0 + case IntCons(_, list) => 1 + size(list) + } + } + // extra task: implement sum using foldLeft - // def foldLeft(???)(???): ??? = ??? + @tailrec + def foldLeft[T](intList: IntList, initValue: T)(f: (T, Int) => T): T = { + intList match { + case IntNil => initValue + case IntCons(x, list) => foldLeft(list, f(initValue, x))(f) + } + } +} + +case object IntNil extends IntList { + override def head: Int = undef + + override def tail: IntList = IntNil + + override def drop(n: Int): IntList = { + n match { + case 0 => IntNil + case _ => undef + } + } + + override def take(n: Int): IntList = { + n match { + case 0 => IntNil + case _ => undef + } + } + + override def map(f: Int => Int): IntList = IntNil } + +case class IntCons(x: Int, list: IntList) extends IntList { + override def head: Int = x + + override def tail: IntList = list + + override def drop(n: Int): IntList = { + n match { + case 0 => this + case _ => list.drop(n - 1) + } + } + + override def take(n: Int): IntList = { + n match { + case 0 => IntNil + case _ => IntCons(x, list.take(n - 1)) + } + } + + override def map(f: Int => Int): IntList = IntCons(f(x), list.map(f)) +} \ No newline at end of file diff --git a/02/practice/src/test/scala/org/spbsu/mkn/scala/IntListTest.scala b/02/practice/src/test/scala/org/spbsu/mkn/scala/IntListTest.scala index 665be66..5de23c9 100644 --- a/02/practice/src/test/scala/org/spbsu/mkn/scala/IntListTest.scala +++ b/02/practice/src/test/scala/org/spbsu/mkn/scala/IntListTest.scala @@ -5,44 +5,44 @@ import org.spbsu.mkn.scala.IntList.{fromSeq, size, sum} class IntListTest extends AnyFunSuite { test("head") { - assert(fromSeq(Seq(1,2,3)).head == 1) + assert(fromSeq(Seq(1, 2, 3)).head == 1) assert(fromSeq(Seq(1)).head == 1) assertThrows[UnsupportedOperationException](fromSeq(Seq()).head) } test("tail") { - assert(fromSeq(Seq(1,2,3)).tail == fromSeq(Seq(2,3))) + assert(fromSeq(Seq(1, 2, 3)).tail == fromSeq(Seq(2, 3))) assert(fromSeq(Seq(1)).tail == IntNil) } test("drop") { - assert(fromSeq(Seq(1,2,3)).drop(0) == fromSeq(Seq(1,2,3))) - assert(fromSeq(Seq(1,2,3)).drop(2) == fromSeq(Seq(3))) - assert(fromSeq(Seq(1,2,3)).drop(3) == IntNil) - assertThrows[UnsupportedOperationException](fromSeq(Seq(1,2,3)).drop(10)) + assert(fromSeq(Seq(1, 2, 3)).drop(0) == fromSeq(Seq(1, 2, 3))) + assert(fromSeq(Seq(1, 2, 3)).drop(2) == fromSeq(Seq(3))) + assert(fromSeq(Seq(1, 2, 3)).drop(3) == IntNil) + assertThrows[UnsupportedOperationException](fromSeq(Seq(1, 2, 3)).drop(10)) } test("take") { - assert(fromSeq(Seq(1,2,3)).take(0) == IntNil) - assert(fromSeq(Seq(1,2,3)).take(2) == fromSeq(Seq(1,2))) - assert(fromSeq(Seq(1,2,3)).take(3) == fromSeq(Seq(1,2,3))) - assertThrows[UnsupportedOperationException](fromSeq(Seq(1,2,3)).take(10)) + assert(fromSeq(Seq(1, 2, 3)).take(0) == IntNil) + assert(fromSeq(Seq(1, 2, 3)).take(2) == fromSeq(Seq(1, 2))) + assert(fromSeq(Seq(1, 2, 3)).take(3) == fromSeq(Seq(1, 2, 3))) + assertThrows[UnsupportedOperationException](fromSeq(Seq(1, 2, 3)).take(10)) } test("map") { assert(IntNil.map(_ * 2) == IntNil) - assert(fromSeq(Seq(1,2,3)).map(_ * 2) == fromSeq(Seq(2,4,6))) - assert(fromSeq(Seq(1,2,3)).map(identity) == fromSeq(Seq(1,2,3))) + assert(fromSeq(Seq(1, 2, 3)).map(_ * 2) == fromSeq(Seq(2, 4, 6))) + assert(fromSeq(Seq(1, 2, 3)).map(identity) == fromSeq(Seq(1, 2, 3))) } test("size") { assert(size(IntNil) == 0) - assert(size(fromSeq(Seq(1,2,3))) == 3) + assert(size(fromSeq(Seq(1, 2, 3))) == 3) } test("sum") { assertThrows[UnsupportedOperationException](sum(IntNil)) - assert(sum(fromSeq(Seq(1,2,3))) == 6) + assert(sum(fromSeq(Seq(1, 2, 3))) == 6) assert(sum(fromSeq(Seq(1))) == 1) }