ちゃきちゃきのJavaプログラマですが、ここ最近Scalaを勉強中です。(2、3年前にもチャレンジしましたがその時は挫折しました。。。)
Scalaの本当の力を引き出すには関数型プログラミングを深く知る必要があるようなのですが、その辺はまだまだ修行不足です。
とりあえずScalaのコーディングに慣れるためCodeIQの問題に挑戦して行きたいと思います。
今回の問題はこちら。
数学の問題をプログラミングで解こう!「プラス・マイナス・ゼロ」問題解説
import java.util.Scanner
import scala.collection.mutable
object Main {
def main(args: Array[String]) = {
val n = new Scanner(System.in).nextLine().toInt
val memo = mutable.Map[(Int,Int), Long]().empty
def g(n:Int, s:Int):Long = {
memo.get((n, s)) match {
case Some(v) => v
case None if n == 1 => if(s == 1 || s == -1) 1 else 0
case _ => memo((n, s)) = g(n-1, s - n) + g(n-1, s + n); memo((n,s))
}
}
println(g(n, 0))
}
}
解法の詳しい解説は先程のページに任せるとして、実は上記コードは提出したものとは別ものです。。。
解説ページや他の人が公開したコードを見て自分の書いたものの稚拙さを反省して書き直しました。
ホントに提出したコードはこちら。
import java.util.Scanner
import scala.collection.mutable
object Main {
def main(args: Array[String]): Unit = {
val scanner = new Scanner(System.in)
val n = scanner.nextLine().toInt
val memo = mutable.Map[String, Long]()
/**
* 1からnまでの数字をプラスマイナスして0になるパターンを再帰的に求める。
* @param currentSum 現在の和
* @param currentNum 現在の数字
* @return パターン数
*/
def countZerosum(currentSum:Int, currentNum:Int):Long = {
val memoKey = currentSum + "-" + currentNum
if(memo.contains(memoKey)) {
return memo(memoKey)
}
if(currentNum > n) {
if(currentSum == 0) {
return 1
}else{
return 0
}
}
val nextNum = currentNum + 1
val count = countZerosum(currentSum + currentNum, nextNum) + countZerosum(currentSum - currentNum, nextNum)
memo(memoKey) = count
count
}
val result = countZerosum(0, 1)
println(result)
}
}
出力結果は間違ってないのですが、エレガントさに欠けますね。
単にJavaのコードをScalaで書き直しただけという感じです。