RosettaCodeData/Task/Roman-numerals-Decode/Haskell/roman-numerals-decode-1.hs
2023-07-01 13:44:08 -04:00

45 lines
1.2 KiB
Haskell

module Main where
------------------------
-- DECODER FUNCTION --
------------------------
decodeDigit :: Char -> Int
decodeDigit 'I' = 1
decodeDigit 'V' = 5
decodeDigit 'X' = 10
decodeDigit 'L' = 50
decodeDigit 'C' = 100
decodeDigit 'D' = 500
decodeDigit 'M' = 1000
decodeDigit _ = error "invalid digit"
-- We process a Roman numeral from right to left, digit by digit, adding the value.
-- If a digit is lower than the previous then its value is negative.
-- The first digit is always positive.
decode roman = decodeRoman startValue startValue rest
where
(first:rest) = reverse roman
startValue = decodeDigit first
decodeRoman :: Int -> Int -> [Char] -> Int
decodeRoman lastSum _ [] = lastSum
decodeRoman lastSum lastValue (digit:rest) = decodeRoman updatedSum digitValue rest
where
digitValue = decodeDigit digit
updatedSum = (if digitValue < lastValue then (-) else (+)) lastSum digitValue
------------------
-- TEST SUITE --
------------------
main = do
test "MCMXC" 1990
test "MMVIII" 2008
test "MDCLXVI" 1666
test roman expected = putStrLn (roman ++ " = " ++ (show (arabic)) ++ remark)
where
arabic = decode roman
remark = " (" ++ (if arabic == expected then "PASS" else ("FAIL, expected " ++ (show expected))) ++ ")"