never executed always true always false
    1 {-|
    2 Module:      Y2016.D01
    3 Description: Advent of Code Day 01 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the day 01 set of problems for <adventofcode.com>.
    8 -}
    9 module Y2016.D01
   10   ( blockDistance
   11   , visitedTwice
   12   ) where
   13 
   14 import Data.List (foldl')
   15 import qualified Data.Set as Set
   16 
   17 -- | Cardinal direction for movement
   18 data Direction
   19   = North
   20   | East
   21   | South
   22   | West
   23   deriving (Enum)
   24 
   25 -- | (x, y) coordinates
   26 type Coordinates = (Int, Int)
   27 
   28 -- | Find number of blocks traveled per list of instructions
   29 blockDistance
   30   :: String -- ^ Input of directions
   31   -> Int -- ^ Number of blocks traveled
   32 blockDistance = blocks . foldl' travel (0, 0) . mapRoute
   33 
   34 -- | Find first block that is visited twice
   35 visitedTwice
   36   :: String -- ^ Input of directions
   37   -> Maybe Int -- ^ Possible block that is visited twice
   38 visitedTwice = navigate (0, 0) Set.empty . mapRoute
   39   where
   40     navigate point set (path:xs)
   41       | Set.member point' set = Just $ blocks point'
   42       | otherwise = navigate point' (Set.insert point' set) xs
   43       where
   44         point' = travel point path
   45     navigate _ _ _ = Nothing
   46 
   47 -- | Translate an input string into a list of movement `Direction`s
   48 mapRoute
   49   :: String -- ^ Input string
   50   -> [Direction] -- ^ List of `Direction`s
   51 mapRoute = toRoute North . map (toPath . filter (not . (==) ',')) . words
   52   where
   53     toRoute orientation ((lr, distance):xs) =
   54       replicate distance orientation' ++ toRoute orientation' xs
   55       where
   56         orientation' = turn lr orientation
   57     toRoute _ [] = []
   58 
   59 -- | Calculate the number of blocks from the origin
   60 blocks
   61   :: Coordinates -- ^ Current `Coordinates`
   62   -> Int -- ^ Number of blocks that `Coordinate` lies from the origin
   63 blocks (x, y) = abs x + abs y
   64 
   65 -- | Move along a given direction
   66 travel
   67   :: Coordinates -- ^ Initial `Coordinates`
   68   -> Direction -- ^ `Direction` to move towards
   69   -> Coordinates -- ^ New `Coordinates`
   70 travel (x, y) d =
   71   case d of
   72     North -> (x, succ y)
   73     East -> (succ x, y)
   74     South -> (x, pred y)
   75     West -> (pred x, y)
   76 
   77 -- | Translate a movement instruction to an intermediate form
   78 toPath
   79   :: String -- ^ Raw input instruction
   80   -> (Char, Int) -- ^ `Tuple` consisting of movement direction and
   81                  -- ^ distance
   82 toPath (direction:steps) = (direction, read steps)
   83 toPath [] = (' ', 0)
   84 
   85 -- | Determine new direction after turning Left or Right
   86 turn
   87   :: Char -- ^ 'L'eft or 'R'right
   88   -> Direction -- ^ Initial `Direction`
   89   -> Direction -- ^ New `Direction`
   90 turn 'R' West = North
   91 turn 'L' North = West
   92 turn 'R' d = succ d
   93 turn 'L' d = pred d
   94 turn _ d = d