thoga31

Reverse Polish Notation Calculator

Aug 8th, 2013
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Reverse Polish Notation (v1.0.0, a newbie's script :D)
  2. import qualified Data.Char as C
  3.  
  4. rpn :: String -> String
  5. rpn expr = let res = calc [] $ words expr
  6.            in show $ (if length res == 1 then head else last) res
  7.     where
  8.         isOper = (`elem` ["+","-","*","/","^"])
  9.         isNum = all (== True) . map (C.isNumber)
  10.  
  11.         calc l [] | length l == 1 = l
  12.                   | otherwise     = ["There aren't sufficient operators."]
  13.         calc l (x:xs) | isOper x  = if length l >= 2
  14.                                        then if (x == "/") && (ultimate == 0)
  15.                                                 then ["Division by zero"]
  16.                                                 else calc (operate x) xs
  17.                                        else ["There aren't sufficient operands."]
  18.                       | isNum x   = calc (push x l) xs
  19.                       | otherwise = ["There are tokens which aren't numbers or operators."]
  20.             where
  21.                 operate "+" = push (show $ penultimate + ultimate) begin
  22.                 operate "-" = push (show $ penultimate - ultimate) begin
  23.                 operate "*" = push (show $ penultimate * ultimate) begin
  24.                 operate "/" = push (show $ penultimate / ultimate) begin
  25.                 operate "^" = push (show $ penultimate ^ (read $ show penultimate :: Int)) begin
  26.  
  27.                 begin = init $ init l
  28.                 ultimate = read $ last l :: Float  -- because we cannot use the identifier 'last', so it's similar to 'penultimate'
  29.                 penultimate = read (last $ init l) :: Float
  30.  
  31.                 push n = (++ [n])
  32.  
  33. -- INPUT BUG: power operator generates an error. Use the function directly and not this 'main' block.
  34. main :: IO()
  35. main = do
  36.     putStr ">> "
  37.     n <- (readLn :: IO String)
  38.     if (/= "EXIT") (map (C.toUpper) n)
  39.         then do
  40.             putStrLn $ "Result: " ++ (rpn n)
  41.             mainrpn
  42.         else putStrLn "End."
Advertisement
Add Comment
Please, Sign In to add comment