FizzBuzzブームが再び巻き起こり、鎮火したかと思ったら「整数を数えていき、素数のときにJOJOと表示する」遊びがひそかに流行している。
- mike、mikeなるままに…: 素数の時にEnrico Pucciと出力するプログラムを書いてみた
- 素数の時にJoJo -Java- - 水まんじゅう
- 素数の時にJOJO -Oacle PL/SQL編- - しおしおの雑記帳
- 素数のときだけ"JOJO!"って出力するプログラムを作ってみた - くりにっき
解いてみた
Kotlinで解いてみた。
fun main(args : Array<String>) { for(i in 1..100) { i.jojo() } } private fun Int.jojo() { val s = if(this.isPrime()) "JOJO!" else "$this" println(s) } private fun Int.isPrime() : Boolean { check(this > 0) if(this == 1) return false if(this == 2) return true if(this % 2 == 0) return false for(i in Array((this - 3) / 4) { it * 2 + 3 }) { if(this % i == 0 && this != i) { return false } } return true }
解説
main()とjojo()はいいとして、注目してもらいたいのがisPrime()関数。
これはIntの拡張関数ということで定義した。
関数の中で最初に登場するcheck()関数。
これはオブジェクトの状態チェックを行う関数で、引数の値がfalseの場合、IllegalStateExceptionを投げる。
似たような関数にassert(), require()などがKotlinの標準ライブラリから提供されているよん。
次の3つ続くif式は、無駄な計算を省くために置いた。
1は素数じゃないし、2は素数。2の倍数は素数じゃないですよ。
って書いておくことで、後のシラミ潰しを少しでも楽にしようとしている。
forループ内で、そのシラミ潰し作業。
要は、自分自身(関数のレシーバのInt)を割り切れる数が存在するかどうかを調べる。
forのカッコ内では配列を作り、その要素に1つずつアクセスするループにしているんだけど、
3から始まり、公差が2の配列を作っている。
Arrayのコンストラクタは、配列の要素数と、初期化のための関数を取るからそれができる。
あとは単純に素数判定。
おまけ
@_siosio_さんもこの問題をKotlinで解かれているので、勝手に解説しちゃいますw
素数の時にJOJOと出力するKotlin — Gist
jojoIterator()は、実際に画面に出力する値のイテレータを返す関数。
関数内で真っ先に目に入るのが、ローカル関数のnext()。
これは1つの数値に対して素数判定を行い、画面に出力する値を返す。
そして、素数判定の仕方がKool!
1と2に関しては、僕のと同様ハードコード。
それ以外の数である場合には、次のように判定している。
「2から、その数の平方根(端数切り捨て)までの連続する整数列に対して、その数を割り切れる要素が1つもなければ素数である」
これをKotlinで次のように表現している。
「2から、その数の平方根(端数切り捨て)までの連続する整数列」を作る
val r = (2..Math.sqrt(number.toDouble()).toInt())
「その数を割り切れる要素が1つもなければ素数である」
if (r.any {number % it == 0}) { number } else { "JOJO" }
any()は、いずれかの要素が指定した条件を満たしたときにtrueを、それ以外の場合にfalseを返す関数。
ここで指定した条件は number % it == 0、つまり素数判定したい数が要素で割り切れるかどうか。
1つでも割り切れる要素が存在すれば、any()はtrueを返すので、素数ではない。
falseの場合は素数なので "JOJO" を返す。