diff --git a/Code/Competition.hs b/Code/Competition.hs
new file mode 100644
--- /dev/null
+++ b/Code/Competition.hs
@@ -0,0 +1,70 @@
+module Code.Competition (
+  Solveable(..), Parseable(..), runCompetition, runSolution, runWriteSolution
+) where
+
+-- getArgs
+import System.Environment (getArgs)
+import System.FilePath (replaceExtension)
+
+-- Parsing
+import Text.ParserCombinators.Parsec (parse, ParseError, GenParser)
+import Code.Competition.Parsers (probfile)
+
+------------------------
+-- Type Classes
+------------------------
+
+-- Solveable denotes any type that represents a solveable problem
+class (Show a) => Solveable p a where
+  solve :: p -> a
+
+class Parseable p where
+  problem :: GenParser Char st p
+
+------------------------
+-- parsers
+------------------------
+
+parseProblemFile :: Parseable p => String -> Either ParseError [p]
+parseProblemFile input = parse (probfile problem) "(unknown)" input
+
+------------------------
+-- Main and IO
+------------------------
+
+runCompetition :: (Solveable p a, Parseable p, Show p) => IO [(p, a)]
+runCompetition = do
+  args <- getArgs
+  inputFn <- return $ head args
+  let outputFn = if length args >= 2 then (args !! 1) else (replaceExtension inputFn ".out")
+  (output, probans) <- runWriteSolution inputFn outputFn
+  putStr output
+  return probans
+
+runSolution :: (Solveable p a, Parseable p, Show p) => String -> IO (String, [(p, a)])
+runSolution inputFn = do
+  input <- readFile inputFn
+  problems <- case parseProblemFile input of
+    Left pe -> handleParseError pe
+    Right xs -> return xs
+  answers <- return $ map solve problems
+  output <- return $ (unlines . caseify) answers
+  return (output, zip problems answers)
+
+runWriteSolution :: (Solveable p a, Parseable p, Show p) => String -> String -> IO (String, [(p, a)])
+runWriteSolution inputFn outputFn = do
+  (output, probans) <- runSolution inputFn
+  writeFile outputFn output
+  return (output, probans)
+
+handleParseError :: Parseable p => ParseError -> IO [p]
+handleParseError err = do
+  putStrLn $ show err
+  return []
+
+------------------------
+-- Helpers
+------------------------
+
+caseify :: Show a => [a] -> [String]
+caseify as = map (\(i,a) -> "Case #" ++ (show i) ++ ": " ++ (show a)) (zip [1..] as)
diff --git a/Code/Competition/Parsers.hs b/Code/Competition/Parsers.hs
new file mode 100644
--- /dev/null
+++ b/Code/Competition/Parsers.hs
@@ -0,0 +1,84 @@
+module Code.Competition.Parsers (
+  probfile,
+  grid, nmgrid,
+  ints, intn, int,
+  floats, floatn, float,
+  andSpace,
+  eol
+) where
+
+
+-- Parsing
+import Text.ParserCombinators.Parsec (GenParser, count, char, space, digit, many, eof)
+
+------------------------
+-- A grid of n rows and m columns (no spaces separated)
+------------------------
+
+grid :: Int -> Int -> GenParser Char st a -> GenParser Char st [[a]]
+grid n m p = count n pline
+  where
+    pline = do
+      ret <- count m p
+      eol
+      return ret
+
+-- A grid with n and m at the top
+nmgrid :: GenParser Char st a -> GenParser Char st [[a]]
+nmgrid p = do
+  [n,m] <- intn 2
+  grid n m p
+
+------------------------
+-- A whole problem file
+------------------------
+
+probfile :: GenParser Char st prob -> GenParser Char st [prob]
+probfile probparse = do
+  [t] <- intn 1
+  probs <- count t probparse
+  eof
+  return probs
+
+------------------------
+-- Ints
+------------------------
+
+ints :: GenParser Char st [Int]
+ints = many (andSpace int)
+
+intn :: Int -> GenParser Char st [Int]
+intn n = count n (andSpace int)
+
+int :: GenParser Char st Int
+int = do
+  tokens <- many digit
+  return $ read tokens
+
+------------------------
+-- Floats
+------------------------
+
+floats :: GenParser Char st [Int]
+floats = many (andSpace int)
+
+floatn :: Int -> GenParser Char st [Float]
+floatn n = count n (andSpace float)
+
+float :: GenParser Char st Float
+float = do
+  predot <- many digit
+  char '.'
+  postdot <- many digit
+  return $ read (predot ++ "." ++ postdot)
+
+-- Helpers
+
+eol :: GenParser Char st Char
+eol = char '\n'
+
+andSpace :: GenParser Char st a -> GenParser Char st a
+andSpace ap = do
+  a <- ap
+  space
+  return a
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Metric Feat LLC
+
+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.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/competition.cabal b/competition.cabal
new file mode 100644
--- /dev/null
+++ b/competition.cabal
@@ -0,0 +1,26 @@
+-- Initial competition.cabal generated by cabal init.  For further
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                competition
+version:             0.2.0.0
+synopsis:            Helpers and runners for code competitions
+-- description:
+homepage:            github.com/yanatan16/haskell-competition
+license:             MIT
+license-file:        LICENSE
+author:              Jon Eisen
+maintainer:          jon@joneisen.me
+-- copyright:
+category:            Code Competitions
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules: Code.Competition, Code.Competition.Parsers
+
+  extensions: MultiParamTypeClasses
+
+  -- other-modules:
+  build-depends: base < 5,
+                 filepath >= 1,
+                 parsec ==3.1.5
