Skip to content

Commit

Permalink
Solve 2023/23
Browse files Browse the repository at this point in the history
  • Loading branch information
code-shoily committed Dec 30, 2023
1 parent e490cf2 commit 72d36b2
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 4 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ Note that you can call those commands independently and also set up pre-commit h

Note: All files mentioned above are autogenerated and are created by running `mix update_stats` task.

## :trophy: 285/450
## :trophy: 287/450

| Day | [2015](/lib/2015) | [2016](/lib/2016) | [2017](/lib/2017) | [2018](/lib/2018) | [2019](/lib/2019) | [2020](/lib/2020) | [2021](/lib/2021) | [2022](/lib/2022) | [2023](/lib/2023) |
|:---:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| :star2: | 48 | 22 | 34 | 15 | 15 | 44 | 24 | 45 | 38 |
| :star2: | 48 | 22 | 34 | 15 | 15 | 44 | 24 | 45 | 40 |
| 1 | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: |
| 2 | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: |
| 3 | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: |
Expand All @@ -88,7 +88,7 @@ Note: All files mentioned above are autogenerated and are created by running `mi
| 20 | :1st_place_medal: | | | | | :2nd_place_medal: | | :1st_place_medal: | |
| 21 | :1st_place_medal: | | | | | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | |
| 22 | | | | | | :1st_place_medal: | | :2nd_place_medal: | |
| 23 | :1st_place_medal: | | :2nd_place_medal: | | | :2nd_place_medal: | | :1st_place_medal: | |
| 23 | :1st_place_medal: | | :2nd_place_medal: | | | :2nd_place_medal: | | :1st_place_medal: | :1st_place_medal: |
| 24 | :1st_place_medal: | | | | | :2nd_place_medal: | | :1st_place_medal: | :1st_place_medal: |
| 25 | :1st_place_medal: | | | | | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: | :1st_place_medal: |

Expand Down
1 change: 1 addition & 0 deletions difficulties.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ optimize them and update this page with refined and more accurate data.
| 2023/5 | [If You Give A Seed A Fertilizer](https://adventofcode.com/2023/day/5) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_05.ex](/lib/2023/day_05.ex) | [day_05_test.exs](/test/2023/day_05_test.exs) | [range](/tags.md#range), [gb-tree](/tags.md#gb-tree) |
| 2023/10 | [Pipe Maze](https://adventofcode.com/2023/day/10) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_10.ex](/lib/2023/day_10.ex) | [day_10_test.exs](/test/2023/day_10_test.exs) | [graph](/tags.md#graph), [graph-traversal](/tags.md#graph-traversal), [needs-improvement](/tags.md#needs-improvement), [not-fast-enough](/tags.md#not-fast-enough) |
| 2023/12 | [Hot Springs](https://adventofcode.com/2023/day/12) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_12.ex](/lib/2023/day_12.ex) | [day_12_test.exs](/test/2023/day_12_test.exs) | [memoization](/tags.md#memoization), [vector](/tags.md#vector) |
| 2023/23 | [A Long Walk](https://adventofcode.com/2023/day/23) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_23.ex](/lib/2023/day_23.ex) | [day_23_test.exs](/test/2023/day_23_test.exs) | [graph](/tags.md#graph), [longest-path](/tags.md#longest-path), [slow](/tags.md#slow), [refactor](/tags.md#refactor) |
| 2023/25 | [Snowverload](https://adventofcode.com/2023/day/25) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_25.ex](/lib/2023/day_25.ex) | [day_25_test.exs](/test/2023/day_25_test.exs) | [graph](/tags.md#graph), [min-cut](/tags.md#min-cut), [probabilistic](/tags.md#probabilistic), [refactor](/tags.md#refactor), [not-fast-enough](/tags.md#not-fast-enough) |

## xxl
Expand Down
3 changes: 2 additions & 1 deletion lib/2023/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[2015](/lib/2015) | [2016](/lib/2016) | [2017](/lib/2017) | [2018](/lib/2018) | [2019](/lib/2019) | [2020](/lib/2020) | [2021](/lib/2021) | [2022](/lib/2022) | 2023


## :trophy: 38/50
## :trophy: 40/50

| Day | Problem Page | Status | Difficulty | Solution Page | Test Page | Tags |
| :---: | :------: | :---: | :---: | :---: | :---: | :---: |
Expand All @@ -27,6 +27,7 @@
| 15 | [Lens Library](https://adventofcode.com/2023/day/15) | :1st_place_medal: | :snowflake: :snowflake: | [day_15.ex](/lib/2023/day_15.ex) | [day_15_test.exs](/test/2023/day_15_test.exs) | [hash](/tags.md#hash), [ordered-map](/tags.md#ordered-map) |
| 16 | [The Floor Will Be Lava](https://adventofcode.com/2023/day/16) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: | [day_16.ex](/lib/2023/day_16.ex) | [day_16_test.exs](/test/2023/day_16_test.exs) | [grid](/tags.md#grid), [grid-walk](/tags.md#grid-walk), [memoization](/tags.md#memoization) |
| 18 | [Lavaduct Lagoon](https://adventofcode.com/2023/day/18) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: | [day_18.ex](/lib/2023/day_18.ex) | [day_18_test.exs](/test/2023/day_18_test.exs) | [geometry](/tags.md#geometry) |
| 23 | [A Long Walk](https://adventofcode.com/2023/day/23) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_23.ex](/lib/2023/day_23.ex) | [day_23_test.exs](/test/2023/day_23_test.exs) | [graph](/tags.md#graph), [longest-path](/tags.md#longest-path), [slow](/tags.md#slow), [refactor](/tags.md#refactor) |
| 24 | [Never Tell Me The Odds](https://adventofcode.com/2023/day/24) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_24.ex](/lib/2023/day_24.ex) | [day_24_test.exs](/test/2023/day_24_test.exs) | [geometry2d](/tags.md#geometry2d), [refactor](/tags.md#refactor) |
| 25 | [Snowverload](https://adventofcode.com/2023/day/25) | :1st_place_medal: | :snowflake: :snowflake: :snowflake: :snowflake: :snowflake: | [day_25.ex](/lib/2023/day_25.ex) | [day_25_test.exs](/test/2023/day_25_test.exs) | [graph](/tags.md#graph), [min-cut](/tags.md#min-cut), [probabilistic](/tags.md#probabilistic), [refactor](/tags.md#refactor), [not-fast-enough](/tags.md#not-fast-enough) |

107 changes: 107 additions & 0 deletions lib/2023/day_23.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
defmodule AdventOfCode.Y2023.Day23 do
@moduledoc """
--- Day 23: A Long Walk ---
Problem Link: https://adventofcode.com/2023/day/23
Difficulty: xl
Tags: graph longest-path slow refactor
"""
alias AdventOfCode.Helpers.InputReader
alias AdventOfCode.Algorithms.Grid

def input, do: InputReader.read_from_file(2023, 23)

@start {0, 1}
@up {-1, 0}
@down {1, 0}
@left {0, -1}
@right {0, 1}
@slopes %{@up => "^", @down => "v", @left => "<", @right => ">"}

def run(input \\ input()) do
input = parse(input)

task_1 = Task.async(fn -> run_1(input) end)
task_2 = Task.async(fn -> run_2(input) end)

{Task.await(task_1, :infinity), Task.await(task_2, :infinity)}
end

def parse(data \\ input()) do
grid = Grid.text_to_grid2d(data)
{max_r, max_c} = Enum.max(Map.keys(grid))

{{max_r, max_c - 1}, edges(grid, [{@start, @down}], [])}
end

defp run_1({{_, _} = finish, edges}) do
edges
|> make_graph()
|> find_longest_path(@start, finish)
end

defp run_2({{_, _} = finish, edges}) do
edges
|> make_graph(:directed)
|> find_longest_path(@start, finish)
end

defp edges(_, [], es), do: es

defp edges(g, [{tile, dir} | todo], es) do
{{tr, tc}, dist, ntodo} = follow_path(g, [{tile, dir}], tile, 0)
ebgs = es |> Enum.map(fn {p, d, _, _} -> {p, d} end)
nftodo = Enum.filter(ntodo, fn {p, d} -> {p, d} not in ebgs and {p, d} not in todo end)

edges(g, todo ++ nftodo, [{tile, dir, {tr, tc}, dist} | es])
end

defp make_graph(edges, type \\ :undirected) do
for {f, _, t, w} <- edges, reduce: Graph.new() do
acc ->
acc
|> Graph.add_edge(f, t, weight: w)
|> then(fn graph ->
(type == :directed && Graph.add_edge(graph, t, f, weight: w)) || graph
end)
end
end

defp follow_path(g, [{tile, dir}], _, n) do
next_tile = follow(tile, dir)

if next_tile in Map.keys(g) do
dirs =
[@up, @down, @left, @right]
|> List.delete(opposite(dir))
|> Enum.map(fn d -> {d, g[follow(next_tile, d)]} end)
|> Enum.filter(fn {_, c} -> c != "#" and c != nil end)

dirs
|> Enum.filter(fn {d, c} -> c == "." or c == @slopes[d] end)
|> Enum.map(fn {d, _} -> {next_tile, d} end)
|> then(fn dir ->
(length(dirs) >= 2 && {next_tile, n + 1, dir}) ||
follow_path(g, dir, next_tile, n + 1)
end)
else
{tile, n, []}
end
end

defp follow_path(_, dir, ppt, n), do: {ppt, n, dir}
defp follow({a, b}, {c, d}), do: {a + c, b + d}
defp opposite({a, b}), do: {-a, -b}

defp path_length([a, b | rest], g, sum) do
wt = g |> Graph.edge(a, b) |> Map.get(:weight, 0)
path_length([b | rest], g, sum + wt)
end

defp path_length([_], _, sum), do: sum

defp find_longest_path(graph, start, finish) do
Graph.Pathfinding.all(graph, start, finish)
|> Stream.map(&path_length(&1, graph, 0))
|> Enum.max()
end
end
Loading

0 comments on commit 72d36b2

Please sign in to comment.