import Control.Monad import Data.Char import qualified Data.Map.Strict as Map import Data.Map.Strict ((!)) splitOn :: Eq a => a -> [a] -> [[a]] splitOn c xs = case break (== c) xs of (pre, []) -> [pre] (pre, _ : post) -> pre : splitOn c post strip :: String -> String strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse dirmap :: Map.Map String (Int, Int) dirmap = Map.fromList [("n", (0,2)), ("ne", (1,1)), ("se", (1,-1)), ("s", (0,-2)), ("sw", (-1,-1)), ("nw", (-1,1))] add :: (Int, Int) -> (Int, Int) -> (Int, Int) add (a,b) (c,d) = (a + c, b + d) distance :: (Int, Int) -> Int distance (0,0) = 0 distance (0,y) = abs y `div` 2 distance (x,0) = abs x distance (x,y) = let m = min (abs x) (abs y) in m + distance (x - m * signum x, y - m * signum y) main :: IO () main = do input <- liftM (map (dirmap !) . splitOn ',' . strip) (readFile "11.in") print $ distance $ foldl1 add input print $ maximum $ map distance $ scanl add (0,0) input