This commit is contained in:
bluepython508
2023-12-01 17:51:59 +00:00
commit 235deeccb7
13 changed files with 358 additions and 0 deletions

13
lib/aoc2023.ex Normal file
View File

@@ -0,0 +1,13 @@
defmodule Aoc2023 do
defmacro __using__([]) do
quote do
import Aoc2023.Common
def main(input) do
parsed = parse(input)
IO.puts("Part 1: #{part1(parsed)}")
IO.puts("Part 2: #{part2(parsed)}")
end
end
end
end

4
lib/common.ex Normal file
View File

@@ -0,0 +1,4 @@
defmodule Aoc2023.Common do
def stringify(s) when is_binary(s) do s end
def stringify(n) when is_integer(n) do inspect(n) end
end

15
lib/day1.ex Normal file
View File

@@ -0,0 +1,15 @@
defmodule Aoc2023.Day1 do
use Aoc2023
def parse(input) do
input
end
def part1(input) do
nil
end
def part2(input) do
nil
end
end

161
lib/mix_tasks.ex Normal file
View File

@@ -0,0 +1,161 @@
defmodule Mix.Tasks.Aoc do
use Mix.Task
import Aoc2023.Common
defp module(1), do: Aoc2023.Day1
# [MODULE INSERTION POINT]
defp base_dir(), do: System.get_env("AOC_BASE")
defp tests(day) do
case File.ls(tests_dir(day)) do
{:ok, paths} -> paths |> Enum.filter(&(not String.contains?(&1, ".")))
{:error, e} -> dbg(e)
[]
end
end
defp read(path) do
f = File.open!(path, [:utf8])
contents = IO.read(f, :eof)
:ok = File.close(f)
String.trim(contents)
end
defp test(day, test) do
f = "#{tests_dir(day)}#{test}"
{
test,
read(f),
if File.exists?(f <> ".1") do
read(f <> ".1")
else
nil
end,
if File.exists?(f <> ".2") do
read(f <> ".2")
else
nil
end
}
end
defp tests_dir(day), do: "#{base_dir()}/tests/day#{day}/"
defp create_file(path, contents) do
File.mkdir_p!(Path.dirname(path))
f = File.open!(path, [:exclusive, :utf8])
IO.write(f, contents)
:ok = File.close(f)
end
def run(params) do
{opts, params} = params |> OptionParser.parse!(strict: [day: :integer])
day = opts |> Keyword.get(:day, Date.utc_today().day)
run(day, params)
end
defp run(day, ["new"]) do
create_file("#{base_dir()}/lib/day#{day}.ex", """
defmodule Aoc2023.Day#{day} do
use Aoc2023
def parse(input) do
input
end
def part1(input) do
end
def part2(input) do
end
end
""")
this_file = "#{base_dir()}/lib/mix_tasks.ex"
contents =
read(this_file)
|> String.replace(
"\n # [MODULE INSERTION POINT]",
"\n defp module(#{day}), do: Aoc2023.Day#{day}\n # [MODULE INSERTION POINT]"
)
f = File.open!(this_file, [:write, :utf8])
IO.write(f, contents)
:ok = File.close(f)
end
defp run(day, ["test", "new"]) do
last = tests(day) |> Enum.map(&String.to_integer(&1)) |> Enum.max(&>=/2, fn -> 0 end)
create_file("#{tests_dir(day)}#{last + 1}", IO.read(:stdio, :eof))
end
defp run(day, ["test", "expected", test, part]) do
create_file("#{tests_dir(day)}#{test}.#{part}", IO.read(:stdio, :eof))
end
defp run(day, ["test"]) do
mod = module(day)
tests = tests(day)
tests
|> Enum.map(&test(day, &1))
|> Enum.map(fn {test, input, p1e, p2e} ->
parsed = mod.parse(input)
p1 = mod.part1(parsed)
if p1e do
if stringify(p1) != p1e do
IO.puts("Failed at #{test}.1: expected #{p1e}, got:")
dbg(p1)
end
else
IO.puts("Test #{test}.1")
dbg(p1)
end
p2 = mod.part2(parsed)
if p2e do
if stringify(p2) != p2e do
IO.puts("Failed at #{test}.2: expected #{p2e}, got:")
dbg(p2)
end
else
IO.puts("Test #{test}.2")
dbg(p2)
end
end)
end
defp run(day, ["run"]) do
run(day, ["fetch"])
run_file(day, "#{base_dir()}/inputs/day#{day}")
end
defp run(day, ["run", "-"]) do
run_file(day)
end
defp run(day, ["fetch"]) do
file = "#{base_dir()}/inputs/day#{day}"
if not File.exists?(file) do
HTTPoison.start()
resp =
HTTPoison.get!("https://adventofcode.com/2023/day/#{day}/input",
"user-agent": "aoc-ex by ben@soroos.net",
cookie: "session=#{System.get_env("AOC_SESSION")}"
)
create_file(file, resp.body)
end
end
defp run_file(day, file \\ nil) do
module(day).main(if file, do: read(file), else: IO.read(:stdio, :eof))
end
end