DEV Community

Caleb Weeks
Caleb Weeks

Posted on

Advent of Code #1 (in Gleam)

It's that time of the year again! Advent of Code is my favorite coding challenge, and I enjoy talking about the problems with friends and coworkers.

This year, I really wanted to try doing the puzzles in Roc. I've been following the development of the language for a while, but I've never really tried using it. Unfortunately, I had a hard time getting started with it. Advent of Code is challenging enough on its own, and I didn't want to add too much to that challenge.

I really enjoyed using Crystal last year. It is a very ergonomic language with a featureful standard library. I was tempted to use it again this year, but I figured I should use this opportunity to try something new. After considering several languages including Go, F#, Nim, and Raku, I decided to go with Gleam.

It took me a bit of time to find a proper package for reading files, but I settled on simplifile.

Without further ado, here's my solution:

import gleam/int
import gleam/io
import gleam/list
import gleam/string
import simplifile as file

const example = "
3   4
4   3
2   5
1   3
3   9
3   3
"

pub fn main() {
  let assert Ok(input) = file.read("input")
  let assert 11 = part1(example)
  let assert 31 = part2(example)
  part1(input) |> int.to_string |> io.println
  part2(input) |> int.to_string |> io.println
}

fn parse_lists(input: String) -> #(List(Int), List(Int)) {
  input
  |> string.trim
  |> string.split("\n")
  |> list.fold(#([], []), fn(acc, line) {
    let #(left_list, right_list) = acc
    let assert [left, right] = string.split(line, "   ")
    let assert Ok(left) = int.parse(left)
    let assert Ok(right) = int.parse(right)
    #([left, ..left_list], [right, ..right_list])
  })
}

fn part1(input: String) -> Int {
  let #(left_list, right_list) = parse_lists(input)
  let left_list = list.sort(left_list, by: int.compare)
  let right_list = list.sort(right_list, by: int.compare)

  list.zip(left_list, right_list)
  |> list.fold(0, fn(sum, pair) {
    let #(left, right) = pair
    sum + int.absolute_value(left - right)
  })
}

fn part2(input: String) -> Int {
  let #(left_list, right_list) = parse_lists(input)

  list.fold(left_list, 0, fn(sum, left) {
    sum + list.count(right_list, fn(right) { left == right }) * left
  })
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)