module GCJ (
GCJ
,module Control.Applicative
,module Control.Monad
)
where
import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Identity
import Control.Monad.Trans.State.Lazy
import Control.Monad.Trans.Class
import Control.Parallel.Strategies
import Data.List
import Prelude
import Safe
import System.Environment
import System.IO
import Text.Printf
newtype GCJ m a = GCJ { fromGCJ :: (StateT [String] m a) }
deriving (Functor,Applicative,Monad,MonadIO,MonadTrans)
cLine :: Monad m => GCJ m String
cLine = GCJ $ do x <- get
put $ tail x
return $ headNote "GCJ: No input lines left to consume" x
cLines :: Monad m => Int -> GCJ m [String]
cLines n = sequence $ take n $ repeat cLine
cBlock :: Monad m => Int -> ([String] -> a) -> GCJ m (Int,a)
cBlock m f = do n <- liftM read cLine
return . (,) n . f =<< cLines (nm)
type Runner m = GCJ m String -> [String] -> IO ()
mainId :: Runner Identity
mainId = mainM $ return.runIdentity
mainIO :: Runner IO
mainIO = mainM $ id
mainM :: Monad m => (forall a. (m a -> IO a))
-> Runner m
mainM exec (GCJ gen) args = do
let cc [] = return ("test", return (), putStr)
cc (a:[]) = do h <- openFile (a++".out") WriteMode
return (a, hClose h, \x -> putStr x >> hPutStr h x)
(inF,close,myP) <- cc args
printf "Reading file: %s\n" inF
(head:tail) <- lines <$> readFile inF
let ncase = read head
printf "Found %d cases\n" ncase
(work,rest) <- (exec $ runStateT (replicateM ncase gen) tail)
zipWithM_ ((myP.).printf "Case #%u: %s") [(1::Int)..] $
parMap rdeepseq (\y -> y ++ if "\n" `isSuffixOf` y then "" else "\n") work
close >> when (length rest > 0)
(error $ "GCJ: not all input lines have been consumed:\n" ++ unlines rest)