As a reminder, these writeups won't be super detailed, since I have to do one every day. I'll try to focus on the key ideas though, and I'll always link to my code!

Subscribe to Monday Morning Haskell!

## Problem Overview

This year we're dealing with **elves**. Each elf is carrying some snack items with a certain number of calories. Our input has one calorie count per line, and an empty line denotes that we have reached the end of one elf's snack collection and started another.

```
1000
2000
3000
4000
5000
6000
7000
8000
9000
10000
```

For the first part, we just want to find the elf with the most calories. This is the 4th elf, with a total of `24000`

calories (`7000+8000+9000`

).

For the second part, we want the sum of calories from the **three** elves with the most. So we take the `24000`

from the elf with the most, and add the 3rd elf (`11000`

calories) and the 5th elf (`10000`

calories). This gives a total of `45000`

.

## Solution Approach and Insights

Nothing complicated here. Once we parse into list-of-lists-of-ints, we just use `map sum`

and either take the maximum or the sum of the top 3.

## Relevant Utilities

Function `parseFile`

## Parsing the Input

Here's our parsing code. One nuance...I needed to add an **extra empty line** to the given inputs in order to make this parse work. Dealing with empty line separators is a little tricky with megaparsec (or at least I haven't mastered the right pattern yet), because the "chunk separator" is the same as the "line separator" within each chunk (`eol`

parser).

```
parseInput :: (MonadLogger m) => ParsecT Void Text m [[Int]]
parseInput =
sepEndBy1 parseIntLines eol
where
parseIntLines = some parseIntLine
parseIntLine = do
i <- parsePositiveNumber
eol
return i
```

## Getting the Solution

As above, nothing complicated here. Use `map sum`

and take the `maximum`

.

```
processInputEasy :: (MonadLogger m) => [[Int]] -> m Int
processInputEasy intLists = return $ maximum (map sum intLists)
```

With the hard part, we `sort`

, `reverse`

, `take 3`

, and then take another `sum`

.

```
processInputHard :: (MonadLogger m) => [[Int]] -> m Int
processInputHard intLists = return $ sum $ take 3 $ reverse $ sort (map sum intLists)
```

## Answering the Question

And no additional processing is needed - we have our answer! (My standard template has the answer always wrapped in `Maybe`

to account for failure cases).

```
solveEasy :: FilePath -> IO (Maybe Int)
solveEasy fp = runStdoutLoggingT $ do
input <- parseFile parseInput fp
Just <$> processInputEasy input
solveHard :: FilePath -> IO (Maybe Int)
solveHard fp = runStdoutLoggingT $ do
input <- parseFile parseInput fp
Just <$> processInputHard input
```