From abdcf1d9820a60c0987ae51c2db1d980820f2beb 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 2015 day 11

---
 2015/README.md      | 13 +++++-----
 2015/lib/2015/11.ex | 63 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 6 deletions(-)
 create mode 100644 2015/lib/2015/11.ex

diff --git a/2015/README.md b/2015/README.md
index bcb8be2..d1e2675 100644
--- a/2015/README.md
+++ b/2015/README.md
@@ -12,12 +12,12 @@
   ```
 </details>
 
-|  S  |  M  |  T  |  W  |  T  |  F  |  S  |
-| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
-|     |     | [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  |     |
+|  S  |  M  |  T  |  W  |  T   |  F   |  S  |
+| :-: | :-: | :-: | :-: | :-:  | :-:  | :-: |
+|     |     | [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   |     |
 
 [1]: ./lib/2015/1.ex
 [2]: ./lib/2015/2.ex
@@ -29,3 +29,4 @@
 [8]: ./lib/2015/8.ex
 [9]: ./lib/2015/9.ex
 [10]: ./lib/2015/10.ex
+[11]: ./lib/2015/11.ex
diff --git a/2015/lib/2015/11.ex b/2015/lib/2015/11.ex
new file mode 100644
index 0000000..c7001b4
--- /dev/null
+++ b/2015/lib/2015/11.ex
@@ -0,0 +1,63 @@
+import AOC
+
+aoc 2015, 11 do
+  def is_valid_password?(password) do
+    includes_increasing_straight_of_three(password) and
+      does_not_contain_iol(password) and
+      includes_two_pairs_of_double_letters(password)
+  end
+
+  def includes_increasing_straight_of_three(b) when is_binary(b),
+    do:
+      String.to_charlist(b)
+      |> includes_increasing_straight_of_three()
+
+  def includes_increasing_straight_of_three([a, b, c | _])
+      when a == b - 1 and b == c - 1,
+      do: true
+
+  def includes_increasing_straight_of_three([_ | rest]),
+    do: includes_increasing_straight_of_three(rest)
+
+  def includes_increasing_straight_of_three(_), do: false
+
+  def does_not_contain_iol(password) do
+    not String.match?(password, ~r/[iol]/)
+  end
+
+  def includes_two_pairs_of_double_letters(password) do
+    String.match?(password, ~r/(\w)\1.*(\w)\2/)
+  end
+
+  def increment_password(password) when is_binary(password),
+    do:
+      password
+      |> String.to_charlist()
+      |> Enum.reverse()
+      |> increment_password()
+      |> Enum.reverse()
+      |> IO.chardata_to_string()
+
+  def increment_password([]), do: [?a]
+  def increment_password([?z | rest]), do: [?a | increment_password(rest)]
+  def increment_password([c | rest]), do: [c + 1 | rest]
+
+  def compute_next_password(current_password) do
+    candidate = increment_password(current_password)
+
+    if is_valid_password?(candidate) do
+      candidate
+    else
+      compute_next_password(candidate)
+    end
+  end
+
+  def p1 do
+    input_string()
+    |> String.trim()
+    |> compute_next_password()
+  end
+
+  def p2 do
+  end
+end