Advent of Code 2019: Elixir @callback

It's Advent of Code season again! I can't believe it's been three years since I started participating. It's such a fun time to remember why I like programming in the first place. I use it to learn new languages, hone skills and patterns, and just have fun.
I'm always obsessed with building tooling, so while the problems are easier I'm having a great time defining a sort of test runner for my advent of code… I think this is my second or third year trying in elixir, so I'm trying some new things.
This year's (current) model is using @callback
to define a sort of API that
all Advent problems have to solve:
defmodule Advent do
@moduledoc """
This is intended to be an importable module that defines some runners and
conventions for advent of code problems.
Each "day" should contain the following methods...
- `setup/0` should setup a input object.
- `p1/1` and `p2/2` should take the input and solve the puzzle, returning the
answer.
I want to define a test runner such that if you run mix <day number> it runs
`setup/0` once and runs `p1/1` and/or `p2/1` when appropriate.
"""
@callback setup() :: {:ok, term}
@callback p1(Map.t) :: {:ok, term}
@callback p2(Map.t) :: {:ok, term}
end
If you look at the whole file here, it also defines some timing functions as a mix task, which is fun. There's a crazy challenge for solving all puzzles under a certain time limit… I think this year I'll have to settle for just solving all puzzles.
This pattern really became really fun for today's puzzle (Day
3). As I started into part 2, more of p1
moved up into setup/0
so that p1/1
and p2/1
are just the specific
solutions to their part.
For instance:
def p1(%{intersections: intersections}) do
intersections
|> Enum.min_by(fn({x, y}) -> abs(x) + abs(y) end)
|> (fn({x, y}) -> abs(x) + abs(y) end).()
end
and
def p2(%{wires: {wire1, wire2}, intersections: intersections}) do
intersections
|> Enum.map(fn(coord) ->
Enum.find_index(Enum.reverse(wire1), & coord == &1) +
Enum.find_index(Enum.reverse(wire2), & coord == &1)
end)
|> Enum.min
end
You can see my full day 3 solution here. Let me know if you have a better way of managing the problems, this is my favorite so far.
Changelog
-
2022-06-08 11:31:29 -0500Rename articles
-
2020-06-18 14:26:02 -0500Move everything to CST
Don't know why I didn't do that before. It caused _no_ end of
problems. -
2019-12-03 12:39:48 -0600Post: Using @callback for elixir