第13回Ruby勉強会@関西の演習課題をHaskellで解いてみました。そのに
id:ha-tan:20061218:1166371729の続きで整数をローマ数字の文字列に変換する関数を書いてみました。解答例のRubyのプログラムも結構いけてました。そのまま移植しても徳の高いHaskellのプログラムになりました。
module Main (main) where import System (getArgs) import System.IO (hPutStr, stderr) oldRomanUnit :: [(Int, String)] oldRomanUnit = zip [1000, 500, 100, 50, 10, 5, 1] ["M", "D", "C", "L", "X", "V", "I"] romanUnit :: [(Int, String)] romanUnit = zip [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"] showRoman' :: [(Int, String)] -> Int -> String showRoman' [] _ = [] showRoman' ((d, s) : xs) n = (concat $ replicate d' s) ++ showRoman' xs n' where (d', n') = n `divMod` d showOldRoman :: Int -> String showOldRoman = showRoman' oldRomanUnit showRoman :: Int -> String showRoman = showRoman' romanUnit main :: IO () main = do args <- getArgs case args of ("-o" : xs) -> mapM_ (print . showOldRoman . read) xs ("-n" : xs) -> mapM_ (print . showRoman . read) xs _ -> usage where usage = hPutStr stderr $ "usage: roman [OPTION] numbers...\n" ++ "\t-o old style.\n" ++ "\t-n new style.\n"
実行例:
$ ./roman.exe -o 1654 "MDCLIIII" $ ./roman.exe -n 1654 "MDCLIV"
BUGS: showRomanで最短の文字列が返るとは限りません(999を与えても"IM"になりません。"CMXCIX"になります)。