Day 4; run watches in a seperate process to allow continuation after crashes
This commit is contained in:
@@ -32,4 +32,6 @@ defmodule Aoc2023.Common do
|
||||
end
|
||||
|
||||
def id(x), do: x
|
||||
def const(_, x), do: x
|
||||
def lines(x), do: String.split(x, "\n")
|
||||
end
|
||||
|
||||
39
lib/day4.ex
Normal file
39
lib/day4.ex
Normal file
@@ -0,0 +1,39 @@
|
||||
defmodule Aoc2023.Day4 do
|
||||
use Aoc2023
|
||||
|
||||
defp numbers(values) do
|
||||
values |> String.split() |> Enum.map(&String.to_integer/1) |> MapSet.new()
|
||||
end
|
||||
|
||||
def parse(input) do
|
||||
input
|
||||
|> lines
|
||||
|> Enum.map(
|
||||
&Regex.run(~r/Card\s+(?<id>\d+): (?<winning>(\s*\d+)+) \| (?<values>(\s*\d+)+)/, &1,
|
||||
capture: ["id", "winning", "values"]
|
||||
)
|
||||
)
|
||||
|> Enum.map(fn [id, winning, values] ->
|
||||
{String.to_integer(id),
|
||||
MapSet.intersection(numbers(winning), numbers(values)) |> MapSet.size()}
|
||||
end)
|
||||
end
|
||||
|
||||
def part1(input) do
|
||||
for {_, count} <- input,
|
||||
count > 0 do
|
||||
2 ** (count - 1)
|
||||
end
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
def part2(input) do
|
||||
for {id, count} <- input,
|
||||
id_ <- (id + 1)..(id + count)//1,
|
||||
reduce: input |> Enum.map(elem(0) &&& const(1)) |> Enum.into(%{}) do
|
||||
acc -> Map.update!(acc, id_, &(&1 + Map.get(acc, id)))
|
||||
end
|
||||
|> Enum.map(pipe(elem(1)))
|
||||
|> Enum.sum()
|
||||
end
|
||||
end
|
||||
@@ -5,6 +5,7 @@ defmodule Mix.Tasks.Aoc do
|
||||
defp module(1), do: Aoc2023.Day1
|
||||
defp module(2), do: Aoc2023.Day2
|
||||
defp module(3), do: Aoc2023.Day3
|
||||
defp module(4), do: Aoc2023.Day4
|
||||
# [MODULE INSERTION POINT]
|
||||
|
||||
defp base_dir(), do: System.get_env("AOC_BASE")
|
||||
@@ -102,7 +103,7 @@ defmodule Mix.Tasks.Aoc do
|
||||
end
|
||||
|
||||
defp run(day, ["test", "watch"]) do
|
||||
{:ok, pid} = Mix.Tasks.Aoc.Watcher.start_link({[dirs: ["lib/", "test/day#{day}/"]], self()})
|
||||
{:ok, pid} = Mix.Tasks.Aoc.Watcher.start_link({[dirs: ["lib/", "tests/day#{day}/"]], self()})
|
||||
Process.monitor(pid)
|
||||
loop = fn (loop) ->
|
||||
IO.puts(IO.ANSI.clear() <> IO.ANSI.cursor(0, 0))
|
||||
@@ -112,7 +113,9 @@ defmodule Mix.Tasks.Aoc do
|
||||
:code.purge(Aoc2023.Common)
|
||||
:code.load_file(module(day))
|
||||
:code.load_file(Aoc2023.Common)
|
||||
run(day, ["test"])
|
||||
spawn fn ->
|
||||
run(day, ["test"])
|
||||
end
|
||||
receive do
|
||||
:update -> loop.(loop)
|
||||
{:DOWN, _, :process, ^pid, _} -> nil
|
||||
@@ -129,8 +132,6 @@ defmodule Mix.Tasks.Aoc do
|
||||
|> Enum.map(&test(day, &1))
|
||||
|> Enum.map(fn {test, input, p1e, p2e} ->
|
||||
parsed = mod.parse(input)
|
||||
p1 = mod.part1(parsed)
|
||||
p2 = mod.part2(parsed)
|
||||
|
||||
result = fn (part, got, expected) ->
|
||||
cond do
|
||||
@@ -142,8 +143,8 @@ defmodule Mix.Tasks.Aoc do
|
||||
end
|
||||
end
|
||||
|
||||
result.(1, p1, p1e)
|
||||
result.(2, p2, p2e)
|
||||
result.(1, mod.part1(parsed), p1e)
|
||||
result.(2, mod.part2(parsed), p2e)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user