From f5285326f2a2423b76cd9dcab329812debdf0d98 Mon Sep 17 00:00:00 2001 From: Vikas Date: Wed, 28 Oct 2020 14:00:36 +0900 Subject: [PATCH 1/3] WordCounter Solution --- src/main/scala/com/chatwork/quiz/misc/WordCounter.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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)) + } + } } From e37d8c69257946994c0206b53f58819497f84a81 Mon Sep 17 00:00:00 2001 From: Vikas Date: Wed, 28 Oct 2020 14:12:18 +0900 Subject: [PATCH 2/3] MyOption Solution --- .../scala/com/chatwork/quiz/MyOption.scala | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/main/scala/com/chatwork/quiz/MyOption.scala b/src/main/scala/com/chatwork/quiz/MyOption.scala index 13d0839..3391dc4 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,7 +52,10 @@ 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 + } /** * 値が存在する場合に、値をフィルタリングする。 @@ -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,9 @@ sealed trait MyOption[+A] { */ case object MyNone extends MyOption[Nothing] { - def get: Nothing = ??? + def get: Nothing = throw new NoSuchElementException - def isEmpty: Boolean = ??? + def isEmpty: Boolean = true } @@ -96,9 +109,9 @@ case object MyNone extends MyOption[Nothing] { */ case class MySome[+A](value: A) extends MyOption[A] { - def get: A = ??? + def get: A = value - def isEmpty: Boolean = ??? + def isEmpty: Boolean = false } @@ -114,18 +127,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] = ??? + def translateToForComprehensions2: MyOption[Int] = MyNone } From 7a10ba60b08a6e599dd585ee42e42bd82bc03b30 Mon Sep 17 00:00:00 2001 From: Vikas Date: Wed, 28 Oct 2020 14:26:56 +0900 Subject: [PATCH 3/3] List and Options --- .../scala/com/chatwork/quiz/MyOption.scala | 26 ++++---- .../com/chatwork/quiz/collection/MyList.scala | 63 +++++++++++++++---- .../scala/com/chatwork/quiz/misc/BTree.scala | 49 ++++++++++----- 3 files changed, 98 insertions(+), 40 deletions(-) diff --git a/src/main/scala/com/chatwork/quiz/MyOption.scala b/src/main/scala/com/chatwork/quiz/MyOption.scala index 3391dc4..79ee734 100644 --- a/src/main/scala/com/chatwork/quiz/MyOption.scala +++ b/src/main/scala/com/chatwork/quiz/MyOption.scala @@ -58,12 +58,12 @@ sealed trait MyOption[+A] { } /** - * 値が存在する場合に、値をフィルタリングする。 - * 本来であれば中間状態を作成しないものだが今回はfilterで実装する - * - * @param f フィルターのための述語関数 - * @return 新しい [[MyOption]] - */ + * 値が存在する場合に、値をフィルタリングする。 + * 本来であれば中間状態を作成しないものだが今回はfilterで実装する + * + * @param f フィルターのための述語関数 + * @return 新しい [[MyOption]] + */ def withFilter(f: A => Boolean): MyOption[A] = filter(f) /** @@ -95,8 +95,7 @@ sealed trait MyOption[+A] { */ case object MyNone extends MyOption[Nothing] { - def get: Nothing = throw new NoSuchElementException - + def get: Nothing = throw new NoSuchElementException def isEmpty: Boolean = true } @@ -109,8 +108,7 @@ case object MyNone extends MyOption[Nothing] { */ case class MySome[+A](value: A) extends MyOption[A] { - def get: A = value - + def get: A = value def isEmpty: Boolean = false } @@ -128,7 +126,7 @@ object MyOption { * @return [[MyOption]] */ def apply[A](value: A): MyOption[A] = value match { - case null => MyNone + case null => MyNone case value => MySome(value) } @@ -139,9 +137,9 @@ object MyOption { def translateToForComprehensions1: MyOption[Int] = MySome(6) /** - * for式 練習問題2 - * @return [[MyOption]] MyNone - */ + * 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 = ??? + }