Skip to content

Instantly share code, notes, and snippets.

@averyanov
Created Mar 9, 2010
Embed
What would you like to do?
module Main where
import Control.Monad
import Data.Char
data Expr = Expr Integer Char Integer [Integer]
deriving Show
digits :: String -> [Integer]
digits s = map (toInteger . digitToInt) s
readsExpr :: ReadS Expr
readsExpr s = do
(x, (op:ys)) <- reads s
(y, t2) <- reads ys
return ((Expr x op y (digits ys)), t2)
instance Read Expr where
readsPrec _ = readsExpr
operator :: Char -> Integer -> Integer -> Integer
operator '+' = (+)
operator '-' = (-)
operator '*' = (*)
linesExpr :: Expr -> [String]
linesExpr (Expr x '*' y yDigits@(d1:d2:ds) ) = let
fst = show x
snd = '*':(show y)
res = show (x*y)
mLines = mulLines 0 x (reverse yDigits)
(fstMLine:_) = mLines
line1Len = max (length snd) (length fstMLine)
line1 = replicate line1Len '-'
line2 = replicate (length res) '-'
in [fst, snd, line1] ++ mLines ++ [line2, res]
linesExpr (Expr x op y yDigits) = let
fst = show x
snd = op:(show y)
res = show ((operator op) x y)
lineLen = max (length snd) (length res)
line = replicate lineLen '-'
in [fst, snd, line, res]
mulLines :: Int -> Integer -> [Integer] -> [String]
mulLines _ _ [] = []
mulLines pad x (d:digits) =
( shows (x*d) (replicate pad ' ') ) : (mulLines (pad+1) x digits)
maxLen :: [String] -> Int
maxLen = maximum . (map length)
printLinesPad :: Int -> [String] -> IO ()
printLinesPad _ [] = do
return ()
printLinesPad len (x:xs) = do
putStr $ replicate (len - (length x)) ' '
putStrLn x
printLinesPad len xs
printExpr :: Expr -> IO()
printExpr expr = do
let lines = linesExpr expr
len = maxLen lines
in printLinesPad len lines
runTests :: Int -> IO()
runTests 0 = do
return ()
runTests n = do
expr <- liftM read getLine
printExpr expr
putStrLn ""
runTests (n-1)
main = do
n <- liftM read getLine
runTests n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment