1
0
Fork 0

solve 2024 day 15

This commit is contained in:
sloane 2024-12-20 17:43:02 -05:00
parent 4abffd3c5e
commit d3d86a5b50
Signed by: sloanelybutsurely
SSH key fingerprint: SHA256:8SBnwhl+RY3oEyQxy1a9wByPzxWM0x+/Ejc+sIlY5qQ
3 changed files with 159 additions and 3 deletions

View file

@ -4,7 +4,7 @@
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| [1] | [2] | [3] | [4] | [5] | [6] | [7] |
| [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 | | | |
[1]: ./lib/2024/1.ex
@ -21,3 +21,4 @@
[12]: ./lib/2024/12.ex
[13]: ./lib/2024/13.ex
[14]: ./lib/2024/14.ex
[15]: ./lib/2024/15.ex

155
2024/lib/2024/15.ex Normal file
View file

@ -0,0 +1,155 @@
import AOC
import AOC.Prelude
aoc 2024, 15 do
def p1(input) do
{grid, moves} = read_input(input)
grid
|> apply_moves(moves)
|> boxes_coords()
|> Enum.map(&gps/1)
|> Enum.sum()
end
def p2(input) do
{grid, moves} =
input
|> String.replace("#", "##")
|> String.replace("O", "[]")
|> String.replace(".", "..")
|> String.replace("@", "@.")
|> read_input()
grid
|> apply_moves(moves)
|> boxes_coords()
|> Enum.map(&gps/1)
|> Enum.sum()
end
## calculations
defp boxes_coords(grid) do
grid
|> Enum.filter(&match?({_, c} when c in ["O", "["], &1))
|> Enum.map(&elem(&1, 0))
end
defp gps({x, y}), do: 100 * y + x
## movement
defp apply_moves(grid, moves) do
Enum.reduce(moves, grid, fn direction, grid ->
# it would be more efficient to keep track of this and move it around but
# this is much easier to manage
robot = find_robot(grid)
{_, grid} = apply_move(grid, robot, direction)
grid
end)
end
defp apply_move(grid, pos, direction, check_pair \\ true) do
dest = move(pos, direction)
case {Map.get(grid, pos), direction, check_pair} do
{"#", _, _} ->
{:error, grid}
# should never happen with the way inputs are constructed
{nil, _, _} ->
{:error, grid}
{".", _, _} ->
{:ok, grid}
# up and down movements of two-width boxes must be able to move both
# chars
{char, direction, true} when char in ["[", "]"] and direction in [:up, :down] ->
shift =
case char do
"[" -> :right
"]" -> :left
end
with {:ok, grid} <- apply_move(grid, move(pos, shift), direction, false),
{:ok, grid} <- apply_move(grid, dest, direction) do
grid =
grid
|> Map.put(dest, char)
|> Map.put(pos, ".")
{:ok, grid}
else
_ -> {:error, grid}
end
# left and right movements of two-width boxes are no different from
# one-width boxes
{char, _, _} when char in ["@", "O", "[", "]"] ->
with {:ok, grid} <- apply_move(grid, dest, direction) do
grid =
grid
|> Map.put(dest, char)
|> Map.put(pos, ".")
{:ok, grid}
end
end
end
defp find_robot(grid) do
{pos, "@"} = Enum.find(grid, &match?({_, "@"}, &1))
pos
end
## traversal
defp move({x, y}, :up), do: {x, y - 1}
defp move({x, y}, :down), do: {x, y + 1}
defp move({x, y}, :left), do: {x - 1, y}
defp move({x, y}, :right), do: {x + 1, y}
## input
defp read_input(input) do
[grid_input, moves_input] =
String.split(input, "\n\n")
grid = map_grid(grid_input)
moves =
moves_input
|> lines()
|> Enum.join()
|> String.graphemes()
|> Enum.map(fn
"^" -> :up
"v" -> :down
"<" -> :left
">" -> :right
end)
{grid, moves}
end
## output
# defp render(grid) do
# {{max_x, _}, _} = Enum.max_by(grid, fn {{x, _}, _} -> x end)
# {{_, max_y}, _} = Enum.max_by(grid, fn {{_, y}, _} -> y end)
# for y <- 0..max_y do
# line =
# for x <- 0..max_x, into: "" do
# Map.get(grid, {x, y})
# end
# IO.puts(line)
# end
# grid
# end
end

View file

@ -15,8 +15,8 @@
| [2021] | **43/50** 🌟 | Elixir |
| [2022] | **14/50** 🌟 | Elixir, Haskell |
| [2023] | **19/50** 🌟 | Elixir, Haskell |
| [2024] | **28/50** 🌟 | Elixir |
| **Total** | **184** 🌟| |
| [2024] | **30/50** 🌟 | Elixir |
| **Total** | **186** 🌟| |
[2015]: ./2015
[2017]: ./2017