ローマ数字変換
えーと、じゃ、Scala で。
assert はテストとは違う気がするが、まぁいいか。
object RomanNumber { val romanDigits = List( ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400), ("C", 100), ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9), ("V", 5), ("IV", 4), ("I", 1) ) def parse(s: String): Int = { def parseImpl(s: String, digits: List[(String, Int)], result: Int) : Int = if (s.length == 0) result else if (digits.isEmpty) throw new IllegalArgumentException() else if (s.startsWith(digits.head._1)) parseImpl(s.substring(digits.head._1.length), digits, result + digits.head._2) else parseImpl(s, digits.tail, result) parseImpl(s.toUpperCase, romanDigits, 0) } def format(n: Int): String = { if (n < 1 || n > 3999) throw new IllegalArgumentException() def formatImpl(n: Int, digits: List[(String, Int)]): List[String] = if (n == 0) List() else if (n >= digits.head._2) digits.head._1 :: formatImpl(n - digits.head._2, digits) else formatImpl(n, digits.tail) def join(xs: List[Object]) = { val builder = new StringBuilder() for (x <- xs) { builder.append(x) } builder.toString() } join(formatImpl(n, romanDigits)) } def main(args: Array[String]) { assert(format(11) == "XI") assert(parse("MDCCCLXXXVIII") == 1888) assert(parse("mdccclxxxviii") == 1888) assert(parse("McmXLv") == 1945) try { format(0) assert(false) } catch { case _: Throwable => Unit } try { parse("A") assert(false) } catch { case _: Throwable => Unit } } }