From fbf79992097520c152a4a53960463939e5a8af87 Mon Sep 17 00:00:00 2001
From: sloane <git@sloanelybutsurely.com>
Date: Thu, 28 Nov 2024 19:33:42 -0500
Subject: [PATCH] solve 2015 day 23
---
2015/README.md | 14 ++---
2015/lib/2015/23.ex | 121 ++++++++++++++++++++++++++++++++++++++++++++
README.md | 2 +-
3 files changed, 130 insertions(+), 7 deletions(-)
create mode 100644 2015/lib/2015/23.ex
diff --git a/2015/README.md b/2015/README.md
index a0ee495..cf82aec 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
@@ -40,3 +40,5 @@
[19]: ./lib/2015/19.ex
[20]: ./lib/2015/20.ex
[21]: ./lib/2015/21.ex
+
+[23]: ./lib/2015/23.ex
diff --git a/2015/lib/2015/23.ex b/2015/lib/2015/23.ex
new file mode 100644
index 0000000..42b33b0
--- /dev/null
+++ b/2015/lib/2015/23.ex
@@ -0,0 +1,121 @@
+import AOC
+
+aoc 2015, 23 do
+ defmodule Program do
+ import Integer, only: [is_even: 1]
+
+ @enforce_keys [:instructions]
+ defstruct [:instructions, ptr: 0, a: 0, b: 0]
+
+ def new(inp) do
+ instructions =
+ for {line, idx} <- Enum.with_index(inp), into: %{} do
+ {idx, parse_line(line)}
+ end
+
+ %Program{instructions: instructions}
+ end
+
+ def run(%Program{ptr: ptr, instructions: instructions} = prgm) do
+ case Map.fetch(instructions, ptr) do
+ {:ok, inst} ->
+ prgm
+ |> exec_inst(inst)
+ |> run()
+
+ :error ->
+ prgm
+ end
+ end
+
+ defp exec_inst(prgm, {:hlf, r}) do
+ prgm
+ |> update!(r, &div(&1, 2))
+ |> step()
+ end
+
+ defp exec_inst(prgm, {:tpl, r}) do
+ prgm
+ |> update!(r, &(&1 * 3))
+ |> step()
+ end
+
+ defp exec_inst(prgm, {:inc, r}) do
+ prgm
+ |> update!(r, &(&1 + 1))
+ |> step()
+ end
+
+ defp exec_inst(prgm, {:jmp, offset}) do
+ update!(prgm, :ptr, &(&1 + offset))
+ end
+
+ defp exec_inst(prgm, {:jie, r, offset}) do
+ if prgm |> fetch!(r) |> is_even() do
+ update!(prgm, :ptr, &(&1 + offset))
+ else
+ step(prgm)
+ end
+ end
+
+ defp exec_inst(prgm, {:jio, r, offset}) do
+ if fetch!(prgm, r) == 1 do
+ update!(prgm, :ptr, &(&1 + offset))
+ else
+ step(prgm)
+ end
+ end
+
+ def reg(%Program{} = prgm, r) do
+ prgm
+ |> Map.get(reg_key(r))
+ end
+
+ defp reg_key("a"), do: :a
+ defp reg_key("b"), do: :b
+ defp reg_key(other), do: other
+
+ defp update!(%Program{} = prgm, r, fun) do
+ Map.update!(prgm, reg_key(r), fun)
+ end
+
+ def fetch!(%Program{} = prgm, r) do
+ Map.fetch!(prgm, reg_key(r))
+ end
+
+ defp step(prgm), do: update!(prgm, :ptr, &(&1 + 1))
+
+ defp parse_line("hlf " <> r), do: {:hlf, r}
+ defp parse_line("tpl " <> r), do: {:tpl, r}
+ defp parse_line("inc " <> r), do: {:inc, r}
+ defp parse_line("jmp +" <> offset), do: {:jmp, String.to_integer(offset)}
+ defp parse_line("jmp -" <> offset), do: {:jmp, 0 - String.to_integer(offset)}
+
+ defp parse_line(<<"jie ", <<r::binary-size(1)>>, ", +", offset::binary>>),
+ do: {:jie, r, String.to_integer(offset)}
+
+ defp parse_line(<<"jie ", <<r::binary-size(1)>>, ", -", offset::binary>>),
+ do: {:jie, r, 0 - String.to_integer(offset)}
+
+ defp parse_line(<<"jio ", <<r::binary-size(1)>>, ", +", offset::binary>>),
+ do: {:jio, r, String.to_integer(offset)}
+
+ defp parse_line(<<"jio ", <<r::binary-size(1)>>, ", -", offset::binary>>),
+ do: {:jio, r, 0 - String.to_integer(offset)}
+ end
+
+ def p1 do
+ input_stream()
+ |> Program.new()
+ |> Program.run()
+ |> Program.fetch!(:b)
+ end
+
+ def p2 do
+ input_stream()
+ |> Program.new()
+ |> Map.put(:a, 1)
+ |> Program.run()
+ |> Program.fetch!(:b)
+ end
+end
diff --git a/README.md b/README.md
index cced555..a90a087 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
| Year | Stars | Languages |
| - | - | - |
-| [2015] | **42/50** 🌟 | Elixir |
+| [2015] | **44/50** 🌟 | Elixir |
| 2016 | | |
| [2017] | **18/50** 🌟 | Haskell |
| 2018 | | |