60 lines
1.5 KiB
Haskell
60 lines
1.5 KiB
Haskell
module Main where
|
|
|
|
------------------------
|
|
-- ENCODER FUNCTION --
|
|
------------------------
|
|
|
|
romanDigits = "IVXLCDM"
|
|
|
|
-- Meaning and indices of the romanDigits sequence:
|
|
--
|
|
-- magnitude | 1 5 | index
|
|
-- -----------|-------|-------
|
|
-- 0 | I V | 0 1
|
|
-- 1 | X L | 2 3
|
|
-- 2 | C D | 4 5
|
|
-- 3 | M | 6
|
|
--
|
|
-- romanPatterns are index offsets into romanDigits,
|
|
-- from an index base of 2 * magnitude.
|
|
|
|
romanPattern 0 = [] -- empty string
|
|
romanPattern 1 = [0] -- I or X or C or M
|
|
romanPattern 2 = [0,0] -- II or XX...
|
|
romanPattern 3 = [0,0,0] -- III...
|
|
romanPattern 4 = [0,1] -- IV...
|
|
romanPattern 5 = [1] -- ...
|
|
romanPattern 6 = [1,0]
|
|
romanPattern 7 = [1,0,0]
|
|
romanPattern 8 = [1,0,0,0]
|
|
romanPattern 9 = [0,2]
|
|
|
|
encodeValue 0 _ = ""
|
|
encodeValue value magnitude = encodeValue rest (magnitude + 1) ++ digits
|
|
where
|
|
low = rem value 10 -- least significant digit (encoded now)
|
|
rest = div value 10 -- the other digits (to be encoded next)
|
|
indices = map addBase (romanPattern low)
|
|
addBase i = i + (2 * magnitude)
|
|
digits = map pickDigit indices
|
|
pickDigit i = romanDigits!!i
|
|
|
|
encode value = encodeValue value 0
|
|
|
|
------------------
|
|
-- TEST SUITE --
|
|
------------------
|
|
|
|
main = do
|
|
test "MCMXC" 1990
|
|
test "MMVIII" 2008
|
|
test "MDCLXVI" 1666
|
|
|
|
test expected value = putStrLn ((show value) ++ " = " ++ roman ++ remark)
|
|
where
|
|
roman = encode value
|
|
remark =
|
|
" (" ++
|
|
(if roman == expected then "PASS"
|
|
else ("FAIL, expected " ++ (show expected))) ++ ")"
|