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
}
Top comments (0)