From c14a9085410934cc45e418756ff3094c6992cc6c Mon Sep 17 00:00:00 2001
From: sloane <1699281+sloanelybutsurely@users.noreply.github.com>
Date: Sat, 9 Dec 2023 13:25:55 -0500
Subject: [PATCH] solve 2023 9.1

---
 2023/README.md                             |  3 ++-
 2023/lib/2023/9.ex                         | 31 ++++++++++++++++++++++
 2023/lib/{AOCHelpers.ex => aoc_helpers.ex} | 17 ++++++++++++
 README.md                                  |  2 +-
 4 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 2023/lib/2023/9.ex
 rename 2023/lib/{AOCHelpers.ex => aoc_helpers.ex} (69%)

diff --git a/2023/README.md b/2023/README.md
index 47ecd57..8059552 100644
--- a/2023/README.md
+++ b/2023/README.md
@@ -3,7 +3,7 @@
 |  S  |  M  |  T  |  W  |  T  |  F  |  S  |
 | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
 |     |     |     |     |     | [1] | [2] |
-| [3] | [4] | [5] |  6  | [7] | [8] |  9  |
+| [3] | [4] | [5] |  6  | [7] | [8] | [9] |
 | 10  | 11  | 12  | 13  | 14  | 15  | 16  |
 | 17  | 18  | 19  | 20  | 21  | 22  | 23  |
 | 24  | 25  |     |     |     |     |     |
@@ -17,3 +17,4 @@
 <!-- [6]: ./lib/2023/6.ex -->
 [7]: ./lib/2023/7.ex
 [8]: ./lib/2023/8.ex
+[9]: ./lib/2023/9.ex
diff --git a/2023/lib/2023/9.ex b/2023/lib/2023/9.ex
new file mode 100644
index 0000000..01da81e
--- /dev/null
+++ b/2023/lib/2023/9.ex
@@ -0,0 +1,31 @@
+import AOC
+import AOCHelpers
+
+aoc 2023, 9 do
+  def p1(input) do
+    input
+    |> lines_of_integers()
+    |> Enum.map(&next_in_sequence/1)
+    |> Enum.sum()
+  end
+
+  def p2(_input) do
+  end
+
+  def next_in_sequence(xs) do
+    xs
+    |> differentiate()
+    |> Enum.map(&List.last/1)
+    |> Enum.sum()
+  end
+
+  def differentiate(xs) do
+    xs
+    |> Stream.iterate(&deltas/1)
+    |> Enum.take_while(&(not all_zeros?(&1)))
+  end
+
+  def deltas(xs), do: Enum.zip_with(xs, Enum.drop(xs, 1), &(&2 - &1))
+
+  def all_zeros?(xs), do: Enum.all?(xs, is?(0))
+end
diff --git a/2023/lib/AOCHelpers.ex b/2023/lib/aoc_helpers.ex
similarity index 69%
rename from 2023/lib/AOCHelpers.ex
rename to 2023/lib/aoc_helpers.ex
index b96f17e..16e0df5 100644
--- a/2023/lib/AOCHelpers.ex
+++ b/2023/lib/aoc_helpers.ex
@@ -11,6 +11,22 @@ defmodule AOCHelpers do
     String.split(str, "", trim: true)
   end
 
+  def integers(str) when is_binary(str) do
+    str
+    |> words()
+    |> integers()
+  end
+
+  def integers(ws) when is_list(ws) do
+    Enum.map(ws, &String.to_integer/1)
+  end
+
+  def lines_of_integers(input) do
+    input
+    |> lines()
+    |> Enum.map(&integers/1)
+  end
+
   @doc """
   Take a list of terms and a list of 1-arity functions and apply each function
   to the coresponding term in the list of terms.
@@ -27,4 +43,5 @@ defmodule AOCHelpers do
 
   def id(x), do: x
   def always(x), do: fn -> x end
+  def is?(x), do: &(&1 == x)
 end
diff --git a/README.md b/README.md
index d5cc989..ec67642 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
 1. [2020] **17/50** 🌟
 1. [2021] **43/50** 🌟
 1. [2022] **14/50** 🌟
-1. [2023] **13/50** 🌟
+1. [2023] **14/50** 🌟
 
 [2015]: ./2015
 [2017]: ./2017