# Advent of Code 2021, Day 2

Welcome to Day 2 of Advent of Code 2021.

Our submarine adventure continues, we’ll need to reconfigure the navigation computer after we fixed the sonar yesterday.

Without further ado, here we go.

## Scheme

### Part 1

Here’s the problem we need to solve: we need to move our submarine according to a list of commands in the form of

```
forward 5
down 5
forward 8
up 3
down 8
forward 2
```

We’ll again first take care of the input. Since input is impure, we’ll hide it away in a function:

```
(define input
(letrec ((input-file (open-input-file "Input.txt"))
(R (lambda (ls)
(let* ((dir (read input-file))
(val (read input-file))
(navcom (list dir val)))
(if (eof-object? dir)
ls
(R (cons navcom ls)))))))
(reverse (R '()))))
```

This is almost identical to what we did [yesterday][day02]. We first read the direction into `dir`

, and the value into `val`

. Here’s the potential for a subtle error: We use `let*`

instead of `let`

here. If we were to use `let`

, the order of evaluation *would be reversed* - aka, `val`

and `dir`

would be switched. Since input operations are impure, order of evaluation matters, so be vary of that.

Next, we write a function that takes a *navigation command* and the *current position* and calculates the new position:

```
(define move-simple
(lambda (navcom curpos)
(record-case navcom
((forward) (val) (list (+ (car curpos) val) (cadr curpos)))
((up) (val) (list (car curpos) (- (cadr curpos) val)))
((down) (val) (list (car curpos) (+ (cadr curpos) val)))
(else (assertion-violationf 'navigate "invalid expression ~s" navcom)))))
```

We use Chez Scheme’s record-case to do a pattern matching-ish structure to interpret the given command to calculate the new position.

Next, we write a function that will navigate our submarine along the path of a *list of navigation* commands with a *move function*:

```
(define navigate
(lambda (move navcoms)
(letrec ((N (lambda (navcoms curpos)
(if (null? navcoms)
curpos
(N (cdr navcoms) (move (car navcoms) curpos))))))
(N navcoms '(0 0 0)))))
```

We enclose the starting position `(0 0 0)`

inside `navigate`

. The position is a 3-tuple here because we’ll need it for part 2 below. This is so we can reuse all functions from part 1 in part 2, because we love function composition.

Finally, we write a solution function that calculates the final position from a given *navigation command list*:

```
(define solution
(lambda (movef navcoms)
(let ((finalpos (navigate movef navcoms)))
(* (car finalpos) (cadr finalpos)))))
```

`solution`

applies a *move function* and a *list of navigation commands* to `navigate`

. We then calculate the product of the horizontal position and the depth, which is the result for part 1. So we can now calculate the result for part 1 thus:

```
(define solution-part1 (solution move-simple input))
```

```
$ scheme .\Dive_Bang.scm
Chez Scheme Version 9.5.5
Copyright 1984-2020 Cisco Systems, Inc.
> solution-part1
1815044
```

That’s the correct result for my input.

### Part 2

For part 2, we need to change the move function to include *aim* (which I interpret as the submarine’s pitch):

```
(define move-aim
(lambda (navcom curpos)
(let ((horizontal (car curpos))
(depth (cadr curpos))
(aim (caddr curpos)))
(record-case navcom
((forward) (val) (list (+ horizontal val) (+ depth (* aim val)) aim))
((up) (val) (list horizontal depth (- aim val)))
((down) (val) (list horizontal depth (+ aim val)))
(else (assertion-violationf 'navigate "invalid expression ~s" navcom))))))
```

And now, we compose the functions from part 1 for our solution:

```
(define solution-part2 (solution move-aim input))
```

```
$ scheme .\Dive_Bang.scm
Chez Scheme Version 9.5.5
Copyright 1984-2020 Cisco Systems, Inc.
> solution-part2
1739283308
```

This yields the correct answer of 1739283308 for my input. Find the complete solution here.

Awesome! Let’s do it again in Haskell.

## Haskell

We’re going to be a bit fancy today and write a simple parser with megaparsec:

```
data NavCom
= Forward Integer
| Up Integer
| Down Integer
deriving (Eq, Show)
type Position = (Integer, Integer, Integer)
-- Parser
type Parser = Parsec Void String
sc :: Parser ()
sc = L.space space1 empty empty
lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc
integer :: Parser Integer
integer = lexeme L.decimal
navcom :: Parser NavCom
navcom = operator <*> integer
where operator = lexeme $ choice [ Forward <$ string' "forward"
, Up <$ string' "up"
, Down <$ string' "down" ]
navcoms :: Parser [NavCom]
navcoms = manyTill navcom eof
```

First, we use some algebraic datatypes to define our own types. This will come in handy in a moment when we use pattern matching. Navigation commands are its own type, positions will be represented as triples.

The parser itself, `navcoms`

, is pretty simple. We use a space consumer `sc`

that will take care of all whitespace. `lexeme`

is a helper function that will remove all whitespace *after* a token has been matched. `navcom`

finally puts it all together: We choose the correct type constructor by matching the input with either one of the strings `forward`

, `up`

, or `down`

, and apply that to the `integer`

parser who will parse the integer after the just matched string.

As always, we hide the nasty impure input the `IO ()`

monad `main`

:

```
main :: IO ()
main = do
handle <- openFile "Input.txt" ReadMode
contents <- hGetContents handle
let (Right input) = runParser navcoms "" contents
print $ "Part 1: " ++ show (part1 input)
print $ "Part 2: " ++ show (part2 input)
hClose handle
```

Only thing missing now are the `part1`

and `part2`

functions.

### Part 1

We’ll use a similar approach as with the Scheme solution. We define a few simple functions and compose them into a solution:

```
moveSimple :: NavCom -> Position -> Position
moveSimple (Forward val) (horizontal, depth, aim) = (horizontal + val, depth, aim)
moveSimple (Up val) (horizontal, depth, aim) = (horizontal, depth - val, aim)
moveSimple (Down val) (horizontal, depth, aim) = (horizontal, depth + val, aim)
navigate :: (NavCom -> Position -> Position) -> [NavCom] -> Position
navigate move = foldr move (0, 0, 0)
solution :: (NavCom -> Position -> Position) -> [NavCom] -> Integer
solution movef navcoms =
let navcoms' = reverse navcoms
(horizontal, depth, _) = navigate movef navcoms'
in horizontal * depth
part1 :: [NavCom] -> Integer
part1 = solution moveSimple
```

Here, we use pattern matching over the types we defined earlier. Then we use a simple `foldr`

over the list of navigation commands to get the final position in `navigate`

. That result is then used in `solution`

to again calculate the product of the horizontal position and the depth. We can compose everything in `part1`

. Take note of the eta-reduction applied to `navigate`

and `part1`

.

### Part 2

We can reuse our solution from part 1:

```
moveAim :: NavCom -> Position -> Position
moveAim (Forward val) (horizontal, depth, aim) = (horizontal + val, depth + aim * val, aim)
moveAim (Up val) (horizontal, depth, aim) = (horizontal, depth, aim - val)
moveAim (Down val) (horizontal, depth, aim) = (horizontal, depth, aim + val)
part2 :: [NavCom] -> Integer
part2 = solution moveAim
```

We again only change the *move function* we pass to `solution`

to get the correct result:

```
$ ghci .\Dive_Bang.hs
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling DiveBang ( Dive_Bang.hs, interpreted )
Ok, one module loaded.
ghci> main
"Part 1: 1815044"
"Part 2: 1739283308"
ghci>
```

Again, the correct numbers for my input.

That’s it for today. You can find all my solutions on my Github.

See you tomorrow.