From db20c890515766a5f95f62ec76623551858630c4 Mon Sep 17 00:00:00 2001 From: sloane Date: Fri, 6 Dec 2024 07:12:55 -0500 Subject: [PATCH] solve 2024 day 6 --- 2024/README.md | 3 +- 2024/lib/2024/6.ex | 126 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 2024/lib/2024/6.ex diff --git a/2024/README.md b/2024/README.md index c27a947..3bc4c6b 100644 --- a/2024/README.md +++ b/2024/README.md @@ -2,7 +2,7 @@ | 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 | | 15 | 16 | 17 | 18 | 19 | 20 | 21 | | 22 | 23 | 24 | 25 | | | | @@ -12,3 +12,4 @@ [3]: ./lib/2024/3.ex [4]: ./lib/2024/4.ex [5]: ./lib/2024/5.ex +[6]: ./lib/2024/6.ex diff --git a/2024/lib/2024/6.ex b/2024/lib/2024/6.ex new file mode 100644 index 0000000..5b37556 --- /dev/null +++ b/2024/lib/2024/6.ex @@ -0,0 +1,126 @@ +import AOC + +aoc 2024, 6 do + defmodule State do + @moduledoc false + defstruct [:pos, :dir, grid: %{}, visited: MapSet.new(), visited_pos_and_dir: MapSet.new(), looped?: false] + end + + def p1(input) do + %State{} = + final_state = + input + |> read_state() + |> simulate() + + MapSet.size(final_state.visited) + end + + def p2(input) do + %State{} = state = read_state(input) + + in_front_of_guard = forward(state).pos + + for pos <- Map.keys(state.grid), pos != in_front_of_guard, not blocked?(state, pos), reduce: 0 do + sum -> + if (state + |> insert_obstacle(pos) + |> simulate()).looped? do + sum + 1 + else + sum + end + end + end + + defp insert_obstacle(%State{grid: grid} = state, pos), do: %State{state | grid: Map.put(grid, pos, "#")} + + ## simulation + + defp simulate(%State{} = state) do + state + |> Stream.iterate(&step/1) + |> Stream.drop_while(&(in_bounds?(&1) and not &1.looped?)) + |> Stream.take(1) + |> Enum.at(0) + end + + defp step(%State{} = state) do + next = forward(state) + + cond do + blocked?(next) -> + rotate_90(state) + + MapSet.member?(state.visited_pos_and_dir, {next.pos, next.dir}) -> + %State{state | looped?: true} + + true -> + visit(next) + end + end + + defp in_bounds?(%State{grid: grid, pos: pos}), do: Map.has_key?(grid, pos) + + defp blocked?(%State{pos: pos} = state), do: blocked?(state, pos) + defp blocked?(%State{grid: grid}, pos), do: Map.get(grid, pos) == "#" + + defp forward(%State{dir: :up, pos: {i, j}} = state), do: %State{state | pos: {i, j - 1}} + defp forward(%State{dir: :down, pos: {i, j}} = state), do: %State{state | pos: {i, j + 1}} + defp forward(%State{dir: :left, pos: {i, j}} = state), do: %State{state | pos: {i - 1, j}} + defp forward(%State{dir: :right, pos: {i, j}} = state), do: %State{state | pos: {i + 1, j}} + + defp rotate_90(%State{dir: :up} = state), do: %State{state | dir: :right} + defp rotate_90(%State{dir: :right} = state), do: %State{state | dir: :down} + defp rotate_90(%State{dir: :down} = state), do: %State{state | dir: :left} + defp rotate_90(%State{dir: :left} = state), do: %State{state | dir: :up} + + defp visit(%State{pos: pos, dir: dir, visited: visited, visited_pos_and_dir: visited_pos_and_dir} = state) do + if in_bounds?(state) do + %State{ + state + | visited: MapSet.put(visited, pos), + visited_pos_and_dir: MapSet.put(visited_pos_and_dir, {pos, dir}) + } + else + state + end + end + + ## input + + defp read_state(input) do + lines = + input + |> String.split("\n") + |> Enum.map(&String.graphemes/1) + + for {line, y} <- Enum.with_index(lines), + {c, x} <- Enum.with_index(line), + reduce: %State{} do + %State{grid: grid, pos: nil, dir: nil} -> + dir = + case c do + "^" -> :up + ">" -> :right + "<" -> :left + "v" -> :down + _ -> nil + end + + if is_nil(dir) do + %State{grid: Map.put(grid, {x, y}, c)} + else + %State{ + grid: Map.put(grid, {x, y}, "."), + dir: dir, + pos: {x, y}, + visited: MapSet.new([{x, y}]) + } + end + + %State{grid: grid} = state -> + %State{state | grid: Map.put(grid, {x, y}, c)} + end + end +end diff --git a/README.md b/README.md index 1640c5d..25b00d7 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ | [2021] | **43/50** 🌟 | Elixir | | [2022] | **14/50** 🌟 | Elixir, Haskell | | [2023] | **19/50** 🌟 | Elixir, Haskell | -| [2024] | **10/50** 🌟 | Elixir | +| [2024] | **12/50** 🌟 | Elixir | | **Total** | **162** 🌟| | [2015]: ./2015