From 9d4492391c9d86fb28b2ca9a92a4c022062022d1 Mon Sep 17 00:00:00 2001
From: Sloane Perrault <sloane.perrault@gmail.com>
Date: Wed, 21 Sep 2022 09:19:53 -0400
Subject: [PATCH] solve day 5

---
 2021/README.md     |  3 ++-
 2021/lib/2021/5.ex | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 2021/mix.exs       |  1 +
 2021/mix.lock      |  1 +
 4 files changed, 70 insertions(+), 1 deletion(-)
 create mode 100644 2021/lib/2021/5.ex

diff --git a/2021/README.md b/2021/README.md
index 2a3d671..4d4b08f 100644
--- a/2021/README.md
+++ b/2021/README.md
@@ -15,7 +15,7 @@
 |  S  |  M  |  T  |  W  |  T  |  F  |  S  |
 | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
 |     |     |     | [1] | [2] | [3] | [4] |
-|  5  |  6  |  7  |  8  |  9  | 10  | 11  |
+| [5] |  6  |  7  |  8  |  9  | 10  | 11  |
 | 12  | 13  | 14  | 15  | 16  | 17  | 18  |
 | 19  | 20  | 21  | 22  | 23  | 24  | 25  |
 
@@ -25,3 +25,4 @@
 [2]: ./lib/2021/2.ex
 [3]: ./lib/2021/3.ex
 [4]: ./lib/2021/4.ex
+[5]: ./lib/2021/5.ex
diff --git a/2021/lib/2021/5.ex b/2021/lib/2021/5.ex
new file mode 100644
index 0000000..eb976c5
--- /dev/null
+++ b/2021/lib/2021/5.ex
@@ -0,0 +1,66 @@
+import AOC
+
+aoc 2021, 5 do
+  import NimbleParsec
+
+  defparsec(
+    :vent_readout_parsec,
+    integer(min: 1)
+    |> ignore(string(","))
+    |> integer(min: 1)
+    |> ignore(string(" -> "))
+    |> integer(min: 1)
+    |> ignore(string(","))
+    |> integer(min: 1)
+  )
+
+  def parse_vent_readout(line) do
+    {:ok, [x1, y1, x2, y2], _, _, _, _} = line |> vent_readout_parsec()
+
+    {{x1, y1}, {x2, y2}}
+  end
+
+  def input_stream(), do: super() |> Stream.map(&parse_vent_readout/1)
+
+  def p1 do
+    input_stream()
+    |> Enum.reduce(Map.new(), &record_line_on_map(&1, &2, false))
+    |> Map.values()
+    |> Enum.count(&(&1 > 1))
+  end
+
+  def p2 do
+    input_stream()
+    |> Enum.reduce(Map.new(), &record_line_on_map(&1, &2, true))
+    |> Map.values()
+    |> Enum.count(&(&1 > 1))
+  end
+
+  def record_line_on_map(line, map, include_diagonals),
+    do:
+      map
+      |> record_points_on_map(points_on_line(line, include_diagonals))
+
+  def record_points_on_map(map, points) do
+    for point <- points, reduce: map do
+      map -> Map.update(map, point, 1, &(&1 + 1))
+    end
+  end
+
+  # vertical lines
+  def points_on_line({{x, y1}, {x, y2}}, _) do
+    for y <- y1..y2, do: {x, y}
+  end
+
+  # horizontal lines
+  def points_on_line({{x1, y}, {x2, y}}, _) do
+    for x <- x1..x2, do: {x, y}
+  end
+
+  # diagonal lines
+  def points_on_line({{x1, y1}, {x2, y2}}, true) do
+    Enum.zip(x1..x2, y1..y2)
+  end
+
+  def points_on_line(_, false), do: []
+end
diff --git a/2021/mix.exs b/2021/mix.exs
index 25c1fd7..f481363 100644
--- a/2021/mix.exs
+++ b/2021/mix.exs
@@ -28,6 +28,7 @@ defmodule AdventOfCode.MixProject do
       {:advent_of_code_utils, "~> 1.0"},
       {:benchee, "~> 1.0", only: :dev},
       {:exla, "~> 0.1.0-dev", github: "elixir-nx/nx", sparse: "exla"},
+      {:nimble_parsec, "~> 1.0"},
       {:nx, "~> 0.1.0-dev", github: "elixir-nx/nx", sparse: "nx", override: true}
     ]
   end
diff --git a/2021/mix.lock b/2021/mix.lock
index c21d716..d91fa9d 100644
--- a/2021/mix.lock
+++ b/2021/mix.lock
@@ -11,6 +11,7 @@
   "mint": {:hex, :mint, "1.4.0", "cd7d2451b201fc8e4a8fd86257fb3878d9e3752899eb67b0c5b25b180bde1212", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "10a99e144b815cbf8522dccbc8199d15802440fc7a64d67b6853adb6fa170217"},
   "mix_test_interactive": {:hex, :mix_test_interactive, "1.1.0", "e3e048ea8b56637c8e5614044483e11d78f81f70e9afb811c06ad3db69704c32", [:mix], [{:file_system, "~> 0.2", [hex: :file_system, repo: "hexpm", optional: false]}, {:typed_struct, "~> 0.2.1", [hex: :typed_struct, repo: "hexpm", optional: false]}], "hexpm", "2288a2edc735ca4879a7c17b9fd9fd4b8b84a57a775c3228db4655806a0a4799"},
   "nimble_options": {:hex, :nimble_options, "0.3.7", "1e52dd7673d36138b1a5dede183b5d86dff175dc46d104a8e98e396b85b04670", [:mix], [], "hexpm", "2086907e6665c6b6579be54ef5001928df5231f355f71ed258f80a55e9f63633"},
+  "nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"},
   "nimble_pool": {:hex, :nimble_pool, "0.2.4", "1db8e9f8a53d967d595e0b32a17030cdb6c0dc4a451b8ac787bf601d3f7704c3", [:mix], [], "hexpm", "367e8071e137b787764e6a9992ccb57b276dc2282535f767a07d881951ebeac6"},
   "nx": {:git, "https://github.com/elixir-nx/nx.git", "e23a678bf0ebcbbafe03f1b5ed78623f052ad486", [sparse: "nx"]},
   "progress_bar": {:hex, :progress_bar, "2.0.1", "7b40200112ae533d5adceb80ff75fbe66dc753bca5f6c55c073bfc122d71896d", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "2519eb58a2f149a3a094e729378256d8cb6d96a259ec94841bd69fdc71f18f87"},