diff --git a/README.md b/README.md index 2475549..1310162 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ My Elixir solutions for [Advent of Code](https://adventofcode.com/) (all years). -
diff --git a/lib/y2024/README.md b/lib/y2024/README.md
index 4cfba37..f7ca1f4 100644
--- a/lib/y2024/README.md
+++ b/lib/y2024/README.md
@@ -2,7 +2,7 @@
My Elixir solutions for [Advent of Code 2024](https://adventofcode.com/2024).
-
+
## Benchmarks
@@ -31,4 +31,5 @@ day 07, part 2 14.76 67.73 ms ±1.35% 67.51 ms 71.
day 08, part 1 1.07 K 0.93 ms ±6.91% 0.90 ms 1.07 ms
day 08, part 2 0.83 K 1.20 ms ±7.78% 1.17 ms 1.38 ms
day 09, part 1 9.27 107.87 ms ±0.84% 107.61 ms 111.83 ms
+day 09, part 2 0.23 4.43 s ±0.12% 4.43 s 4.43 s
```
diff --git a/lib/y2024/day09.ex b/lib/y2024/day09.ex
index d90316f..88b8246 100644
--- a/lib/y2024/day09.ex
+++ b/lib/y2024/day09.ex
@@ -42,13 +42,64 @@ defmodule Y2024.Day09 do
|> elem(1)
end
- # @doc """
- # iex> Day09.part2("update or delete me")
- # "update or delete me"
- # """
- # def part2(input) do
- # input
- # end
+ @doc """
+ iex> Day09.part2(Integer.digits(2333133121414131402))
+ 2858
+ """
+ def part2(input) do
+ input
+ |> Enum.reduce({0, true, []}, fn num, {file_id, fill?, list} ->
+ type = if fill?, do: :fill, else: :gap
+ next_file_id = if fill?, do: file_id + 1, else: file_id
+ {next_file_id, !fill?, [%{type: type, file_id: file_id, num: num} | list]}
+ end)
+ |> elem(2)
+ |> Enum.reverse()
+ |> defrag([])
+ |> Enum.reduce({0, 0}, fn record, {index, acc} ->
+ if record.type == :gap do
+ {index + record.num, acc}
+ else
+ acc =
+ Enum.reduce(0..(record.num - 1), acc, fn sub_index, acc ->
+ acc + (index + sub_index) * record.file_id
+ end)
+
+ {index + record.num, acc}
+ end
+ end)
+ |> elem(1)
+ end
+
+ defp defrag([], list), do: Enum.reverse(list)
+
+ defp defrag([%{type: :fill} = head | tail], list) do
+ defrag(tail, [head | list])
+ end
+
+ defp defrag([%{type: :gap, num: num} = head | tail], list) do
+ filler =
+ Enum.find(Enum.reverse(tail), fn %{num: check_num, type: type} ->
+ type == :fill && check_num <= num
+ end)
+
+ if filler do
+ list = [filler | list]
+
+ tail =
+ Enum.map(tail, fn record ->
+ if record == filler, do: %{type: :gap, num: filler.num}, else: record
+ end)
+
+ if num - filler.num == 0 do
+ defrag(tail, list)
+ else
+ defrag([%{type: :gap, num: num - filler.num} | tail], list)
+ end
+ else
+ defrag(tail, [head | list])
+ end
+ end
def parse_input(input) do
input
@@ -58,5 +109,5 @@ defmodule Y2024.Day09 do
end
def part1_verify, do: input() |> parse_input() |> part1()
- # def part2_verify, do: input() |> parse_input() |> part2()
+ def part2_verify, do: input() |> parse_input() |> part2()
end
diff --git a/test/y2024/day09_test.exs b/test/y2024/day09_test.exs
index 1a59267..62e0d1f 100644
--- a/test/y2024/day09_test.exs
+++ b/test/y2024/day09_test.exs
@@ -4,5 +4,5 @@ defmodule Y2024.Day09Test do
doctest Day09
test "verification, part 1", do: assert(Day09.part1_verify() == 6_241_633_730_082)
- # test "verification, part 2", do: assert(Day09.part2_verify() == "update or delete me")
+ test "verification, part 2", do: assert(Day09.part2_verify() == 6_265_268_809_555)
end