module Euler.Roman (
	roman, unroman
) where

import Data.Word

roman :: Word64 -> String
roman 1000 = "M"
roman 900  = "CM"
roman 500  = "D"
roman 400  = "CD"
roman 100  = "C"
roman 90   = "XC"
roman 50   = "L"
roman 40   = "XL"
roman 10   = "X"
roman 9    = "IX"
roman 5    = "V"
roman 4    = "IV"
roman 1    = "I"
roman x
	| x > 1000  = 'M' :       roman (x - 1000)
	| x > 900   = 'C' : 'M' : roman (x - 900)
	| x > 500   = 'D' :       roman (x - 500)
	| x > 400   = 'C' : 'M' : roman (x - 400)
	| x > 100   = 'C' :       roman (x - 100)
	| x > 90    = 'C' : 'M' : roman (x - 90)
	| x > 50    = 'L' :       roman (x - 50)
	| x > 40    = 'X' : 'L' : roman (x - 40)
	| x > 10    = 'X' :       roman (x - 10)
	| x > 9     = 'I' : 'X' : roman (x - 9)
	| x > 5     = 'V' :       roman (x - 5)
	| x > 4     = 'I' : 'V' : roman (x - 4)
	| otherwise = 'I' :       roman (x - 1)

unroman :: String -> Word64
unroman [] = 0
unroman ('M' : x)       = 1000 + unroman x
unroman ('C' : 'M' : x) = 900  + unroman x
unroman ('D' : x)       = 500  + unroman x
unroman ('C' : 'D' : x) = 400  + unroman x
unroman ('C' : x)       = 100  + unroman x
unroman ('X' : 'C' : x) = 90   + unroman x
unroman ('L' : x)       = 50   + unroman x
unroman ('X' : 'L' : x) = 40   + unroman x
unroman ('X' : x)       = 10   + unroman x
unroman ('I' : 'X' : x) = 9    + unroman x
unroman ('V' : x)       = 5    + unroman x
unroman ('I' : 'V' : x) = 4    + unroman x
unroman ('I' : x)       = 1    + unroman x
unroman _ = error "unroman: invalid numeral"
