LostKobrakai
Advent of Code 2022 - Day 10
This one was really fun contrary to other “implement something CPU like” puzzles in the past. I used a bunch of Stream API and a module for scoping the CRT logic. I really liked the visual component of part 2.
Solution
defmodule Day10 do
defmodule CRT do
defstruct pixels: [], index: 0
def render_pixel(state, x) do
pixel = if state.index in (x - 1)..(x + 1), do: "#", else: "."
%__MODULE__{
pixels: [pixel | state.pixels],
index: rem(state.index + 1, 40)
}
end
def render(state) do
state.pixels
|> Enum.reverse()
|> Enum.chunk_every(40)
|> Enum.join("\n")
end
end
def run(text) do
text
|> program()
|> Stream.filter(fn {_, cycle} -> cycle in [20, 60, 100, 140, 180, 220] end)
|> Stream.map(fn {x, cycle} -> x * cycle end)
|> Enum.take(6)
|> Enum.sum()
end
def render_to_crt(text) do
text
|> program()
|> Stream.take_while(fn {_, cycle} -> cycle <= 240 end)
|> Enum.reduce(%CRT{}, fn {x, _}, crt ->
CRT.render_pixel(crt, x)
end)
|> CRT.render()
end
defp program(text) do
text
|> String.split("\n", trim: true)
|> Stream.transform(1, fn
"noop", x -> {[x], x}
"addx " <> num, x -> {[x, x], x + String.to_integer(num)}
end)
|> Stream.with_index(1)
end
end
Most Liked
deadbeef
kwando
I had a very clunky version that got me the gold stars, but after some coffee I ended up with a super neat version using Stream.transform.
input
|> Stream.transform({1, 1}, fn
:noop, {cycle, x} ->
{[{cycle, x}], {cycle + 1, x}}
{:addx, value}, {cycle, x} ->
{[{cycle, x}, {cycle + 1, x}], {cycle + 2, x + value}}
end)
That will give you a stream of {cycle_no, x} tuples that you could use to find the solution to the other parts. input is parsed in to a list of tuples, the small example would look like the [:noop, {:addx, 3}, {:addx, -5}].
Just pipe that stream into this for the second part ![]()
cycle_stream # from above
|> Stream.map(fn
{pc, x} when rem(pc-1, 40) in (x-1)..(x+1) -> ?#
_ -> ?\s
end)
|> Stream.chunk_every(40)
|> Enum.intersperse(?\n)
|> IO.puts
Elixir standard library is so awesomely good.
kwando
It is probably faster with handrolled recursive functions, but it can be quite dense to read ![]()
There are a lot of gems hidden in the standard library:)
pistelak
You are right, there is something wrong.
I tried to someone’s else solution and the result is slightly different: Screenshot 2022-12-10 at 18.56.23 2022-12-10 at 7.00.50 PM … Will take a look.
pistelak
Error by one
- cycles are indexed from 1 but CRT starts drawing at 0. So
Enum.member?(i.x-1..i.x+1, rem(i.cycle - 1, 40)) is correct.








