aboutsummaryrefslogtreecommitdiff
path: root/2020/12b.hs
blob: 040287e1dec9c28924e7ae88b977b17d46a020dc (plain)
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
63
64
65
66
67
module Day12B 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);

-- ((shipX, shipY), (wY, wX))
type State = ((Int, Int), (Int, Int));

initialState :: State;
initialState = ((0, 0), (10, 1));

rotateAround :: (Int, Int) -> Int -> (Int, Int)
rotateAround (wx, wy) (-90) = (-wy, wx)
rotateAround (wx, wy) 0 = (wx, wy)
rotateAround (wx, wy) 90 = (wy, -wx)
rotateAround (wx, wy) 180 = (-wx, -wy)
rotateAround (wx, wy) (-180) = rotateAround (wx, wy) 180
rotateAround (wx, wy) 270 = rotateAround (wx, wy) (-90)
rotateAround (wx, wy) (-270) = rotateAround (wx, wy) 90
rotateAround _ _ = error "Direction not defined"

moveToward :: (Int, Int) -> (Int, Int) -> Int -> (Int, Int)
moveToward (sx, sy) (wx, wy) r = (sx + (wx * r), sy + (wy * r))

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) ((sx, sy), (wx, wy)) = ((sx, sy), (wx, wy + r))
doInstruction (South r) ((sx, sy), (wx, wy)) = ((sx, sy), (wx, wy - r))
doInstruction (East r) ((sx, sy), (wx, wy)) = ((sx, sy), (wx + r, wy))
doInstruction (West r) ((sx, sy), (wx, wy)) = ((sx, sy), (wx - r, wy))
doInstruction (TLeft r) ((sx, sy), (wx, wy)) = ((sx, sy), rotateAround (wx, wy) (-r))
doInstruction (TRight r) ((sx, sy), (wx, wy)) = ((sx, sy), rotateAround (wx, wy) r)
doInstruction (Forward r) ((sx, sy), (wx, wy)) = (moveToward (sx, sy) (wx, wy) r, (wx, wy))

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 ();