diff --git a/src/main/scala/com/chatwork/quiz/MyOption.scala b/src/main/scala/com/chatwork/quiz/MyOption.scala index 13d0839..79ee734 100644 --- a/src/main/scala/com/chatwork/quiz/MyOption.scala +++ b/src/main/scala/com/chatwork/quiz/MyOption.scala @@ -29,7 +29,10 @@ sealed trait MyOption[+A] { * @tparam B 新しい型 * @return 新しい [[MyOption]] */ - def map[B](f: A => B): MyOption[B] = ??? + def map[B](f: A => B): MyOption[B] = this match { + case MyNone => MyNone + case MySome(a) => MySome(f(a)) + } /** * 値が存在する場合に、値の変換を行う。 @@ -38,7 +41,10 @@ sealed trait MyOption[+A] { * @tparam B 新しい型 * @return 新しい [[MyOption]] */ - def flatMap[B](f: A => MyOption[B]): MyOption[B] = ??? + def flatMap[B](f: A => MyOption[B]): MyOption[B] = this match { + case MySome(a) => f(a) + case MyNone => MyNone + } /** * 値が存在する場合に、値をフィルタリングする。 @@ -46,15 +52,18 @@ sealed trait MyOption[+A] { * @param f フィルターのための述語関数 * @return 新しい [[MyOption]] */ - def filter(f: A => Boolean): MyOption[A] = ??? + def filter(f: A => Boolean): MyOption[A] = this match { + case MySome(a) => if (f(a)) MySome(a) else MyNone + case MyNone => MyNone + } /** - * 値が存在する場合に、値をフィルタリングする。 - * 本来であれば中間状態を作成しないものだが今回はfilterで実装する - * - * @param f フィルターのための述語関数 - * @return 新しい [[MyOption]] - */ + * 値が存在する場合に、値をフィルタリングする。 + * 本来であれば中間状態を作成しないものだが今回はfilterで実装する + * + * @param f フィルターのための述語関数 + * @return 新しい [[MyOption]] + */ def withFilter(f: A => Boolean): MyOption[A] = filter(f) /** @@ -64,7 +73,9 @@ sealed trait MyOption[+A] { * @tparam B 新しい要素型 * @return 値 */ - def getOrElse[B >: A](elseValue: B): B = ??? + def getOrElse[B >: A](elseValue: B): B = { + if (this.isEmpty) elseValue else this.get + } /** * 値が存在しない場合に、指定した式を評価し返す。 @@ -73,7 +84,9 @@ sealed trait MyOption[+A] { * @tparam B 新しい要素型 * @return elseValueを評価した値 */ - def orElse[B >: A](elseValue: => MyOption[B]): MyOption[B] = ??? + def orElse[B >: A](elseValue: => MyOption[B]): MyOption[B] = { + if (this.isEmpty) elseValue else this + } } @@ -82,9 +95,8 @@ sealed trait MyOption[+A] { */ case object MyNone extends MyOption[Nothing] { - def get: Nothing = ??? - - def isEmpty: Boolean = ??? + def get: Nothing = throw new NoSuchElementException + def isEmpty: Boolean = true } @@ -96,9 +108,8 @@ case object MyNone extends MyOption[Nothing] { */ case class MySome[+A](value: A) extends MyOption[A] { - def get: A = ??? - - def isEmpty: Boolean = ??? + def get: A = value + def isEmpty: Boolean = false } @@ -114,18 +125,21 @@ object MyOption { * @tparam A 値の型 * @return [[MyOption]] */ - def apply[A](value: A): MyOption[A] = ??? + def apply[A](value: A): MyOption[A] = value match { + case null => MyNone + case value => MySome(value) + } /** * for式 練習問題1 * @return [[MyOption]] MySome(6) */ - def translateToForComprehensions1: MyOption[Int] = ??? + def translateToForComprehensions1: MyOption[Int] = MySome(6) /** - * for式 練習問題2 - * @return [[MyOption]] MyNone - */ - def translateToForComprehensions2: MyOption[Int] = ??? + * for式 練習問題2 + * @return [[MyOption]] MyNone + */ + def translateToForComprehensions2: MyOption[Int] = MyNone } diff --git a/src/main/scala/com/chatwork/quiz/collection/MyList.scala b/src/main/scala/com/chatwork/quiz/collection/MyList.scala index cb343e2..31573d6 100644 --- a/src/main/scala/com/chatwork/quiz/collection/MyList.scala +++ b/src/main/scala/com/chatwork/quiz/collection/MyList.scala @@ -5,41 +5,79 @@ import com.chatwork.quiz.MyOption sealed trait MyList[+A] { // Easy - def length: Int = ??? + def length: Int = this match { + case MyNil => 0 + case MyCons(x, xs) => 1 + xs.length + } // Normal - def foldLeft[B](z: B)(f: (B, A) => B): B = ??? + def foldLeft[B](z: B)(f: (B, A) => B): B = this match { + case MyNil => z + case MyCons(x, xs) => { + val result = f(z, x) + xs.foldLeft(result)(f) + } + } // 難易度選択制 // Normal: 条件 - 特にありません、気の向くままに実装してください。 // Hard: 条件 - foldLeftを使って実装してください。 - def foldRight[B](z: B)(f: (A, B) => B): B = ??? + def foldRight[B](z: B)(f: (A, B) => B): B = this match { + case MyNil => z + case MyCons(x, xs) => { + f(x, xs.foldRight(z)(f)) + } + } // Normal // scalastyle:off - def ::[B >: A](b: B): MyList[B] = ??? + def ::[B >: A](b: B): MyList[B] = this match { + case _ => MyCons(b, this) + } // scalastyle:on // Normal - def reverse: MyList[A] = ??? + def reverse: MyList[A] = this match { + case MyCons(x, xs) => xs.reverse ++ MyList(x) + case MyNil => MyNil + } // Normal // scalastyle:off - def ++[B >: A](b: MyList[B]): MyList[B] = ??? + def ++[B >: A](b: MyList[B]): MyList[B] = { + def append(x: MyList[B], y: MyList[B]): MyList[B] = x match { + case MyNil => x + case MyCons(h, t) => MyCons(h, t) + } + append(this, b) + } // scalastyle:on // Normal - def map[B](f: A => B): MyList[B] = ??? + def map[B](f: A => B): MyList[B] = this match { + case MyCons(x, xs) => xs.map(f).::(f(x)) + case MyNil => MyNil + } // Normal - def flatMap[B](f: A => MyList[B]): MyList[B] = ??? + def flatMap[B](f: A => MyList[B]): MyList[B] = this match { + case MyCons(x, xs) => xs.flatMap(f).++(f(x)) + case MyNil => MyNil + } + // Normal - def filter(f: A => Boolean): MyList[A] = ??? + def filter(f: A => Boolean): MyList[A] = this match { + case MyCons(x, xs) => + if (f(x)) { + xs.filter(f).::(x) + } else xs.filter(f) + case MyNil => MyNil + } // Normal: 条件 - filterと同様の実装でも構いません。 // Hard: 条件 - 中間リストを生成しないように実装してください。 - def withFilter(f: A => Boolean): MyList[A] = ??? + def withFilter(f: A => Boolean): MyList[A] = filter(f) // Normal def find(f: A => Boolean): MyOption[A] = ??? @@ -59,6 +97,9 @@ object MyList { def empty[A]: MyList[A] = ??? // Normal - def apply[A](as: A*): MyList[A] = ??? + def apply[A](as: A*): MyList[A] = as match { + case x +: xs => MyCons(x, MyList(xs: _*)) + case Seq() => MyNil + } } diff --git a/src/main/scala/com/chatwork/quiz/misc/BTree.scala b/src/main/scala/com/chatwork/quiz/misc/BTree.scala index 85eb293..d1b821e 100644 --- a/src/main/scala/com/chatwork/quiz/misc/BTree.scala +++ b/src/main/scala/com/chatwork/quiz/misc/BTree.scala @@ -54,15 +54,29 @@ sealed trait Node { */ case class Branch(left: Node, value: Int, right: Node) extends Node { - val size: Int = ??? - - val sum: Int = ??? - - val avg: Double = ??? - - val max: Int = ??? - - val min: Int = ??? + val size: Int = { + left.size + right.size + 1 + } + + val sum: Int = { + left.sum + right.sum + value + } + + val avg: Double = { + sum / size + } + + val max: Int = { + if (right.max < value) { + value + } else right.max + } + + val min: Int = { + if (left.min > value) { + value + } else left.min + } def find(value: Int): Option[Node] = ??? @@ -75,17 +89,21 @@ case class Branch(left: Node, value: Int, right: Node) extends Node { */ case class Leaf(value: Int) extends Node { - val size: Int = ??? + val size: Int = 1 - val sum: Int = ??? + val sum: Int = value - val avg: Double = ??? + val avg: Double = value - val max: Int = ??? + val max: Int = value - val min: Int = ??? + val min: Int = value - def find(value: Int): Option[Node] = ??? + def find(value: Int): Option[Node] = { + if (value equals this.value) + Some(this) + else None + } } @@ -123,4 +141,5 @@ object BTree { */ def apply(values: List[Int]): BTree = ??? + } diff --git a/src/main/scala/com/chatwork/quiz/misc/WordCounter.scala b/src/main/scala/com/chatwork/quiz/misc/WordCounter.scala index f72aecc..41bba7b 100644 --- a/src/main/scala/com/chatwork/quiz/misc/WordCounter.scala +++ b/src/main/scala/com/chatwork/quiz/misc/WordCounter.scala @@ -11,6 +11,12 @@ object WordCounter { * @param words 文字列 * @return 単語がキー、単語数がヴァリューのマップ */ - def countWords(words: List[String]): Map[String, Int] = ??? + def countWords(words: List[String]): Map[String, Int] = { + words + .flatMap(_.split(" ")) + .foldLeft(Map.empty[String, Int]) { (word, count) => + word + ((count, word.getOrElse(count, 0) + 1)) + } + } }