Skip to content

Commit

Permalink
2023 day 17, part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
sevenseacat committed Dec 17, 2023
1 parent d4e1a21 commit 2620576
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
My Elixir solutions for [Advent of Code](https://adventofcode.com/) (all years).

<!-- stars start -->
<p><a href="./lib/y2023/"><img src="https://img.shields.io/static/v1?label=2023&message=32%20stars&style=for-the-badge&color=yellow" alt="32 stars" /></a><br />
<p><a href="./lib/y2023/"><img src="https://img.shields.io/static/v1?label=2023&message=33%20stars&style=for-the-badge&color=yellow" alt="33 stars" /></a><br />
<a href="./lib/y2022/"><img src="https://img.shields.io/static/v1?label=2022&message=%E2%AD%90%EF%B8%8F%2050%20stars%20%E2%AD%90%EF%B8%8F&style=for-the-badge&color=brightgreen" alt="50 stars" /></a><br />
<a href="./lib/y2021/"><img src="https://img.shields.io/static/v1?label=2021&message=46%20stars&style=for-the-badge&color=green" alt="46 stars" /></a><br />
<a href="./lib/y2020/"><img src="https://img.shields.io/static/v1?label=2020&message=39%20stars&style=for-the-badge&color=yellow" alt="39 stars" /></a><br />
Expand Down
2 changes: 1 addition & 1 deletion lib/advent/grid.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ defmodule Advent.Grid do
end

defp colour(char) do
IO.ANSI.red() <> char <> IO.ANSI.reset()
IO.ANSI.color(4, 0, 5) <> "#{char}" <> IO.ANSI.reset()
end
end
3 changes: 2 additions & 1 deletion lib/y2023/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

My Elixir solutions for [Advent of Code 2023](https://adventofcode.com/2023).

<!-- stars 2023 start --><img src="https://img.shields.io/static/v1?label=2023&message=32%20stars&style=for-the-badge&color=yellow" alt="32 stars" /><!-- stars 2023 end -->
<!-- stars 2023 start --><img src="https://img.shields.io/static/v1?label=2023&message=33%20stars&style=for-the-badge&color=yellow" alt="33 stars" /><!-- stars 2023 end -->

## Benchmarks

Expand Down Expand Up @@ -47,4 +47,5 @@ day 15, part 1 1.97 K 0.51 ms ±58.77% 0.47 ms 1.
day 15, part 2 0.39 K 2.57 ms ±9.13% 2.56 ms 3.05 ms
day 16, part 1 97.00 10.31 ms ±14.20% 10.08 ms 13.65 ms
day 16, part 2 2.07 483.12 ms ±2.51% 482.96 ms 503.06 ms
day 17, part 1 1.42 704.79 ms ±2.71% 713.38 ms 719.67 ms
```
102 changes: 102 additions & 0 deletions lib/y2023/day17.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
defmodule Y2023.Day17 do
use Advent.Day, no: 17

alias Advent.Grid

def part1(grid) do
find_best_path(grid, {1, 1})
end

# @doc """
# iex> Day17.part2("update or delete me")
# "update or delete me"
# """
# def part2(input) do
# input
# end

defp find_best_path(grid, {row, col}) do
PriorityQueue.new()
|> add_to_queue([[{row, col, nil, 0}]])
|> search(grid, Grid.size(grid), MapSet.new())
end

defp add_to_queue(queue, states) do
Enum.reduce(states, queue, fn state, queue ->
PriorityQueue.push(queue, state, elem(hd(state), 3))
end)
end

defp search(queue, grid, destination, cache) do
do_search(PriorityQueue.pop(queue), grid, destination, cache)
end

defp do_search({:empty, _queue}, _grid, _destination, _cache) do
raise("No path found")
end

defp do_search(
{{:value, [{row, col, _direction, count} | _rest]}, _queue},
_grid,
{row, col},
_cache
) do
# Winner winner chicken dinner.
count
end

defp do_search({{:value, path}, queue}, grid, destination, cache) do
if MapSet.member?(cache, cache_key(path)) do
# Been here before at a lower heat loss value, ignore
search(queue, grid, destination, cache)
else
cache = MapSet.put(cache, cache_key(path))

queue
|> add_to_queue(valid_moves(path, grid))
|> search(grid, destination, cache)
end
end

defp valid_moves([{row, col, direction, value} | _rest] = path, grid) do
[{row - 1, col, :up}, {row + 1, col, :down}, {row, col - 1, :left}, {row, col + 1, :right}]
|> Enum.filter(&in_grid?(grid, &1))
|> Enum.reject(&backwards?(direction, &1))
|> Enum.reject(&too_far_straight?(path, &1))
|> Enum.map(fn {row, col, dir} ->
[{row, col, dir, value + Map.fetch!(grid, {row, col})} | path]
end)
end

defp cache_key([{row, col, direction, _} | _rest] = path) do
# The cache key has to include the last three directions
# Something going | may give a different result to --
# |- |
# even with the same current value, due to the straight run length
# limitation
next_cache = Enum.take_while(path, fn {_, _, dir, _} -> dir == direction end) |> length()
{{row, col, direction}, next_cache}
end

defp in_grid?(grid, {row, col, _dir}), do: Map.has_key?(grid, {row, col})

defp backwards?(from, {_, _, to}) do
{from, to} in [{:left, :right}, {:right, :left}, {:up, :down}, {:down, :up}]
end

defp too_far_straight?([{_, _, dir, _}, {_, _, dir, _}, {_, _, dir, _} | _rest], {_, _, dir}) do
true
end

defp too_far_straight?(_, _), do: false

def parse_input(input) do
input
|> Grid.new()
|> Enum.map(fn {a, b} -> {a, String.to_integer(b)} end)
|> Enum.into(%{})
end

def part1_verify, do: input() |> parse_input() |> part1()
# def part2_verify, do: input() |> parse_input() |> part2()
end
Binary file added lib/y2023/input/day17.txt
Binary file not shown.
29 changes: 29 additions & 0 deletions test/y2023/day17_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Y2023.Day17Test do
use ExUnit.Case, async: true
alias Y2023.Day17
doctest Day17

test "verification, part 1", do: assert(Day17.part1_verify() == 886)
# test "verification, part 2", do: assert(Day17.part2_verify() == "update or delete me")

@sample_input """
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533
"""

test "part 1" do
actual = Day17.parse_input(@sample_input) |> Day17.part1()
assert 102 == actual
end
end

0 comments on commit 2620576

Please sign in to comment.