From 2debe381705ce88b53c73325088d403b023973e3 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] still fighting 2021 day 18

---
 2021/lib/2021/18.ex | 76 ++++++++++++++++++++++++++++-----------------
 1 file changed, 47 insertions(+), 29 deletions(-)

diff --git a/2021/lib/2021/18.ex b/2021/lib/2021/18.ex
index 3804639..08f2084 100644
--- a/2021/lib/2021/18.ex
+++ b/2021/lib/2021/18.ex
@@ -5,7 +5,11 @@ aoc 2021, 18 do
 
   def p1 do
     input()
-    |> Enum.reduce(fn x, acc -> reduce([acc, x]) end)
+    |> Enum.reduce(fn x, acc ->
+      result = reduce([acc, x])
+      IO.write(".")
+      result
+    end)
     |> magnitude()
   end
 
@@ -23,8 +27,8 @@ aoc 2021, 18 do
     recurse = op != :none
     result = apply_op(op, xs)
 
-    IO.inspect(op, label: "op")
-    IO.inspect(result, label: "result")
+    # IO.inspect(op, label: "op")
+    # IO.inspect(result, label: "result")
 
     if recurse, do: reduce(result), else: result
   end
@@ -43,39 +47,53 @@ aoc 2021, 18 do
   def apply_op(:none, xs), do: xs
   def apply_op({:explode, path}, xs) do
     case explode(path, xs) do
-      {_, xs} -> xs
+      # {_, xs} -> xs
       xs -> xs
     end
   end
   def apply_op({:split, path}, xs), do: split(path, xs)
 
-  def explode([:l], [a, b]) do
-    [l, r] = a
-    {{:l, l}, [0, add_car(b, r)]}
-  end
-  def explode([:r], [a, b]) do
-    [l, r] = b
-    {{:r, r}, [add_car(a, l), 0]}
-  end
-  def explode([:l | path], [a, b]) do
-    case explode(path, a) do
-      {{:r, r}, a} -> add_cdr([a, b], r)
-      {op, a} -> {op, [a, b]}
-      a -> [a, b]
-    end
-  end
-  def explode([:r | path], [a, b]) do
-    case explode(path, b) do
-      {{:l, l}, b} -> add_car([a, b], l)
-      {op, b} -> {op, [a, b]}
-      b -> [a, b]
-    end
+  def explode(path, xs) do
+    {adds, xs} = zero_out_exploded(path, xs)
+    add_exploded(path, adds, xs)
   end
 
-  def add_car([a, b], v), do: [add_cdr(a, v), b]
-  def add_car(car, v), do: car + v
-  def add_cdr([a, b], v), do: [a, add_car(b, v)]
-  def add_cdr(cdr, v), do: cdr + v
+  def zero_out_exploded([], [a, b]), do: {[a, b], 0}
+  def zero_out_exploded([:l | path], [a, b]) do
+    {ret, a} = zero_out_exploded(path, a)
+    {ret, [a, b]}
+  end
+  def zero_out_exploded([:r | path], [a, b]) do
+    {ret, b} = zero_out_exploded(path, b)
+    {ret, [a, b]}
+  end
+
+  def add_exploded([:r], [l, _], [a, b]) do
+    [add_r(a, l), b]
+  end
+  def add_exploded([:l], [_, r], [a, b]) do
+    [a, add_l(b, r)]
+  end
+  def add_exploded([:l | path], [_, r] = adds, [a, b]) do
+    if :l in path do
+      [add_exploded(path, adds, a), b]
+    else
+      [add_exploded(path, adds, a), add_l(b, r)]
+    end
+  end
+  def add_exploded([:r | path], [l, _] = adds, [a, b]) do
+    if :r in path do
+      [a, add_exploded(path, adds, b)]
+    else
+      [add_r(a, l), add_exploded(path, adds, a)]
+    end
+  end
+  def add_exploded(_, _, other), do: other
+
+  def add_r([a, b], n), do: [a, add_r(b, n)]
+  def add_r(b, n), do: b + n
+  def add_l([a, b], n), do: [add_l(a, n), b]
+  def add_l(a, n), do: a + n
 
   def split([], v) when is_even(v), do: [div(v, 2), div(v, 2)]
   def split([], v) when is_odd(v), do: [div(v, 2), div(v, 2) + 1]