diff options
| author | Gregor Kleen <gkleen@praseodym.org> | 2015-03-05 20:01:08 +0000 |
|---|---|---|
| committer | Gregor Kleen <gkleen@praseodym.org> | 2015-03-05 20:01:08 +0000 |
| commit | bd759f8dd5d70e266c0eae97d7076976cf2fc2a3 (patch) | |
| tree | 706ce8b1c5a780dd3528af950ffb10ab013eb997 | |
| parent | 7aa86b0a785cb428a7b54c606fd854ba87789503 (diff) | |
| download | gausshs-bd759f8dd5d70e266c0eae97d7076976cf2fc2a3.tar gausshs-bd759f8dd5d70e266c0eae97d7076976cf2fc2a3.tar.gz gausshs-bd759f8dd5d70e266c0eae97d7076976cf2fc2a3.tar.bz2 gausshs-bd759f8dd5d70e266c0eae97d7076976cf2fc2a3.tar.xz gausshs-bd759f8dd5d70e266c0eae97d7076976cf2fc2a3.zip | |
Variables & Symbol 'e'
| -rw-r--r-- | rpn.hs | 53 |
1 files changed, 49 insertions, 4 deletions
| @@ -1,8 +1,13 @@ | |||
| 1 | import Control.Monad (join, sequence) | 1 | import Control.Monad (join, sequence) |
| 2 | import System.Environment (getArgs) | 2 | import System.Environment (getArgs) |
| 3 | import Data.Maybe (listToMaybe, isJust) | ||
| 4 | import Data.Char (isSpace) | ||
| 5 | import Data.List (nub) | ||
| 3 | import qualified Control.Monad.State as S | 6 | import qualified Control.Monad.State as S |
| 7 | import qualified Data.Map as M | ||
| 8 | import System.IO | ||
| 4 | 9 | ||
| 5 | data Symbol a = Number a a | Err | Add | Sub | Mult | Div | Unc deriving (Eq, Ord, Show) | 10 | data Symbol a = Number a a | Err | Add | Sub | Mult | Div | Unc | Exp deriving (Eq, Ord, Show) |
| 6 | instance Floating a => Num (Symbol a) where | 11 | instance Floating a => Num (Symbol a) where |
| 7 | (Number x del) + (Number y del') = Number (x + y) (abs $ gMean [del, del']) | 12 | (Number x del) + (Number y del') = Number (x + y) (abs $ gMean [del, del']) |
| 8 | _ + _ = Err | 13 | _ + _ = Err |
| @@ -32,14 +37,47 @@ fromSymbol :: Floating a => Symbol a -> (a, a) | |||
| 32 | fromSymbol (Number x d) = (x, d) | 37 | fromSymbol (Number x d) = (x, d) |
| 33 | fromSymbol _ = (0, 0) | 38 | fromSymbol _ = (0, 0) |
| 34 | 39 | ||
| 40 | |||
| 41 | pPrint :: Show a => Symbol a -> String | ||
| 42 | pPrint (Number x d) = (show x) ++ " ± " ++ (show d) | ||
| 43 | pPrint s = show s | ||
| 44 | |||
| 35 | main :: IO () | 45 | main :: IO () |
| 36 | main = do | 46 | main = do |
| 37 | (mode:stdin:_) <- getArgs | 47 | hSetBuffering stdin LineBuffering |
| 38 | let symbols = map interpreteSymbol $ join $ map words . lines $ stdin | 48 | hSetBuffering stdout NoBuffering |
| 39 | result = evalExpVec symbols | 49 | (mode:args) <- getArgs |
| 50 | let symbols = join . join $ map (map words) . map lines $ args | ||
| 51 | unknownSymbols = nub $ filter (not . isKnownSymbol) symbols | ||
| 52 | symbolMap <- sequence $ map (sequencePair . (\x -> (x, clarifySymbol x))) unknownSymbols | ||
| 53 | let symbolMap' = M.fromList symbolMap | ||
| 54 | symbols' = map (\x -> if x `elem` (M.keys symbolMap') then symbolMap' M.! x else [x]) symbols | ||
| 55 | symbols'' = map interpreteSymbol $ join symbols' | ||
| 56 | let result = evalExpVec symbols'' | ||
| 40 | case mode of | 57 | case mode of |
| 41 | "n" -> putStrLn . show . fst $ fromSymbol result | 58 | "n" -> putStrLn . show . fst $ fromSymbol result |
| 42 | "e" -> putStrLn . show . snd $ fromSymbol result | 59 | "e" -> putStrLn . show . snd $ fromSymbol result |
| 60 | _ -> putStrLn $ pPrint result | ||
| 61 | |||
| 62 | clarifySymbol :: String -> IO [String] | ||
| 63 | clarifySymbol s = do | ||
| 64 | putStr $ "Define " ++ s ++ ": " | ||
| 65 | line <- getLine | ||
| 66 | return $ words line | ||
| 67 | |||
| 68 | isKnownSymbol :: String -> Bool | ||
| 69 | isKnownSymbol s = or [ | ||
| 70 | s `elem` ["+", "-", "*", "/", "±", "e"], | ||
| 71 | isJust $ (maybeRead s :: Maybe Double) | ||
| 72 | ] | ||
| 73 | |||
| 74 | sequencePair :: (a, IO b) -> IO (a, b) | ||
| 75 | sequencePair (a, b) = do | ||
| 76 | b' <- b | ||
| 77 | return (a, b') | ||
| 78 | |||
| 79 | maybeRead :: (Read a) => String -> Maybe a | ||
| 80 | maybeRead = fmap fst . listToMaybe . filter (null . dropWhile isSpace . snd) . reads | ||
| 43 | 81 | ||
| 44 | interpreteSymbol :: String -> Symbol Double | 82 | interpreteSymbol :: String -> Symbol Double |
| 45 | interpreteSymbol "+" = Add | 83 | interpreteSymbol "+" = Add |
| @@ -47,6 +85,7 @@ interpreteSymbol "-" = Sub | |||
| 47 | interpreteSymbol "*" = Mult | 85 | interpreteSymbol "*" = Mult |
| 48 | interpreteSymbol "/" = Div | 86 | interpreteSymbol "/" = Div |
| 49 | interpreteSymbol "±" = Unc | 87 | interpreteSymbol "±" = Unc |
| 88 | interpreteSymbol "e" = Exp | ||
| 50 | interpreteSymbol x = Number (read x) 0 | 89 | interpreteSymbol x = Number (read x) 0 |
| 51 | 90 | ||
| 52 | evalExpVec :: Floating a => [Symbol a] -> Symbol a | 91 | evalExpVec :: Floating a => [Symbol a] -> Symbol a |
| @@ -76,3 +115,9 @@ evalExp Mult = do | |||
| 76 | evalExp Div = do | 115 | evalExp Div = do |
| 77 | state <- S.get | 116 | state <- S.get |
| 78 | S.put $ ((foldl1 (/) . reverse $ take 2 state):drop 2 state) | 117 | S.put $ ((foldl1 (/) . reverse $ take 2 state):drop 2 state) |
| 118 | evalExp Exp = do | ||
| 119 | state <- S.get | ||
| 120 | let | ||
| 121 | b = state !! 1 | ||
| 122 | e = state !! 0 | ||
| 123 | S.put $ ((b * (Number (10 ** (fst $ fromSymbol e)) 0)):drop 2 state) | ||
