Day 1: No Time for a Taxicab


In [1]:
import Data.List.Split

In [2]:
inputLine = head <$> lines <$> readFile "input/day1.txt"

Transform the input line to a list of instructions


In [3]:
instructions = splitOn "," . filter (/= ' ') <$> inputLine
take 5 <$> instructions -- just to see if it works


["R4","R1","L2","R1","L1"]

We encode the direction of the step in a tuple of two Int values:

(0, 1) : North

(1, 0) : East

(0, -1) : South

(-1, 0) : West


In [4]:
-- Takes an initial direction and a list of instructions and returns a list of single-block steps
getSteps :: (Int, Int) -> [String] -> [(Int, Int)]
getSteps _ [] = []
getSteps direction (instruction:is) =
    replicate distance newDirection ++ getSteps newDirection is
        where    
            turn = head instruction -- L or R
            distance = read (tail instruction)

            evalTurn :: Char -> (Int, Int) -> (Int, Int)
            evalTurn 'L' (dx, dy) = (-dy, dx)
            evalTurn 'R' (dx, dy) = (dy, -dx)
        
            newDirection = evalTurn turn direction

In [5]:
-- Applies a single-block step to a given position and returns the new position
applyStep :: (Int, Int) -> (Int, Int) -> (Int, Int)
applyStep (x, y) (dx, dy) = (x + dx, y + dy)

In [6]:
-- Takes a list of steps and returns the final position if (0, 0) was the initial position
evalSteps = foldl applyStep (0, 0)

In [7]:
-- Manhattan distance from the origin
distanceFromOrigin :: (Int, Int) -> Int
distanceFromOrigin (x, y) = abs x + abs y

In [8]:
-- Solution of part 1
distanceFromOrigin . evalSteps . getSteps (0, 1) <$> instructions


161

In [9]:
import qualified Data.Set as Set

In [10]:
-- * Takes a list of steps
-- * Assumes that (0, 0) is the initial position
-- * Returns a list of tuples where:
--     * the first tuple element is the position
--     * the second tuple element is the set of positions that have been visited previously.

evalSteps' = scanl update ((0, 0), Set.empty)
    where
        update (position, alreadyVisited) step = (applyStep position step, position `Set.insert` alreadyVisited)

In [11]:
-- Solution of part 2
distanceFromOrigin . fst . head . filter (uncurry Set.member) . evalSteps' . getSteps (0, 1) <$> instructions


110