はじめに
この記事で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.
まとめ
実はこの記事を書いている最中にこの記事の
英語版のWikipediaにはフィボナッチ数列をいろいろな方向に拡張しまくった数列群についての性質等が書かれていますので、必要に応じてご覧いただけるとよろしいかと思います。
この記事は以上です。