Beginning Scala programming4

初心者ぺちぱーがGitHubでScalaレッスンを始めたぞ。今回は、4回目の問題の続きとして、与えられた数が素数かどうかを判定する関数を追加してみよう。

引き続き、練習問題はここのページだ。

素数判定

与えられた数が素数かどうか調べる

前回までの内容で、与えられた数までの素数を取得することができた。今回はその中に与えられた数が含まれるかどうかを判定できるようにしよう。

前回書いたコードはこんなやつだ。

object MyFirstPrimeNumber5 {
def toList(max: Int): List[Int] = max match {
case max if max <= 1 => List()
case max if max == 2 => List(2)
// step1
// step2
case _ => eratosthenesSieve(2, List(2), 2 to max)
}
private
def eratosthenesSieve(last: Int, list: List[Int], range: Seq[Int]): List[Int] = range.filter {
// step3
_ % last != 0
} match {
// step4
case range1 if range1.max < math.pow(list.max, 2) => list ++ range1
// back to step2
// step3
case range1 => eratosthenesSieve(range1.head, list ::: List(range1.head), range1)
}
}

toList(max)を実行して、Listを取得した後、その中に、引数の数字が含まれるかどうかを調べればいいわけだ。PHPだとin_array()みたいな関数だけど、Scalaだと、Listクラスにcontains()というメソッドがある。scala.collection.immutable.Listのドキュメントによると、こんなシグネチャーだ。

def contains(elem: Any): Boolean

ちょっと使ってみよう。

val list = List(1, 3, 5)
list.contains(1)
list.contains(2)
scala> val list = List(1, 3, 5)
list: List[Int] = List(1, 3, 5)
scala> list.contains(1)
res0: Boolean = true
scala> list.contains(2)
res1: Boolean = false

動いてそうだな。じゃあ書いてみよう。

object MyFirstPrimeNumber6 {
def contains(i: Int) = toList(i).contains(i)
//... MyFirstPrimeNumber5と一緒
}

なんか簡単に書けるよね。

テストーーー

class MyFirstPrimeNumber6Test extends FunSuite {
// … MyFirstPrimeNumber5Testと一緒
test("Prime numbers do not contain -1") {
expectResult(false)(MyFirstPrimeNumber6.contains(-1))
}
test("Prime numbers do not contain 0") {
expectResult(false)(MyFirstPrimeNumber6.contains(0))
}
test("Prime numbers do not contain 1") {
expectResult(false)(MyFirstPrimeNumber6.contains(1))
}
test("Prime numbers contain 2") {
expectResult(true)(MyFirstPrimeNumber6.contains(2))
}
test("Prime numbers contain 3") {
expectResult(true)(MyFirstPrimeNumber6.contains(3))
}
test("Prime numbers do not contain 4") {
expectResult(false)(MyFirstPrimeNumber6.contains(4))
}
}
テスト結果
Testing started at 18:53 ...
- Prime numbers ranging from 2 to 20 are 2, 3, 5, 7, 11, 13, 17, 19
- 2 is prime number
- 1 is not prime number
- 0 is not prime number
- -1 is not prime number
- Prime numbers do not contain -1
- Prime numbers do not contain 0
- Prime numbers do not contain 1
- Prime numbers contain 2
- Prime numbers contain 3
- Prime numbers do not contain 4
Process finished with exit code 0

よしよし。大丈夫そうだ。

Refactor

toList(max)を書いたときもそうだったけど、1以下の場合は、素数の定義上、そもそも素数がないことが分かっているから、toList(max)を実行する必要はなくて、falseを返せばいいし、2の場合もtrueを返せばいいわけだから、ちょっと変更してみよう。

object MyFirstPrimeNumber7 {
def contains(i: Int) = i match {
case i if i <= 1 => false
case i if i == 2 => true
case _ => toList(i).contains(i)
}
// …
}
テスト結果
Testing started at 19:01 ...
- Prime numbers ranging from 2 to 20 are 2, 3, 5, 7, 11, 13, 17, 19
- 2 is prime number
- 1 is not prime number
- 0 is not prime number
- -1 is not prime number
- Prime numbers do not contain -1
- Prime numbers do not contain 0
- Prime numbers do not contain 1
- Prime numbers contain 2
- Prime numbers contain 3
- Prime numbers do not contain 4
Process finished with exit code 0

動いてそうね。

Stream

全部の要素を計算する必要がない場合には、こんなやり方もあるらしい。Scalaって~~こわい~~奥が深いんだなー。。

Conclusion

4回目のレッスンもGitHubに上げてある。今日はあんまり大したことしてないな。まとめ!

  • contains()使ってみた
  • Streamが使えるようになると、~~モテモテ~~いろいろできるらしい