ICPC: Problem C: Numeral System

Problem C: Numeral Systemより。ふつうに実装。StringがCharのリストだと楽です。エラーチェックはしていません。変な入力を与えると落ちます。

module Main (main) where

import Data.Char (isDigit, digitToInt)
import Text.Printf (printf)

toMCXI :: Int -> String
toMCXI = concat . zipWith f "mcxi"  . printf "%04d"
  where
    f :: Char -> Char -> String
    f u '0' = ""
    f u '1' = [u]
    f u c = [c, u]

fromMCXI :: String -> Int
fromMCXI = sum . map g . f
  where
    f :: String -> [(Char, Int)]
    f [] = []
    f (c : cs)
      | isDigit c = (head cs, digitToInt c) : (f . tail) cs
      | otherwise = (c, 1) : f cs

    g :: (Char, Int) -> Int
    g ('m', i) = i * 1000
    g ('c', i) = i * 100
    g ('x', i) = i * 10
    g ('i', i) = i

interactLines :: ([String] -> [String]) -> IO ()
interactLines f = interact (unlines . f . lines)

calc :: String -> String
calc = toMCXI . sum . map fromMCXI . words

main :: IO ()
main = interactLines (\ (n : ls) -> map calc $ take (read n) ls)

入力:

10
xi x9i
i 9i
c2x2i 4c8x8i
m2ci 4m7c9x8i
9c9x9i i
i 9m9c9x8i
m i
i m
m9i i
9m8c7xi c2x8i

出力:

3x
x
6cx
5m9c9x9i
m
9m9c9x9i
mi
mi
mx
9m9c9x9i