Skip to content

Instantly share code, notes, and snippets.

@bereal
Created March 18, 2019 08:23
Show Gist options
  • Save bereal/0012c434aa10c57b15559b05e4506f1c to your computer and use it in GitHub Desktop.
Save bereal/0012c434aa10c57b15559b05e4506f1c to your computer and use it in GitHub Desktop.
Conversion between Roman and decimals numbers
import System.Environment
import qualified Data.Map as M
import Data.Maybe
import Data.Char
letters = "MDCLXVI"
values = [1000, 500, 100, 50, 10, 5, 1]
-- convert in to Roman
toRoman n = concat $ convert (reverse letters) (coeffs values n []) []
where coeffs (v : vs) n buf = let (val, n') = divMod n v in coeffs vs n' (val:buf)
coeffs [] n buf = buf
convert (s1:(s2:ss@(s3:_))) (4:(1:(vs))) buf = convert ss vs ([s1, s3]:buf)
convert (s1:(s2:ss)) (4:(0:vs)) buf = convert ss vs ([s1, s2]:buf)
convert (s1:ss) (v1:vs) buf = convert ss vs ((replicate v1 s1):buf)
convert [] _ buf = buf
-- convert Roman to Int
parseRoman s =
let mapping = M.fromList $ zip letters values
convert = fromJust . (flip M.lookup mapping)
parsedDigits = (map convert s) in
sum $ parse parsedDigits []
where parse [] buf = buf
parse (x:y:xs) buf | x < y = parse xs ((y-x): buf)
parse (x:xs) buf = parse xs (x:buf)
convert s
| all (flip elem letters) s = show $ parseRoman s
| all isDigit s = toRoman $ read s
| otherwise = "error"
main = getArgs >>= putStrLn . convert . (map toUpper) . head
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment