Day 12 - Easy, but so many mistakes
Sometimes you know you shouldn't do something but you do it anyway. Today I made that mistake on the assignment. It was a simple assignment we have a ship, with a direction (N,E,S,W) and a location on a grid. And some simple instructions on how to change the direction and location. My plan was to write a simple function that takes the current state (direction and location) and an instruction to return the new state. I would use pattern matching to write out each individual situation. It would be a solution with lots of duplication, but it would be fast to write. This was the result.
solve1 xs = abs (x + y) where
(dir, x, y) = foldl go ('E',0,0) xs
go ('E',x,y) ('F', n) = ('E', x + n, y )
go ('S',x,y) ('F', n) = ('S', x + n, y )
go ('W',x,y) ('F', n) = ('W', x + n, y )
go ('N',x,y) ('F', n) = ('N', x + n, y )
go (_ ,x,y) ('E', n) = ('E', x + n, y )
go (_ ,x,y) ('S', n) = ('S', x , y + n)
go (_ ,x,y) ('W', n) = ('W', x - n, y )
go (_ ,x,y) ('N', n) = ('N', x , y - n)
go ('E',x,y) ('R', 90) = ('S', x , y )
go ('E',x,y) ('R', 180) = ('W', x , y )
go ('E',x,y) ('R', 270) = ('N', x , y )
go ('S',x,y) ('R', 90) = ('W', x , y )
go ('S',x,y) ('R', 180) = ('N', x , y )
go ('S',x,y) ('R', 270) = ('E', x , y )
go ('W',x,y) ('R', 90) = ('N', x , y )
go ('W',x,y) ('R', 180) = ('E', x , y )
go ('W',x,y) ('R', 270) = ('S', x , y )
go ('N',x,y) ('R', 90) = ('E', x , y )
go ('N',x,y) ('R', 180) = ('N', x , y )
go ('N',x,y) ('R', 270) = ('W', x , y )
go ('E',x,y) ('L', 90) = ('N', x , y )
go ('E',x,y) ('L', 180) = ('W', x , y )
go ('E',x,y) ('L', 270) = ('S', x , y )
go ('S',x,y) ('L', 90) = ('E', x , y )
go ('S',x,y) ('L', 180) = ('N', x , y )
go ('S',x,y) ('L', 270) = ('W', x , y )
go ('W',x,y) ('L', 90) = ('S', x , y )
go ('W',x,y) ('L', 180) = ('E', x , y )
go ('W',x,y) ('L', 270) = ('N', x , y )
go ('N',x,y) ('L', 90) = ('W', x , y )
go ('N',x,y) ('L', 180) = ('N', x , y )
go ('N',x,y) ('L', 270) = ('E', x , y )
As I knew before I started this approach, it would bite me in the ass if I made some mistake while creating all the rules. And those mistakes would be hard to debug. Of course, I made mistakes, and there were quite a lot as you can see.
solve xs = abs (x + y) where
(dir, x, y) = foldl go ('E',0,0) xs
go ('E',x,y) ('F', n) = ('E', x + n, y )
go ('S',x,y) ('F', n) = ('S', x + n, y )
go ('W',x,y) ('F', n) = ('W', x + n, y )
go ('N',x,y) ('F', n) = ('N', x + n, y )
go (_ ,x,y) ('E', n) = ('E', x + n, y )
go (_ ,x,y) ('S', n) = ('S', x , y + n)
go (_ ,x,y) ('W', n) = ('W', x - n, y )
go (_ ,x,y) ('N', n) = ('N', x , y - n)
...
go ('N',x,y) ('R', 180) = ('N', x , y )
...
go ('N',x,y) ('L', 180) = ('N', x , y )
While copying the Forward instructions I forgot to change the output. I had misread the assignment for the N,E,S,W instruction the ship had only to be moved in that direction, but I also changed the direction of the ship. And in the L and R instructions, I made a mistake where if the ship was facing North and would turn 180 degrees left or right it would again face North. Even with the mistakes, the instructions worked on my example input, so I could not use the simple case to find my mistakes. I had to use the actual input of which I did not know the outcome. This meant that I had to check everything manually. Took me about twenty minutes to get everything fixed, but still, I only got the correct answer for the example, not for the actual input. After starring at it for a while I couldn't find what was wrong with it, so I decided to start coding some of the rules. Starting with L and R turns because these got the most rules.
solve1 xs = abs (x + y) where
(dir, x, y) = foldl go ('E',0,0) xs
go ('E',x,y) ('F', n) = ('E', x + n, y )
go ('S',x,y) ('F', n) = ('S', x , y + n)
go ('W',x,y) ('F', n) = ('W', x - n, y )
go ('N',x,y) ('F', n) = ('N', x , y - n)
go (d ,x,y) ('E', n) = (d , x + n, y )
go (d ,x,y) ('S', n) = (d , x , y + n)
go (d ,x,y) ('W', n) = (d , x - n, y )
go (d ,x,y) ('N', n) = (d , x , y - n)
go (d ,x,y) ('R', 90) = (turn 1 d,x,y)
go (d ,x,y) ('R', 180) = (turn 2 d,x,y)
go (d ,x,y) ('R', 270) = (turn 3 d,x,y)
go (d ,x,y) ('L', 90) = (turn (-1) d,x,y)
go (d ,x,y) ('L', 180) = (turn (-2) d,x,y)
go (d ,x,y) ('L', 270) = (turn (-3) d,x,y)
turn t d = d' where
dirs = ("NESW")
di = fromJust $ elemIndex d dirs
d' = dirs !! ((4 + di + t) `mod` 4)
After coding the turns it still not worked, so I started looking at the code again until I finally figured out that the problem was not in my rules, but in my Manhattan distance function, I used abs (x+y) instead of abs x + abs y. Changing that made the code finally work. Of course, this would have fixed the original code as well. Drop a comment if you had already spotted the error, or if you have had such a failure yourself.
For part 2 the rules of the instructions changed, learning from my mistakes I started out with less duplication and more coding. With a few small missteps, I got to a working solution.
solve2 xs = abs x + abs y where
(_, x, y) = foldl go ((10,-1),(0,0)) xs
go ((e,s), (x,y)) ('F',n) = ((e,s),(x + n * e, y + n * s)
go (w, l) ('R', 90) = (turn w 1, l)
go (w, l) ('R', 180) = (turn w 2, l)
go (w, l) ('R', 270) = (turn w 3, l)
go (w, l) ('L', 90) = (turn w 3, l)
go (w, l) ('L', 180) = (turn w 2, l)
go (w, l) ('L', 270) = (turn w 1, l)
go (w, l) ('N', n) = (move w ('N',n), l)
go (w, l) ('E', n) = (move w ('E',n), l)
go (w, l) ('S', n) = (move w ('S',n), l)
go (w, l) ('W', n) = (move w ('W',n), l)
turn (e,s) 0 = (e,s)
turn (e,s) t = turn (-s, e) (t - 1)
move (x,y) ('N',n) = (x, y - n)
move (x,y) ('E',n) = (x + n, y)
move (x,y) ('S',n) = (x, y + n)
move (x,y) ('W',n) = (x - n, y)
Still quite a lot of duplication, but having put in my scores for the day I started working on my cleanup, I'm quite content with the final result. I hope to see you back tomorrow, or you can go back to Day 1 to read the other stories in the series.