## DEV Community

Ryan Haskell-Glatz

Posted on

# Learn functional programming with Advent of Code! ☃️

## Hello, there! 👋

My name is Ryan, and I'm making a tiny YouTube series to help folks learn functional programming through Advent of Code. Each video will tackle a daily Advent of Code problem, and walk through how to solve it using Elm, a language for making reliable web apps.

For day one, I wanted to share this written guide to introduce you to the basics of the language. I used to build web applications using HTML, CSS, and JS– and articles like this really helped me wrap my head around learning this new style of coding!

### In this article

1. Let's help some elves!
2. Print stuff on the screen
3. Our first Elm program
4. Reusing code for Part 2

## 1. Let's help some elves!

You can visit Advent of Code to see the full description for today's coding puzzle– but we'll summarize it here for you:

• A group of elves need to count calories for their trip
• Each elf writes down how many calories each food item they have in a list like this:
``````1000
2000
3000
``````

That list above is saying "the first elf has 6000 calories worth of food" (Calculated by adding 1000, 2000, and 3000).

### But there are more elves!

Every elf in the group jots down the calories for their food, and uses blank lines to separate their food from the elf in front of them:

``````1000
2000
3000

4000

5000
6000

7000
8000
9000

10000
``````

In the list shown above, we see foods for all 5 elves in our group. Each

### What do we need to do?

The problem asks us to:

1. Add up all the calories for each elf
2. Find the elf with the most calories
3. Return that biggest calorie number

In this example, the answer would be 24,000– because Elf #4 has 7,000 + 8,000 + 9,000 calories worth of food.

But how can we use Elm to get that answer?

## 2. Printing stuff on the screen

This whole Elm thing is new, let's make sure we feel confident first! Here's a basic Elm program that prints "Hello!" to the screen.

``````import Html

main =
Html.text "Hello!"
``````
``````Hello!
``````

Elm compiles to HTML, so this is what we'd see in our web browser if we ran this program.

Elm programs have "functions" and "values":

• `Html.text` is a function that converts a `String` value into an `Html` value.
• `"Hello!"` is a value that stores the message we want to print on the screen.

Every Elm program has one `main` function that runs on startup. When we give `main` an `Html` value, our program will work!

### Can we print more than "Hello!"?

If we try to give `Html.text` the wrong input, the Elm compiler will let us know. Let's try to give it a `List number` instead of a `String` value:

``````import Html

main =
Html.text [ 1, 2, 3 ]
``````
``````TYPE MISMATCH ----------------------------------

The 1st argument to `text` is not what I expect:

4|     Html.text [ 1, 2, 3 ]
^^^^^^^^^^^
This argument is a list of type:

List number

But `text` needs the 1st argument to be:

String
``````

Here is our first "Elm compiler message". Elm doesn't throw errors on our users– instead it gives compiler errors up front during devleopment.

This error is telling us that `Html.text` expected a `String`, but we gave it a `List number` instead.

Luckily for us, Elm provides a helpful function that lets us print out any value we want: `Debug.toString`

If we update our code to convert that `List number` to a `String`, then `Html.text` will get the `String` value it expects:

``````import Html

main =
Html.text (Debug.toString [ 1, 2, 3 ])
``````
``````[ 1, 2, 3 ]
``````

Now our program works, and we can print any kind of value. But these parentheses are going to be hard to work with...

### Calling functions step-by-step with pipes

Every Elm function can use a special "pipeline" operator. This is an alternative way to pass an input into a function, from left-to-right.

Here's what the same code looks like, but using the pipeline operator:

``````import Html

main =
[ 1, 2, 3 ]             -- List number
|> Debug.toString   -- String
|> Html.text        -- Html msg
``````
``````[ 1, 2, 3 ]
``````

Note: I've added comments like `-- List number` to the end of each line, to help you see the shape of each value after each step of the pipeline. These comments aren't required to make our code run, though!

This pipeline-style will let us break our program into small steps, so we can make tiny progress towards getting to our answer.

Hopefully, the next section will show you what I mean!

## 3. Our first Elm program

Alright, that's a quick intro to the Elm language– let's learn how to actually solve the problem from before:

Which elf has the most food?

We should start by taking that puzzle input as a `String`, and printing that onto the screen as HTML. From there, we'll tackle the problem one step at a time!

I've copied the puzzleInput from before, and used `"""` to create a "multiline" Elm string:

``````import Html

main =
puzzleInput
|> Debug.toString
|> Html.text

puzzleInput = """
1000
2000
3000

4000

5000
6000

7000
8000
9000

10000
"""
``````
``````"\n1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000\n"
``````

This prints out the String, including all the new line characters (`"\n"`).

If you want to follow along, I made this Ellie example for you. It's basically CodePen, so you can code Elm apps in the web browser! ( Clicking the "Compile" button in the top-right will run this code! )

### Trimming extra white-space

When we print out this puzzle input, we'll see the string has new lines at the beginning and end.

Let's make our first step to use `String.trim` to clean those up:

``````import Html

main =
puzzleInput            -- String
|> String.trim     -- String
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````"1000\n2000\n3000\n\n4000\n\n5000\n6000\n\n7000\n8000\n9000\n\n10000"
``````

String.trim takes in a `String` and returns another `String`– but without those extra characters.

I've added back in those Elm comments to make it clear that we still have a `String` even after running the trim function.

### Splitting food up for each elf

Now that we used `String.trim`, we don't have the leading and trailing `\n` characters.

What's next? Let's split up each elf's food by using `String.split`. If we look at our input, we can see that each Elf has two `\n` characters between their food.

That's all we need to split up our string into a list of smaller ones:

``````import Html

main =
puzzleInput                    -- String
|> String.trim             -- String
|> String.split "\n\n"     -- List String
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````["1000\n2000\n3000","4000","5000\n6000","7000\n8000\n9000","10000"]
``````

The String.split function took in two arguments:

1. `"\n\n"` – the string we want to split things apart with
2. The result of `puzzleInput |> String.trim`

Note: When we use the `|>` operator, the last argument will be the last value in our pipeline. For this example, that means the trimmed puzzle input from the last step!

### Making lists of food for each elf

Each elf has their food split up from the other ones– and each elf's food is an item in the list.

But the numbers are still glued together with `\n` for each elf...

For each item in the list, let's split those numbers up with another `String.split` call:

``````import Html

main =
puzzleInput                         -- String
|> String.trim                  -- String
|> String.split "\n\n"          -- List String
|> List.map (String.split "\n") -- List (List String)
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[["1000","2000","3000"],["4000"],["5000","6000"],["7000","8000","9000"],["10000"]]
``````

Because we want to "split up each string in the list", we need to call `List.map`. The List.map function runs on each item, and returns the new item.

Because our input list was a `List String`, each item was a `String`. When we call `(String.split "\n")` on each individual `String` item– we end up with a `List String` for each item!

Hopefully the HTML output above makes this a bit easier to understand, but now each elf's food is tracked as a `List String`.

• Because there are multiple elves, we track the whole thing in a nested `List (List String)`.

### We can't add up text!

We are getting really close, but there's a problem... we can't do addition with `String` values!

Let's convert these `String` values to numbers using Elm's built-in `String.toInt` function:

``````import Html

main =
puzzleInput                              -- String
|> String.trim                       -- String
|> String.split "\n\n"               -- List String
|> List.map (String.split "\n")      -- List (List String)
|> List.map (List.map String.toInt)  -- List (List (Maybe Int))
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[[Just 1000,Just 2000,Just 3000],[Just 4000],[Just 5000,Just 6000],[Just 7000,Just 8000,Just 9000],[Just 10000]]
``````

Uh-oh. This doesn't look right at all!

### What the heck is "Just"?

Whoa, whoa, whoa– what's this crazy "Maybe" thing? Why are all our numbers prefixed with that `Just` keyword?

In Elm, there's no `null` or runtime errors allowed– so any operation that might fail needs to return a `Maybe Int` instead of a normal `Int` we might expect from something like JavaScript's `parseInt` function

This means three things:

• Our Elm program will never crash for bad input!
• If we try to call `String.toInt "banana"` we will get `Nothing`
• If we call `String.toInt "1000"`, we will get `Just 1000`

So how do we get rid of those weird `Just` things?

Luckily, Elm also comes with another helpful function for filtering the `Just`/`Nothing` stuff out of a list!

Let's change this code to use `List.filterMap String.toInt` instead of `List.map String.toInt`:

``````import Html

main =
puzzleInput                              -- String
|> String.trim                       -- String
|> String.split "\n\n"               -- List String
|> List.map (String.split "\n")      -- List (List String)
|> List.map (List.filterMap String.toInt)  -- List (List Int)
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[[1000,2000,3000],[4000],[5000,6000],[7000,8000,9000],[10000]]
``````

Thank goodness– the List.filterMap function took care of those weird `Maybe` values!

### Adding up each elf's food

Finally, we have some numbers that we can do math with! 😌

Let's use another great built-in function called `List.sum` to add up all the numbers for each list:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[6000,4000,11000,24000,10000]
``````

When we combine `List.map` and List.sum, we can sum up each item in our list.

That turned our nested `List (List Int)` back into a `List Int`.

### So who's got the most food?

Now each item in the list has the total calorie counts for each elf, we only need one more function.

Let's use that function, `List.maximum`, which can find the biggest number in a list:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> List.maximum                         -- Maybe Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````Just 24000
``````

### You solved it!

That's it! That's the answer we were looking for all along.

Pat yourself on the back, you made it through some scary, new syntax.

As a final step, let's see if our code is flexible enough to solve a slightly the final challenge...

## 4. Reusing code for Part 2

The next part of the Advent of Code problem asks us to add up the top 3 elf calories, not just the top 1.

Let's rewind a bit by removing that last part with `List.maximum`, and having our program return the `List Int` we had before:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[6000,4000,11000,24000,10000]
``````

We're back to what we had before– and don't need to deal with all the grouping and int conversion again.

### Sorting lists

This is where we left off before calling `List.maximum`. It still has all the data we need, but we need to make sure to grab the 3 biggest numbers this time around.

We can group the big numbers together with the built-in `List.sort` function:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> List.sort                              -- List Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[4000,6000,10000,11000,24000]
``````

The List.sort function automatically sorts the numbers for us, from smallest to biggest.

### Reversing our list

Elm lists have a function called `List.take`, but it only grabs the items in the front of the list. When we called `List.sort`, all the biggest numbers moved to the end.

Let's use `List.reverse` so that the biggest items are in front, instead:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> List.sort                              -- List Int
|> List.reverse                           -- List Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[24000,11000,10000,6000,4000]
``````

The List.reverse function reversed the order of our list– and things are looking good!

### Grabbing the first 3 items

Great! Now we have the three biggest numbers right in front

• The only remaining step is to take the first 3 items with `List.take`:
``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> List.sort                              -- List Int
|> List.reverse                           -- List Int
|> List.take 3                            -- List Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````[24000,11000,10000]
``````

The List.take function takes two arguments:

1. The amount of items we want to keep (`3`)
2. The full list we want to take from

### Wait a minute... we know how to do this part!

Now we have the top 3 biggest numbers, so let's add them up!

Earlier, we used an Elm function for adding up all the numbers in a list.

Let's use the `List.sum` function one last time to get our answer:

``````import Html

main =
puzzleInput                                   -- String
|> String.trim                            -- String
|> String.split "\n\n"                    -- List String
|> List.map (String.split "\n")           -- List (List String)
|> List.map (List.filterMap String.toInt) -- List (List Int)
|> List.map List.sum                      -- List Int
|> List.sort                              -- List Int
|> List.reverse                           -- List Int
|> List.take 3                            -- List Int
|> List.sum                               -- Int
|> Debug.toString
|> Html.text

puzzleInput =
...
``````
``````45000
``````

## Hooray– you're an Elm developer!

Hopefully, you learned something new and feel super smart! Here's the final solution on Ellie

If you want to learn more here are some resources:

In each video, I'll walk through my thought process step-by-step. If you're like me, having someone talk things through is the easiest way to absorb new information.

Thanks for reading– and I hope you all have a wonderful December! 👋

DEV Community

## Super Useful CSS Resources

A collection of 70 hand-picked, web-based tools which are actually useful.
Each will generate pure CSS without the need for JS or any external libraries.