View Source AOC (Advent of Code Utils v3.1.1)
Advent of Code solution module macro and helpers.
This module contains the aoc/3
macro, which should be used to write a solution module for a
given advent of code challenge. The intended use is to write your solution for day <day>
, year
<year>
as follows:
import AOC
aoc <year>, <day> do
def p1(input) do
# Part 1 solution goes here
end
def p2(input) do
# Part 1 solution goes here
end
end
Defining a module with the aoc/3
macro has a few advantages:
- The
AOC.IEx
functions can be used to call your solutions in the module, making your life easier. - Helper functions to access the input and examples (if present) are inserted into the generated module.
Each of these advantages corresponds with a way to write your solution module, which we discuss
below. Overall, the aoc/3
macro is intended to allow you to forego writing boilerplate code
which is shared between all the solutions.
Note that the code skeleton shown above can be generated by running mix aoc.gen
or mix aoc
.
aoc-3-and-use-aoc
aoc/3
and use AOC
Internally, aoc/3
generates a module with a predefined name (Y<year>.D<day>
) which contains
a use AOC, day: <day>, year: <year>
statement. In turn, the __using__/1
macro defined in
this module is responsible for generating helper functions. Thus, if you prefer to use a
different naming scheme than the one imposed by aoc/3
, you can write your module as follows:
defmodule MySolution do
use AOC, day: <day>, year: <year>
...
end
When the AOC
module is used like this, the helper functions defined below are still usable,
but the helpers defined in AOC.IEx
will not work.
iex
IEx
The AOC.IEx
module defines various helpers which facilitate testing the code in this module
within iex, the elixir shell. For instance, if you write your solution for part 1 as follows:
aoc <year>, <day> do
def p1(input) do
# solutions go here
end
end
You can use AOC.IEx.p1e/1
to call p1
with the example input of that day and AOC.IEx.p1i/1
to call p1
with the puzzle input of that day. Similar functions are available for p2
.
helper-functions
Helper functions
You can also directly access the puzzle input or examples for a day inside an aoc/3
module.
This module defines various functions such as input_path/2
, input_string/2
,
input_stream/2
and their example_*/2
counter parts. Helpers are inserted inside the
generated module which call these functions with the module's day / year. Thus, if you call
input_path()
inside your solution module, it will call input_path/2
for you with the
module's day and year, obtaining the path to the appropriate input file.
The following table provides an overview of the inserted functions and their counterparts in this module:
Generated | Calls |
---|---|
input_path/0 | input_path/2 |
input_string/0 | input_string/2 |
input_stream/0 | input_stream/2 |
example_path/0 | example_path/2 |
example_string/0 | example_string/2 |
example_stream/0 | example_stream/2 |
The generated functions are overridable, i.e. you can define your own version of these functions which will overwrite the generated function. This is handy to do something like the following:
def input_stream, do: super() |> Stream.map(&String.to_integer/1)
Link to this section Summary
Functions
Generate an advent of code solution module for a given year and day.
Get the example path for year
, day
.
Stream the contents of the example for year
, day
.
Get the example contents of year
, day
.
Get the input path for year
, day
.
Stream the contents of the input for year
, day
.
Get the input contents of year
, day
.
Link to this section Functions
Generate an advent of code solution module for a given year and day.
The generated module will be named Y<year>.D<day>
. use AOC
will be injected in the body of
the module, so that the input helpers described in the module documentation are available.
examples
Examples
import AOC
aoc 2020, 1 do
def some_function do
:foo
end
end
is equivalent to:
defmodule Y2020.D1 do
use AOC, year: 2020, day: 1
def some_function do
:foo
end
end
@spec example_path(pos_integer(), pos_integer()) :: Path.t()
Get the example path for year
, day
.
Obtains the path where mix aoc.get
stores the input for year
, day
. This path defaults to
input/<year>_<day>_example.txt
, but can be customized. Please refer to the mix aoc.get
documentation for more information.
@spec example_stream(pos_integer(), pos_integer()) :: Enumerable.t()
Stream the contents of the example for year
, day
.
The stream is created by calling File.stream!/1
on the path returned by example_path/2
.
Afterwards, String.trim_trailing(&1, " ")
is mapped over the stream (using Stream.map/2
),
to remove trailing newlines.
@spec example_string(pos_integer(), pos_integer()) :: String.t()
Get the example contents of year
, day
.
Obtained by calling File.read!/1
on the path returned by example_path/2
.
String.trim_trailing(string, " ")
is called on the resulting string to remove trailing
whitespace.
@spec input_path(pos_integer(), pos_integer()) :: Path.t()
Get the input path for year
, day
.
Obtains the path where mix aoc.get
stores the input for year
, day
. This path defaults to
input/<year>_<day>.txt
, but can be customized. Please refer to the mix aoc.get
documentation
for more information.
@spec input_stream(pos_integer(), pos_integer()) :: Enumerable.t()
Stream the contents of the input for year
, day
.
The stream is created by calling File.stream!/1
on the path returned by input_path/2
.
Afterwards, String.trim_trailing(&1, " ")
is mapped over the stream (using Stream.map/2
),
to remove trailing newlines.
@spec input_string(pos_integer(), pos_integer()) :: String.t()
Get the input contents of year
, day
.
Obtained by calling File.read!/1
on the path returned by input_path/2
.
String.trim_trailing(string, " ")
is called on the resulting string to remove trailing
whitespace.