Advent of Code - Day 1 - Differences and Products (F#)

As the challenge at AoC is not about the syntax but the algorithm, I decided to try a different approach this year: a new language every day. I am probably not going to explain the code in detail, but I will point out characteristics of each particular language that I think are worth mentioning. Let’s see how far I get. Please don’t take my judgement to serious.

Disclaimer: Of course, I am using AI to get the actual syntax, but not for the algorithm itself. I usually use ClaudeAI for that, as I’ve experienced the best results with the free version there.

On the first day, I’m starting with F# — the sister of C# — which focuses on functional programming.

Setting Up the Development Environment

First, I need to set up my development environment. Since I don’t want to pollute my system with tons of different interpreters, I prefer to work in Docker containers. Above all, this requires the Dev Containers extension. To make VS Code ready for F#, I also need the Ionide extension.

Here is the Dockerfile for a containerized F# environment:

# Use official .NET SDK image with F# support
FROM mcr.microsoft.com/dotnet/sdk:8.0

# Install additional tools
RUN apt-get update && \
    apt-get install -y \
    git \
    curl \
    vim \
    sudo

# Create vscode user with sudo permissions
RUN groupadd -r vscode \
    && useradd -m -s /bin/bash -g vscode -G sudo vscode \
    && echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/vscode \
    && chmod 0440 /etc/sudoers.d/vscode

# Set working directory and ensure proper ownership
WORKDIR /app
RUN chown -R vscode:vscode /app

# Ensure .NET tools are in PATH
ENV PATH="/home/vscode/.dotnet/tools:${PATH}"

# Set the default user to vscode
USER vscode

# Ensure .NET tools are installed for the vscode user
RUN dotnet tool list --global || true

# Default command
CMD ["/bin/bash"]

Developing inside a container requires /.devcontainer/devcontainer.json to look like this:

{
    "name": "F# Dev Environment",
    "build": {
        "dockerfile": "../Dockerfile",
        "context": ".."
    },
    "remoteUser": "vscode",
    "workspaceFolder": "/app",
    "customizations": {
        "vscode": {
            "extensions": [
                "Ionide.ionide-fsharp",
                "ms-dotnettools.csharp"
            ]
        }
    },
    "mounts": [
        "source=${localWorkspaceFolder},target=/app,type=bind,consistency=cached"
    ],
    "containerUser": "vscode",
    "remoteEnv": {
        "DOTNET_CLI_HOME": "/app"
    }
}

Now, after building and running the container with docker-compose build; docker-compose up -d, I can connect to the container by either pressing CMD+SHIFT+P or using the small blue button on the bottom left, selecting the option “Connect to Dev Container.

Day 1 - About differences and products

(task - solution)

The first day consists of two simple tasks, so I won’t go into too much detail:

  1. Order two lists incrementally, then get the difference for each list item and sum all differences up.
  2. For each item on the first list, count the occurrences on the second list, compute the product i * frequency(i), and then get the sum of all products.

Whats up, F#?

8 of 12, would like to stay in touch

Well, I certainly havent had the chance to get familar with F#, but at the first glance I like how you can connect output to adjecent commands using the pipe operator:

let readListFromFile (filePath: string) =
    File.ReadAllLines(filePath) 
    |> Array.map int
    |> Array.toList

This makes things quiete easy, resulting in a clearer and more concise coding style. Seems like F# is a good choice for hands one problem solving.

See you next day…