68 lines
1.4 KiB
Elixir
68 lines
1.4 KiB
Elixir
defmodule Aoc2023.Day18 do
|
|
require Integer
|
|
use Aoc2023
|
|
|
|
def parse(input) do
|
|
input
|
|
|> lines
|
|
|> Enum.map(fn line ->
|
|
[dir, n, color] =
|
|
Regex.run(~r/^([RDLU]) (\d+) \(#([0-9a-f]{6})\)$/, line, capture: :all_but_first)
|
|
|
|
{
|
|
dir |> String.to_charlist() |> head,
|
|
n |> String.to_integer(),
|
|
color
|
|
}
|
|
end)
|
|
end
|
|
|
|
defp simulate({pos, dist, points}, {dir, n}) do
|
|
p =
|
|
case dir do
|
|
:u -> {-n, 0}
|
|
:d -> {n, 0}
|
|
:r -> {0, n}
|
|
:l -> {0, -n}
|
|
end
|
|
|> add_vec(pos)
|
|
|
|
{p, dist + n, [p | points]}
|
|
end
|
|
|
|
defp area(perim, points),
|
|
# Shoelace formula
|
|
do:
|
|
Stream.zip(points, points |> Stream.cycle() |> Stream.drop(1))
|
|
|> Stream.map(fn {{y, x}, {y1, x1}} -> x * y1 - x1 * y end)
|
|
|> Enum.sum()
|
|
|> abs
|
|
|> then(&((&1 + perim) / 2))
|
|
|> trunc
|
|
|
|
defp run(instrs) do
|
|
{_, dist, points} = instrs |> Enum.reduce({{0, 0}, 2, [{0, 0}]}, &simulate(&2, &1))
|
|
area(dist, points)
|
|
end
|
|
|
|
def part1(input) do
|
|
run(for {dir, n, _} <- input, do: {case dir do
|
|
?U -> :u
|
|
?D -> :d
|
|
?L -> :l
|
|
?R -> :r
|
|
end, n})
|
|
end
|
|
|
|
def part2(input) do
|
|
run(for {_, _, <<len::binary-size(5), dir::integer>>} <- input do
|
|
{case dir do
|
|
?0 -> :r
|
|
?1 -> :d
|
|
?2 -> :l
|
|
?3 -> :u
|
|
end, String.to_integer(len, 16)}
|
|
end)
|
|
end
|
|
end
|