import System.IO import Data.Array.IO import Data.Array.Base (unsafeRead) import Data.Word import Char import List wc :: Handle -> IO (Int, Int, Int) wc h = do buf <- newArray_ (0, bufSize - 1) :: IO (IOUArray Int Word8) let wcLoop :: Char -> Int -> Int -> Int -> Int -> Int -> IO (Int, Int, Int) wcLoop prev nl nw nc i n | prev `seq` nl `seq` nw `seq` nc `seq` i `seq` n `seq` False = undefined | i == n = do n' <- hGetArray h buf bufSize if n' == 0 then return (nl, nw, nc) else wcLoop prev nl nw nc 0 n' | otherwise = do c <- fmap (toEnum . fromEnum) (unsafeRead buf i) wcLoop c (nl + if c == '\n' then 1 else 0) (nw + if not (isSpace c) && isSpace prev then 1 else 0) (nc + 1) (i + 1) n wcLoop ' ' 0 0 0 0 0 where bufSize :: Int bufSize = 8192 main = do (nl, nw, nc) <- wc stdin putStrLn $ concat $ intersperse " " $ map show [nl, nw, nc]