{-# OPTIONS -funbox-strict-fields #-} import System.IO import Data.Array.IO import Data.Array.Base import Data.Word import Data.Int import List import Char main = fileIterate stdin wc' (C 0 0 0 False) >>= putStrLn . showC data C = C !Int !Int !Int !Bool deriving Show -- Line Word Char InWord showC (C l w c _) = show l ++ " " ++ show w ++ " " ++ show c wc' :: C -> Char -> C wc' (C l w c _) '\n' = C (l+1) w (c+1) False wc' (C l w c _) ' ' = C l w (c+1) False wc' (C l w c _) '\t' = C l w (c+1) False wc' (C l w c False) _ = C l (w+1) (c+1) True wc' (C l w c True) _ = C l w (c+1) True -------------------------------------------------------------------------------- {-# INLINE fileIterate #-} fileIterate :: Handle -> (a -> Char -> a) -> a -> IO a fileIterate h f a0 = do buf <- newArray_ (0, bufSize - 1) :: IO (IOUArray Int Word8) let loop i n a | i `seq` n `seq` a `seq` False = undefined | i == n = do n' <- hGetArray h buf bufSize if n' == 0 then return a else loop 0 n' a | otherwise = do c <- fmap (toEnum . fromEnum) (readArray buf i) loop (i + 1) n (f a c) loop 0 0 a0 where bufSize :: Int bufSize = 4096