1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
module Day12A where
import System.Environment (getArgs)
data Instruction = North Int | East Int |
South Int | West Int |
TLeft Int | TRight Int |
Forward Int
deriving (Eq, Show, Ord);
-- ((x, y), direction)
type State = ((Int, Int), Int);
initialState :: State;
initialState = ((0, 0), 90);
directionToDisplacement :: Int -> (Int, Int)
directionToDisplacement 0 = (0, 1)
directionToDisplacement 90 = (1, 0)
directionToDisplacement 180 = (0, -1)
directionToDisplacement 270 = (-1, 0)
directionToDisplacement _ = error "Invalid direction"
readInstructions :: String -> [Instruction]
readInstructions = map readInstruction . lines
where readInstruction ('N':xs) = North $ read xs
readInstruction ('S':xs) = South $ read xs
readInstruction ('E':xs) = East $ read xs
readInstruction ('W':xs) = West $ read xs
readInstruction ('L':xs) = TLeft $ read xs
readInstruction ('R':xs) = TRight $ read xs
readInstruction ('F':xs) = Forward $ read xs
readInstruction _ = error "Invalid instruction"
doInstruction :: Instruction -> State -> State
doInstruction (North r) ((x, y), d) = ((x, y + r), d)
doInstruction (South r) ((x, y), d) = ((x, y - r), d)
doInstruction (East r) ((x, y), d) = ((x + r, y), d)
doInstruction (West r) ((x, y), d) = ((x - r, y), d)
doInstruction (TLeft r) ((x, y), d) = ((x, y), (d - r) `mod` 360)
doInstruction (TRight r) ((x, y), d) = ((x, y), (d + r) `mod` 360)
doInstruction (Forward r) ((x, y), d) = ((x + (x' * r), y + (y' * r)), d)
where (x', y') = directionToDisplacement d
instructionsFromFile :: String -> IO [Instruction]
instructionsFromFile s = do
contents <- readFile s;
return $ readInstructions contents;
main :: IO ()
main = do
args <- getArgs;
is <- instructionsFromFile (head args);
let final = foldl (flip doInstruction) initialState is;
putStrLn $ "Final State: " ++ show final;
let ((x, y), _) = final;
let dist = abs x + abs y;
putStrLn $ "Distance: " ++ show dist;
return ();
|