Advent of Code 2023 Day 18
Mix.install([
{:kino_aoc, "~> 0.1.5"},
{:nx, "~> 0.6.4"},
{:exla, "~> 0.6.4"}
])
Prep
{:ok, real_input} =
KinoAOC.download_puzzle("2023", "18", System.fetch_env!("LB_AOC_SESSION"))
test_input =
"""
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)
"""
|> String.trim()
puzzle_input = real_input
Part 1
actions =
puzzle_input
|> String.split("\n")
|> Enum.map(fn line ->
line |> String.split(" ", parts: 3, trim: true) |> Enum.take(2)
end)
|> Enum.map(fn [dir, meters] ->
{dir, String.to_integer(meters)}
end)
directions = %{
"L" => {0, -1},
"R" => {0, 1},
"U" => {-1, 0},
"D" => {1, 0}
}
vertices =
for {dir, meters} <- actions,
reduce: [{0, 0}] do
[{i, j} | _] = acc ->
{di, dj} = directions[dir]
next_pos = {i + di * meters, j + dj * meters}
[next_pos | acc]
end
area =
vertices
|> Stream.chunk_every(2, 1, :discard)
|> Stream.map(fn [{i1, j1}, {i2, j2}] ->
(i1 - i2) * (j1 + j2)
end)
|> Enum.sum()
|> div(2)
|> abs()
perimeter = actions |> Enum.map(&elem(&1, 1)) |> Enum.sum()
area + div(perimeter, 2) + 1
Expected: 46359
Part 2
directions = %{
0 => {0, 1},
1 => {1, 0},
2 => {0, -1},
3 => {-1, 0}
}
actions =
Regex.scan(~r/\b([0-9a-f]{5})([0-3])\b/m, puzzle_input, capture: :all_but_first)
|> Enum.map(fn [hex, dir] ->
{String.to_integer(dir), String.to_integer(hex, 16)}
end)
vertices =
for {dir, meters} <- actions,
reduce: [{0, 0}] do
[{i, j} | _] = acc ->
{di, dj} = directions[dir]
next_pos = {i + di * meters, j + dj * meters}
[next_pos | acc]
end
area =
vertices
|> Stream.chunk_every(2, 1, :discard)
|> Stream.map(fn [{i1, j1}, {i2, j2}] ->
i1 * j2 - i2 * j1
end)
|> Enum.sum()
|> div(2)
|> abs()
perimeter = actions |> Enum.map(&elem(&1, 1)) |> Enum.sum()
area + div(perimeter, 2) + 1