packages feed

GoogleCodeJam (empty) → 0.0.1

raw patch · 3 files changed

+172/−0 lines, 3 filesdep +arraydep +basedep +containers

Dependencies added: array, base, containers, mtl, parallel, safe, split, transformers

Files

+ GCJ.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE+ScopedTypeVariables+,Rank2Types+,GeneralizedNewtypeDeriving+ #-}+{-# OPTIONS_HADDOCK ignore-exports #-}++-- | This defines a Google Code Jam monad with a handful of combinators for simple parsing of input files.+--+-- The test cases are solved in parallel.+--+-- Although the parsing of the input cannot happen in parallel+-- (lines are consumed one by one, and input of the nexta example+-- depends on how much the current has consumed), the actual work can be+-- automatically parallelized, if the number of lines to consume does+-- not depend on the result of the main workload of each case.+--+-- This is demonstrated by the following example:+--+-- @+-- parallel test+-- mainP = mainId $ do+--        r <- return . length . show . product . enumFromTo (1::Integer) . read =<< cLine+--        if not parallel && r == 1 then return =<< cLine else return $ show r  +--        where parallel = False+-- @+--+-- input file:+--+-- @+-- 2+-- 200000+-- 200000+-- 200000+-- 200000+-- @++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++-- | data type for Google Code Jam Solution Program+--+-- It has to be a Monad (e.g. to implement cBlock).+--+-- Next action has to be able to depend on state.+newtype GCJ m a = GCJ { fromGCJ :: (StateT [String] m a) }+                deriving (Functor,Applicative,Monad,MonadIO,MonadTrans)++-- * Combinators       +  +-- | consumes and returns one line+cLine :: Monad m => GCJ m String+cLine = GCJ $ do x <- get+                 put $ tail x+                 return $ headNote "GCJ: No input lines left to consume" x++-- | consumes and returns n lines+cLines :: Monad m => Int -> GCJ m [String]+cLines n = sequence $ take n $ repeat cLine++-- | consumes, transforms and returns next block:+--+-- a block consists of first line: n, then (n-m) lines+cBlock :: Monad m => Int -> ([String] -> a) -> GCJ m (Int,a)+cBlock m f = do n <-  liftM read cLine+                return . (,) n . f =<< cLines (n-m) +++-- * Runners+type Runner m = GCJ m String -> [String] -> IO ()+             +-- | produce main from pure function+mainId :: Runner Identity+mainId = mainM $ return.runIdentity++-- | produce main from with transformed IO monad+mainIO :: Runner IO+mainIO = mainM $ id+                         +-- | produce main from Monad+--+-- reads testInput or the file given on the command line+--+-- writes to standard out and to the given file with '.out' appended+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)+  
+ GoogleCodeJam.cabal view
@@ -0,0 +1,31 @@+name: GoogleCodeJam+version: 0.0.1+cabal-version: >=1.10+build-type: Simple+license: MIT+license-file: LICENSE+maintainer: Johannes Gerer <oss@johannesgerer.com>+stability: Experimental+homepage: http://johannesgerer.com/GoogleCodeJam+bug-reports: http://github.com/johannesgerer/GoogleCodeJam/issues+synopsis: A monad for flexible parsing of Google Code Jam input files with automatic parallelization.+description:+    For more (including usage examples and solutions to GCJ problems) see <https://github.com/johannesgerer/buchhaltung Readme> on Github.+category: Text+author: Johannes Gerer++library+    exposed-modules:+        GCJ+    build-depends:+        base >=4.9.0.0 && <4.10,+        transformers >=0.5.2.0 && <0.6,+        safe >=0.3.10 && <0.4,+        split >=0.2.3.1 && <0.3,+        mtl >=2.2.1 && <2.3,+        parallel >=3.2.1.0 && <3.3,+        containers >=0.5.5.1 && <0.6,+        array >=0.5.0.0 && <0.6+    default-language: Haskell2010+    ghc-options: -O2+
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2017 Johannes Gerer++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.