DEV Community

Caleb Weeks
Caleb Weeks

Posted on

Advent of Code #3 (in Gleam)

Regex is doing a lot of the heavy lifting in today's puzzles. That is one of the main reasons why I ended up not using Roc for Advent of Code this year. There is no regex library, and I just couldn't quite wrap my head around the parser combinator library in time for this year. Maybe I'll get around to it next year.

Pattern matching is a powerful tool in general, and really excels at handling the regex matches. I find it a little strange that you can't pattern match in function parameter definitions like you can in most languages with pattern matching. I'm sure there is a good reason for it, but I'm not sure what that is at the moment.

Anyway, here's how I solved today's puzzles:

import gleam/int
import gleam/io
import gleam/list
import gleam/pair
import gleam/option.{Some}
import gleam/regexp.{Match}
import simplifile as file

const example1 = "
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
"

const example2 = "
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
"

pub fn main() {
  let assert Ok(input) = file.read("input")
  let assert 161 = part1(example1)
  let assert 48 = part2(example2)
  part1(input) |> int.to_string |> io.println
  part2(input) |> int.to_string |> io.println
}

fn mult_pair(x: String, y: String) -> Int {
  let assert Ok(x) = int.parse(x)
  let assert Ok(y) = int.parse(y)
  x * y
}

fn part1(input: String) -> Int {
  let assert Ok(re) = regexp.from_string("mul\\((\\d+),(\\d+)\\)")
  regexp.scan(re, input)
  |> list.fold(0, fn(sum, match) {
    let assert Match(_, [Some(x), Some(y)]) = match
    sum + mult_pair(x, y)
  })
}

fn part2(input: String) -> Int {
  let assert Ok(re) = regexp.from_string("mul\\((\\d+),(\\d+)\\)|do\\(\\)|don't\\(\\)")
  regexp.scan(re, input)
  |> list.fold(#(0, True), fn(state, match) {
    case match, state {
      Match(_, [Some(x), Some(y)]), #(sum, True) -> #(sum + mult_pair(x, y), True)
      Match("do()", _), #(sum, _) -> #(sum, True)
      Match("don't()", _), #(sum, _) -> #(sum, False)
      _, _ -> state
    }
  })
  |> pair.first
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)