n-bonacci数列を出力するScalaのコードを書いてみた。

By | 2020年5月2日

はじめに

この記事でnbonacci数列を計算するPython3のコードを書いてみたので、その勢いに乗ってScalaのプログラムも書いてみることにしました。

スポンサーリンク

さっそくプログラムです。

以下のようなプログラムを書いてみました。sbtを使ってFAT jarを作って実行することがほぼ前提のコードになっているために、コマンドラインオプションの処理にscoptを使うのが前提のコードになっていたりしますが、そのあたりの点は平にご容赦ください。🙇‍♂️

//
// See https://pandanote.info/?p=6259 for details.
//
package info.pandanote.nbonaccitest
import scopt.OParser
import org.slf4j.LoggerFactory
import scala.collection.mutable.ListBuffer
case class Options(a: Int = 2, n: Int = 10)
class NBonacci
object NBonacci {
private lazy val logger = LoggerFactory.getLogger(classOf[NBonacci])
def main(args: Array[String]): Unit = {
val builder = OParser.builder[Options]
val parser = {
import builder._
OParser.sequence(
programName("NBonacci"),
head("NBonacci","0.1.0-SNAPSHOT"),
opt[Int]('a',"term")
.action((x,c) => c.copy(a = x)).text("Number of terms in the recurrence relation.")
.validate(x =>
if (x > 0) success
else failure("Value <a> must be a positive integer")),
opt[Int]('n',"number-of-terms")
.action((x,c) => c.copy(n = x)).text("Number of terms to calculate.")
.validate(x =>
if (x > 0) success
else failure("Value <n> must be a positive integer")),
help("help").text("Calculate n-bonacci sequence.")
)
}
val o: Options = OParser.parse(parser,args,Options()) match {
case Some(options) => options
case _ => sys.exit(1)
}
logger.info(o.toString)
val buf = ListBuffer.fill(o.a-1)(0)
buf += 1
var count = 0
while (count < o.n) {
if (count < o.a) {
println(buf(count))
} else {
val next = buf.result.foldRight(0){(x,y) => x+y}
println(next)
buf += next
buf.remove(0)
}
count+=1
}
}
}

ということで、scoptを用いたコマンドラインオプションの処理のためのコードが行数にして全体の2/3くらいを占めるコードになっていて、nbonacci数列の計算を行うコードは46行目から始まります。この記事のPython3の数列の計算を行うためのコードと比較すると、Scalaの方ではコードブロックの境界を示す括弧({,})がある分だけコードの行数が増えています。

動作の確認。

前節で示したプログラムでFAT jarを作成して動作確認です。

以下のコマンドラインオプションが使用できる仕様としています。

  • -a <integer>: 次の項を求めるために必要な項の数。3項間漸化式であれば2となります。
  • -n <integer>: 計算の対象となる項の数。初項からの項数になります。

以下、”-a”オプションとともに指定した値をa、”-n”オプションとともに指定した値をnとそれぞれおきます。

a = 2, n = 10


C:\Users\Pandanote\scala\NBonacciTest>java -jar target\scala-2.13\nbonaccitest-assembly-0.1.0-SNAPSHOT.jar -a 2 -n 10
0
1
1
2
3
5
8
13
21
34

a = 3, n = 10

C:\Users\Pandanote\scala\NBonacciTest> java -jar target\scala-2.13\nbonaccitest-assembly-0.1.0-SNAPSHOT.jar -a 3 -n 10
0
0
1
1
2
4
7
13
24
44

a = 4, n = 15

スポンサーリンク

C:\Users\Pandanote\scala\NBonacciTest> java -jar target\scala-2.13\nbonaccitest-assembly-0.1.0-SNAPSHOT.jar -a 4 -n 15
0
0
0
1
1
2
4
8
15
29
56
108
208
401
773

a = 5, n = 30

C:\Users\Pandanote\scala\NBonacciTest> java -jar target\scala-2.13\nbonaccitest-assembly-0.1.0-SNAPSHOT.jar -a 5 -n 30
0
0
0
0
1
1
2
4
8
16
31
61
120
236
464
912
1793
3525
6930
13624
26784
52656
103519
203513
400096
786568
1546352
3040048
5976577
11749641

a = 0, n = 300

※エラーメッセージの表示例です。
C:\Users\Pandanote\scala\NBonacciTest> java -jar target\scala-2.13\nbonaccitest-assembly-0.1.0-SNAPSHOT.jar -a 0 -n 300
Error: Value must be a positive integer
Try --help for more information.

まとめ

実はこの記事を書いている最中にこの記事の際の最初の項の値は1としていたのは誤りっぽいことに気が付いたので、プログラムともどもしれっと修正してしまいました。

英語版のWikipediaにはフィボナッチ数列をいろいろな方向に拡張しまくった数列群についての性質等が書かれていますので、必要に応じてご覧いただけるとよろしいかと思います。

この記事は以上です。