1
0
Fork 0

solve 2024 day 12

This commit is contained in:
sloane 2024-12-12 16:06:58 -05:00
parent 1e677cbbc9
commit 154e278fb3
Signed by: sloanelybutsurely
SSH key fingerprint: SHA256:8SBnwhl+RY3oEyQxy1a9wByPzxWM0x+/Ejc+sIlY5qQ
3 changed files with 116 additions and 3 deletions

View file

@ -3,7 +3,7 @@
| S | M | T | W | T | F | S |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| [1] | [2] | [3] | [4] | [5] | [6] | [7] |
| [8] | [9] | [10]| [11]| 12 | 13 | 14 |
| [8] | [9] | [10]| [11]| [12]| 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | | | |
@ -18,3 +18,4 @@
[9]: ./lib/2024/9.ex
[10]: ./lib/2024/10.ex
[11]: ./lib/2024/11.ex
[12]: ./lib/2024/12.ex

112
2024/lib/2024/12.ex Normal file
View file

@ -0,0 +1,112 @@
import AOC
import AOC.Prelude
aoc 2024, 12 do
def p1(input) do
input
|> map_grid()
|> group_plots()
|> Enum.map(&size_plot/1)
|> Enum.map(fn {area, perimeter, _} -> area * perimeter end)
|> Enum.sum()
end
def p2(input) do
input
|> map_grid()
|> group_plots()
|> Enum.map(&size_plot/1)
|> Enum.map(fn {area, _, sides} -> area * sides end)
|> Enum.sum()
end
## group plots
defp group_plots(map, plots \\ [])
defp group_plots(map, plots) when map_size(map) == 0, do: plots
defp group_plots(map, plots) do
{pos, plant} = Enum.at(map, 0)
plot = walk_plot(map, pos, plant)
{_, map} = Map.split(map, MapSet.to_list(plot))
group_plots(map, [plot | plots])
end
defp size_plot(plot) do
area = MapSet.size(plot)
perimeter =
for pos <- plot, reduce: 0 do
sum ->
sum +
([&n/1, &s/1, &e/1, &w/1]
|> Enum.map(& &1.(pos))
|> Enum.count(&(not MapSet.member?(plot, &1))))
end
{area, perimeter, count_sides(plot)}
end
## traversal
defp walk_plot(map, pos, plant, plot \\ MapSet.new()) do
plot = MapSet.put(plot, pos)
[&n/1, &s/1, &e/1, &w/1]
|> Enum.map(& &1.(pos))
|> Enum.reject(&MapSet.member?(plot, &1))
|> Enum.filter(&(Map.get(map, &1) == plant))
|> Enum.reduce(plot, fn pos, plot ->
walk_plot(map, pos, plant, plot)
end)
end
def n({x, y}), do: {x, y + 1}
def s({x, y}), do: {x, y - 1}
def e({x, y}), do: {x + 1, y}
def w({x, y}), do: {x - 1, y}
defp count_sides(plot) do
# find exterior faces
exterior_faces =
for pos <- plot, dir <- ~w[n e s w]a, exterior?(plot, pos, dir) do
{pos, dir}
end
exterior_faces
# group exterior faces
|> Enum.group_by(
fn
{{_, y}, dir} when dir in ~w[n s]a -> {dir, y}
{{x, _}, dir} when dir in ~w[e w]a -> {dir, x}
end,
fn
{{x, _}, dir} when dir in ~w[n s]a -> x
{{_, y}, dir} when dir in ~w[e w]a -> y
end
)
|> Map.values()
# count groups of exterior faces, splitting non-monotonic sections
|> Enum.map(fn group ->
{faces, _} =
group
|> Enum.sort()
|> Enum.reduce({0, nil}, fn
n, {sides, nil} -> {sides + 1, n}
n, {sides, last} when last + 1 == n -> {sides, n}
n, {sides, _last} -> {sides + 1, n}
end)
faces
end)
|> Enum.sum()
end
defp exterior?(plot, pos, dir) do
neighboring_pos = apply(__MODULE__, dir, [pos])
not MapSet.member?(plot, neighboring_pos)
end
end

View file

@ -15,8 +15,8 @@
| [2021] | **43/50** 🌟 | Elixir |
| [2022] | **14/50** 🌟 | Elixir, Haskell |
| [2023] | **19/50** 🌟 | Elixir, Haskell |
| [2024] | **22/50** 🌟 | Elixir |
| **Total** | **178** 🌟| |
| [2024] | **24/50** 🌟 | Elixir |
| **Total** | **180** 🌟| |
[2015]: ./2015
[2017]: ./2017