diff --git a/2022/README.md b/2022/README.md
index 629546f..c97a2ee 100644
--- a/2022/README.md
+++ b/2022/README.md
@@ -2,7 +2,7 @@
My (attempted) solutions to [Advent of Code 2022](https://adventofcode.com/2022) in Elixir.
-
+
## Running:
diff --git a/2022/day10.exs b/2022/day10.exs
new file mode 100644
index 0000000..66f1ab1
--- /dev/null
+++ b/2022/day10.exs
@@ -0,0 +1,109 @@
+defmodule Day10 do
+ defmodule Instr do
+ defstruct cmd: nil, cycles: 0, amt: nil
+ end
+
+ def part1(input) do
+ process(input, _cycle = 1, _x = 1, _sample_at = 20, _sig = 0)
+ end
+
+ defp process([], _cycle, _x, _sample_at, sig), do: sig
+
+ defp process(instrs, cycle, x, sample_at, sig) when cycle == sample_at do
+ process(instrs, cycle, x, sample_at + 40, sig + cycle * x)
+ end
+
+ defp process([%Instr{cycles: 0} | rest], cycle, x, sample_at, sig) do
+ process(rest, cycle + 1, x, sample_at, sig)
+ end
+
+ defp process([instr = %Instr{cycles: 1, cmd: :noop} | rest], cycle, x, sample_at, sig) do
+ process([%Instr{instr | cycles: 0} | rest], cycle, x, sample_at, sig)
+ end
+
+ defp process([instr = %Instr{cycles: 1, cmd: :addx, amt: amt} | rest], cycle, x, sample_at, sig) do
+ process([%Instr{instr | cycles: 0} | rest], cycle, x + amt, sample_at, sig)
+ end
+
+ defp process([instr = %Instr{cycles: cycles} | rest], cycle, x, sample_at, sig) do
+ process([%Instr{instr | cycles: cycles - 1} | rest], cycle + 1, x, sample_at, sig)
+ end
+
+ def part2(input) do
+ input
+ |> scan(_x = 1, _pixel = 0, _pixels = [[]])
+ |> Enum.map(&Enum.reverse/1)
+ |> Enum.reverse()
+ |> Enum.join("\n")
+ end
+
+ defp scan([], _x, _pixel, pixels), do: pixels
+
+ defp scan(instrs, x, _pixel = 40, pixels) do
+ scan(instrs, x, _pixel = 0, [[] | pixels])
+ end
+
+ defp scan([%Instr{cmd: :noop} | rest], x, pixel, [row | pixels]) do
+ scan(rest, x, pixel + 1, [draw_pixel(pixel, x, row) | pixels])
+ end
+
+ defp scan([%Instr{cycles: 1, cmd: :addx, amt: amt} | rest], x, pixel, [row | pixels]) do
+ scan(rest, x + amt, pixel + 1, [draw_pixel(pixel, x, row) | pixels])
+ end
+
+ defp scan([instr = %Instr{cycles: cycles} | rest], x, pixel, [row | pixels]) do
+ scan([%Instr{instr | cycles: cycles - 1} | rest], x, pixel + 1, [
+ draw_pixel(pixel, x, row) | pixels
+ ])
+ end
+
+ defp draw_pixel(pixel, x, row) when pixel in (x - 1)..(x + 1), do: ["#" | row]
+ defp draw_pixel(_pixel, _x, row), do: [" " | row]
+
+ def input do
+ with [input_filename] <- System.argv(),
+ {:ok, input} <- File.read(input_filename) do
+ input
+ |> String.trim()
+ |> String.split("\n")
+ |> Enum.map(fn
+ "noop" -> %Instr{cmd: :noop, cycles: 1}
+ "addx " <> x -> %Instr{cmd: :addx, cycles: 2, amt: String.to_integer(x)}
+ end)
+ else
+ _ -> :error
+ end
+ end
+
+ #######################
+ # HERE BE BOILERPLATE #
+ #######################
+
+ def run do
+ case input() do
+ :error -> print_usage()
+ input -> run_parts_with_timer(input)
+ end
+ end
+
+ defp run_parts_with_timer(input) do
+ run_with_timer(1, fn -> part1(input) end)
+ run_with_timer(2, fn -> part2(input) end)
+ end
+
+ defp run_with_timer(part, fun) do
+ {time, result} = :timer.tc(fun)
+ IO.puts("Part #{part} (completed in #{format_time(time)}):\n")
+ IO.puts("#{result}\n")
+ end
+
+ defp format_time(μsec) when μsec < 1_000, do: "#{μsec}μs"
+ defp format_time(μsec) when μsec < 1_000_000, do: "#{μsec / 1000}ms"
+ defp format_time(μsec), do: "#{μsec / 1_000_000}s"
+
+ defp print_usage do
+ IO.puts("Usage: elixir day10.exs input_filename")
+ end
+end
+
+Day10.run()