RPN.hs
module Main where
import System.Environment (getArgs)
import Control.Applicative
data RPValue = Number Int | Plus | Minus | Multiply | Divide deriving (Eq, Show)
data Frak = F Int Int deriving (Eq)
instance Show Frak where
show (F n 0) = "NaN"
show (F n 1) = show n
show (F n m) = show n ++ "/" ++ show m
type Stack = [Frak]
reduce (F 0 0) = F 0 0
reduce (F n m) = F (div n (gcd n m)) (div m (gcd n m))
plus (F n m) (F a b) = reduce $ F (n*b+a*m) (m*b)
minus (F n m) (F a b) = reduce $ F (n*b-a*m) (m*b)
multiply (F n m) (F a b) = reduce $ F (n*a) (m*b)
divide (F n m) (F a 0) = F 0 0
divide (F n m) (F a b) = reduce $ F (n*b) (m*a)
process :: Stack -> RPValue -> Stack
process (x:y:xs) Plus = (plus y x):xs
process (x:y:xs) Minus = (minus y x):xs
process (x:y:xs) Multiply = (multiply y x):xs
process (x:y:xs) Divide = (divide y x):xs
process xs (Number n) = (F n 1):xs
parse :: String -> [RPValue]
parse = map parse' . words
where
parse' "+" = Plus
parse' "-" = Minus
parse' "*" = Multiply
parse' "/" = Divide
parse' str = Number (read str)
calc :: String -> Stack
calc str = foldl process [] (parse str)
main = mapM_ print =<< calc.head <$> getArgs
> ./RPN " 12 7 + 5 6 * / 7 8 + 19 2 * / - 20 3 + 11 /"
23/11
68/285
> ./RPN " 12 0 / 1 3 / +"
NaN