solve 2024 day 12
This commit is contained in:
parent
1e677cbbc9
commit
154e278fb3
3 changed files with 116 additions and 3 deletions
|
@ -3,7 +3,7 @@
|
||||||
| S | M | T | W | T | F | S |
|
| S | M | T | W | T | F | S |
|
||||||
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|
||||||
| [1] | [2] | [3] | [4] | [5] | [6] | [7] |
|
| [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 |
|
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
|
||||||
| 22 | 23 | 24 | 25 | | | |
|
| 22 | 23 | 24 | 25 | | | |
|
||||||
|
|
||||||
|
@ -18,3 +18,4 @@
|
||||||
[9]: ./lib/2024/9.ex
|
[9]: ./lib/2024/9.ex
|
||||||
[10]: ./lib/2024/10.ex
|
[10]: ./lib/2024/10.ex
|
||||||
[11]: ./lib/2024/11.ex
|
[11]: ./lib/2024/11.ex
|
||||||
|
[12]: ./lib/2024/12.ex
|
||||||
|
|
112
2024/lib/2024/12.ex
Normal file
112
2024/lib/2024/12.ex
Normal 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
|
|
@ -15,8 +15,8 @@
|
||||||
| [2021] | **43/50** 🌟 | Elixir |
|
| [2021] | **43/50** 🌟 | Elixir |
|
||||||
| [2022] | **14/50** 🌟 | Elixir, Haskell |
|
| [2022] | **14/50** 🌟 | Elixir, Haskell |
|
||||||
| [2023] | **19/50** 🌟 | Elixir, Haskell |
|
| [2023] | **19/50** 🌟 | Elixir, Haskell |
|
||||||
| [2024] | **22/50** 🌟 | Elixir |
|
| [2024] | **24/50** 🌟 | Elixir |
|
||||||
| **Total** | **178** 🌟| |
|
| **Total** | **180** 🌟| |
|
||||||
|
|
||||||
[2015]: ./2015
|
[2015]: ./2015
|
||||||
[2017]: ./2017
|
[2017]: ./2017
|
||||||
|
|
Loading…
Reference in a new issue