Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactored Haskell solutions to no longer need the CodeJam module.

With some more experience, I've found that the CodeJam module is not
really necessary, so I refactored the Haskell solutions (with heavy
commentary) to make them easier to understand and, in some cases,
shorter.
  • Loading branch information...
commit a79f028c1e0cade6a69c791266d08cfd1915bda4 1 parent e0debcc
Damien Radtke authored
View
54 alien-language/alien-language.hs
@@ -1,25 +1,38 @@
-{-# OPTIONS_GHC -i.. #-}
-
{-
- URL: http://code.google.com/codejam/contest/90101/dashboard#s=p0
-}
-import CodeJam
-
+import Control.Monad
type Pattern = [String]
main = do
- input <- fmap lines getContents
- let (l:d:n:_) = map read $ words $ head input :: [Int]
- let (knownWords,patterns) = splitAt d $ tail input
- let input = map (:[]) patterns
- codeJam (solve knownWords) input
-
-solve :: Input -> Input -> String
-solve knownWords patterns = show $ foldl f 0 knownWords
- where pattern = convertPattern $ head patterns
- f acc word = if word `isMatch` pattern then acc + 1 else acc
-
+ -- Read the first three variables: L (word length),
+ -- D (number of known words), and N (number of test cases)
+ (l:d:n:_) <- readIntList
+
+ -- Read in the next D lines, which contain the known words
+ knownWords <- getLines d
+
+ -- Solve
+ mapM (solve knownWords) [1..n]
+
+-- Solve the problem, given a list of known words and the case number
+solve :: [String] -> Int -> IO ()
+solve knownWords i = do
+ -- Read in the pattern and convert it
+ pattern <- liftM convertPattern getLine
+
+ -- Iterate over the known words, comparing the pattern to each one
+ let ans = countMatches knownWords pattern
+ putStrLn $ "Case #" ++ show i ++ ": " ++ show ans
+
+-- Count the number of known words that match the pattern
+countMatches :: [String] -> Pattern -> Int
+countMatches knownWords pattern = foldl f 0 knownWords
+ where f acc word = if word `isMatch` pattern then acc+1 else acc
+
+-- Create a pattern from a string. Each element of a pattern is a list
+-- of characters that are valid in that position
convertPattern :: String -> Pattern
convertPattern [] = []
convertPattern p@(x:xs) =
@@ -27,12 +40,23 @@ convertPattern p@(x:xs) =
then let (a,b) = extractGroup p in a : convertPattern b
else [x] : convertPattern xs
+-- Extract a parenthetical group from a string, used for creating patterns
extractGroup :: String -> (String,String)
extractGroup pattern = (group,rest)
where pattern' = tail pattern
group = takeWhile (\x -> [x] /= ")") pattern'
rest = drop (length group + 1) pattern'
+-- Returns true if the string matches the pattern
isMatch :: String -> Pattern -> Bool
isMatch [] _ = True
isMatch (x:xs) (y:ys) = if x `elem` y then isMatch xs ys else False
+
+-- Read a list of Int's from standard input
+readIntList :: IO [Int]
+readIntList = getLine >>= \l -> return (fmap read $ words l)
+
+-- Get the next n lines from standard input
+getLines :: Int -> IO [String]
+getLines n = foldM f [] [1..n]
+ where f l _ = getLine >>= \x -> return $ x:l
View
46 minimum-scalar/minimum-scalar.hs
@@ -1,25 +1,39 @@
-{-# OPTIONS_GHC -i.. #-}
-
{-
- URL: http://code.google.com/codejam/contest/32016/dashboard#s=p0
-}
-import CodeJam
+import Control.Monad
import Data.List
-main :: IO ()
-main = codeJam' solve
+-- Read in the number of cases and call 'solve' for each one
+main = readLn >>= \n -> mapM solve [1..n]
-solve :: Input -> String
-solve input = show result
- where (l1:l2:l3:_) = input
- n = read l1 :: Int
- v1 = parseVector l2 n
- v2 = parseVector l3 n
- result = scalar (sort v1) (reverse $ sort v2)
+-- Solve a case, passing in the case number
+solve :: Int -> IO ()
+solve i = do
+ -- Read in the number of items per vector. Not used,
+ -- but we need to read it in order to get past it
+ readLn :: IO (Int)
+
+ -- Read each vector in as a list of Ints, then sort the
+ -- first one and reverse-sort the second one
+ v1 <- readIntList >>= \l -> return (sort l)
+ v2 <- readIntList >>= \l -> return (reverse $ sort l)
+
+ -- Calculate the scalar
+ let result = scalar v1 v2
+
+ -- Display the result
+ putStrLn $ "Case #" ++ show i ++ ": " ++ show result
-parseVector :: String -> Int -> [Integer]
-parseVector line n = map read $ take n $ (words line) :: [Integer]
+-- Read a list of Int's from standard input
+readIntList :: IO [Int]
+readIntList = getLine >>= \l -> return (fmap read $ words l)
-scalar :: [Integer] -> [Integer] -> Integer
-scalar v1 v2 = sum $ zipWith (*) v1 v2 :: Integer
+-- Calculate the scalar value of two vectors. The input vectors
+-- are first converted from [Int] to [Integer] to prevent potential
+-- overflows
+scalar :: [Int] -> [Int] -> Integer
+scalar v1 v2 = sum $ zipWith (*) v1' v2'
+ where v1' = map toInteger v1
+ v2' = map toInteger v2
View
21 reverse-words/reverse-words.hs
@@ -1,10 +1,21 @@
-{-# OPTIONS_GHC -i.. #-}
-
{-
- URL: http://code.google.com/codejam/contest/dashboard?c=351101#s=p1
-}
-import CodeJam
+import Control.Monad
-main :: IO ()
-main = codeJam' (\input -> unwords.reverse.words $ head input)
+-- Read in the number of cases and call 'solve' for each one
+main = readLn >>= \n -> mapM solve [1..n]
+
+-- Solve a case, passing in the case number
+solve :: Int -> IO ()
+solve i = do
+ -- Read in the next line
+ line <- getLine
+
+ -- Convert the line to a list of words, reverse it, then
+ -- convert it back to a string
+ let ans = (unwords.reverse.words) line
+
+ -- Print the answer
+ putStrLn $ "Case #" ++ show i ++ ": " ++ ans
View
60 store-credit/store-credit.hs
@@ -1,27 +1,33 @@
-{-# OPTIONS_GHC -i.. #-}
-
-{-
- - URL: http://code.google.com/codejam/contest/351101/dashboard#s=p0
- -}
-
-import CodeJam
-
-data Item = Item { index :: Int, price :: Int }
-
-instance Show Item where
- show (Item index price) = show index
-
-main :: IO ()
-main = codeJam' solve
-
-solve :: Input -> String
-solve input = (show res1) ++ " " ++ (show res2)
- where (l1:l2:l3:_) = input
- credit = read l1 :: Int
- items = read l2 :: Int
- prices = map read $ take items $ (words l3) :: [Int]
- itemlist = zipWith Item [1..] prices
- options = [(item1,item2) | item1 <- itemlist, item2 <- itemlist,
- (index item1) < (index item2),
- (price item1) + (price item2) == credit]
- (res1,res2) = head options
+{-
+ - URL: http://code.google.com/codejam/contest/351101/dashboard#s=p0
+ -}
+
+import Control.Monad
+
+-- Read in the number of cases and call 'solve' for each one
+main = readLn >>= \n -> mapM solve [1..n]
+
+-- Solve a case, passing in the case number
+solve :: Int -> IO ()
+solve i = do
+ -- Read in the variables for this case
+ credit <- readLn :: IO (Int)
+ items <- readLn :: IO (Int)
+ prices <- readIntList
+
+ -- Create a list of item tuples, which associates index with price
+ let itemList = zip [1..] prices
+
+ -- Use a list comprehension to find all item pairs whose prices
+ -- add up to the available credit. Since we know there will be
+ -- one and only one, we can take the head of the list and extract
+ -- the indices of each item
+ let ((j,_),(k,_)) = head $ [(a,b) | a <- itemList, b <- itemList,
+ (fst a) < (fst b), (snd a) + (snd b) == credit]
+
+ -- Display the result
+ putStrLn $ "Case #" ++ show i ++ ": " ++ show j ++ " " ++ show k
+
+-- Read a list of Int's from standard input
+readIntList :: IO [Int]
+readIntList = getLine >>= \l -> return (fmap read $ words l)
Please sign in to comment.
Something went wrong with that request. Please try again.