ローマ数字変換
えーと、じゃ、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
}
}
}