-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNavigation.hs
78 lines (60 loc) · 2.31 KB
/
Navigation.hs
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
68
69
70
71
72
73
74
75
76
77
78
module Navigation where
import Control.Applicative
import Text.Trifecta
navigateDistance :: String -> Integer
navigateDistance s = let inst = parseString parseInstructions mempty s
in
case inst of
Failure _ -> 0
Success inst -> distance $
foldl move initState inst
newtype Direction a = Direction (a, a)
deriving Show
instance Functor Direction where
fmap f (Direction (x, y)) = Direction (f x, f y)
newtype Position = Position (Integer, Integer)
newtype Distance = Distance Integer
deriving Show
data Turn = LeftTurn | RightTurn
deriving Show
data Instruction = Instruction Turn Distance
deriving Show
data State = State (Direction Integer) Position
distance :: State -> Integer
distance (State _ (Position (x, y))) = (abs x) + (abs y)
initState :: State
initState = State (Direction (0, 1)) (Position (0, 0))
move :: State -> Instruction -> State
move (State dir (Position (x, y))) (Instruction t (Distance dist)) =
let newD = turn t dir
Direction (newx, newy) = (*dist) <$> dir
newPos = Position (x + newx, y + newy)
in State newD newPos
turn :: Turn -> Direction Integer -> Direction Integer
turn RightTurn (Direction (1, _)) = Direction (0, -1)
turn RightTurn (Direction (-1, _)) = Direction (0, 1)
turn RightTurn (Direction (_, 1)) = Direction (1, 0)
turn RightTurn (Direction (_, -1)) = Direction (-1, 0)
turn LeftTurn (Direction (1, _)) = Direction (0, 11)
turn LeftTurn (Direction (-1, _)) = Direction (0, -11)
turn LeftTurn (Direction (_, 1)) = Direction (-1, 0)
turn LeftTurn (Direction (_, -1)) = Direction (1, 0)
parseInstructions :: Parser [Instruction]
parseInstructions = do
first <- parseInstruction
rest <- some parseNextInstruction
return $ first : rest
parseInstruction :: Parser Instruction
parseInstruction = do
turn <- parseTurn
dist <- parseDist
return $ Instruction turn dist
parseNextInstruction :: Parser Instruction
parseNextInstruction = do
_ <- string ", "
parseInstruction
parseTurn :: Parser Turn
parseTurn = (char 'R' >>= \_ -> return RightTurn)
<|> (char 'L' >>= \_ -> return LeftTurn)
parseDist :: Parser Distance
parseDist = decimal >>= \d -> return $ Distance d