public
Created — forked from petermarks/Automata.hs

Automata

  • Download Gist
Automata.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
module Automata where
 
import Prelude hiding (map, head, foldl, take)
import qualified Prelude as P
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C
import Data.ByteString.Internal (c2w)
import qualified Data.Map as M
import Data.List (sort)
import Data.Tuple
import System.Environment
import Data.Enumerator hiding (foldl)
import Data.Enumerator.List
import qualified Data.Enumerator.Binary as EB
 
-- Data Types
data Entry = Entry {
date :: BS.ByteString,
host :: BS.ByteString,
program :: BS.ByteString,
message :: BS.ByteString
} deriving Show
type Summary = M.Map BS.ByteString Int
 
-- Enumerator
filelines :: FilePath -> Enumerator BS.ByteString IO a
filelines fname = EB.enumFile fname $= EB.splitWhen (==(c2w '\n'))
 
-- Iteratees
count :: Monad m => Iteratee BS.ByteString m Int
count = (fold (flip $ const (+1)) 0)
 
summary :: Monad m => Iteratee BS.ByteString m Summary
summary = fold op M.empty
where op :: Summary -> BS.ByteString -> Summary
op sumMap line =
let e = parseEntry line
in M.insertWith' (+) (program e) 1 sumMap
 
-- Utils
parseEntry :: BS.ByteString -> Entry
parseEntry s = Entry d h p m
where d1:d2:d3:h:p':ms = C.words s
d = C.unwords [d1,d2,d3]
p = BS.init p'
m = C.unwords ms
top10 :: Summary -> [(Int, BS.ByteString)]
top10 = P.take 10 . P.reverse . sort . P.map swap . M.toList
 
processFile :: Enumerator BS.ByteString IO (Int, Summary) -> IO (Int, [(Int, BS.ByteString)])
processFile enum = do
(i, sum) <- run_ $ enum $$ EB.zip count summary
return (i, top10 sum)
 
main = do
fname <- getArgs >>= return . P.head
print =<< (processFile $ filelines fname)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.