This topic is about Day 10 of the Advent of Code 2022 .
Link to our leaderboard:
https://adventofcode.com/2022/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
Good luck!
This topic is about Day 10 of the Advent of Code 2022 .
Link to our leaderboard:
https://adventofcode.com/2022/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
Good luck!
Today was fun, but I had to re-read Part 2 five times to understand what was happening (maybe because it’s 5AM here, idk):
main(File) ->
{ok, RawData} = file:read_file(File),
Data = [ case Line of
<<"noop">> -> noop;
<<"addx ", V/binary>> -> {addx, binary_to_integer(V)}
end || Line <- binary:split(RawData, <<"\n">>, [global, trim]) ],
io:format("part 1: ~p~n", [solve1(Data)]),
io:format("part 2: ~p~n", [solve2(Data)]).
solve1(Data) ->
Values = simulate(Data, 1, 1),
lists:sum([ K * element(2, lists:keyfind(K, 1, Values)) || K <- lists:seq(20, 220, 40) ]).
solve2(Data) ->
lists:foreach(fun draw/1, simulate(Data, 1, 1)).
simulate([], _, _) -> [];
simulate([Op|Rest], C, Value) ->
case Op of
noop -> [{C, Value} |simulate(Rest, C + 1, Value)];
{addx, ToAdd} -> [{C, Value}, {C + 1, Value}|simulate(Rest, C + 2, Value + ToAdd)]
end.
draw({Cycle, X}) ->
Shifted = Cycle - 40 * (Cycle div 40) - 1,
case Shifted >= (X - 1) andalso Shifted =< (X + 1) of
true -> io:format("#");
false -> io:format(".")
end,
case Cycle rem 40 of
0 -> io:format("\n");
_ -> ok
end.
-module(day_10).
-export([solve/0]).
-define(print, "█").
-define(blank, "▒").
input() ->
element(2, file:read_file("data/10.txt")).
solve() ->
{Cycles, _, _} = run(parse(input())),
Nths = [20, 60, 100, 140, 180, 220],
Solve1 = lists:sum([X * element(2, lists:keyfind(X, 1, Cycles)) || X <- Nths]),
Solve2 =
lists:foreach(fun render/1, lists:sort(fun({X, _}, {Y, _}) -> X < Y end, Cycles)),
{Solve1, Solve2}.
parse(RawInstructions) ->
[parse_instruction(RawInstruction)
|| RawInstruction <- binary:split(RawInstructions, <<"\n">>, [global, trim])].
parse_instruction(<<"noop">>) ->
noop;
parse_instruction(<<"addx ", Val/binary>>) ->
binary_to_integer(Val).
run(Instructions) ->
lists:foldl(fun (noop, {Xs, Cycle, Value}) ->
{[{Cycle, Value} | Xs], Cycle + 1, Value};
(AddValue, {Xs, Cycle, Value}) when is_integer(AddValue) ->
{[{Cycle, Value}, {Cycle + 1, Value} | Xs], Cycle + 2, Value + AddValue}
end,
{[], 1, 1},
Instructions).
render({Cycle, X}) ->
Shift = Cycle - 40 * (Cycle div 40) - 1,
if Shift >= X - 1 andalso Shift =< X + 1 ->
io:format(?print);
true ->
io:format(?blank)
end,
if Cycle rem 40 == 0 ->
io:format("\n");
true ->
ok
end.
Messy solution but works; and borrowed the render from @mafinar as I didn’t understand the how they wanted it rendered.
-module(day10).
-compile([export_all]).
%% ====================================================================
%% API functions
%% ====================================================================
-export([p1/0,
p2/0]).
-define(print, "█").
-define(blank, "▒").
s() ->
?MODULE ! stop.
p1() ->
proc_lib:spawn_link(?MODULE, init, [self(), #{}]),
receive after 500 -> void end,
loop_r(0).
p2() ->
proc_lib:spawn_link(?MODULE, init2, [self(), #{}]),
receive after 500 -> void end,
[catch render(I) || I <- lists:keysort(1, loop_2([]))].
loop_2(Mem) ->
receive
{ack,_,_} ->
loop_2(Mem);
I ->
loop_2([I|Mem])
after 0 ->
Mem
end.
loop_r(Cnt) ->
receive
Int when is_integer(Int) ->
loop_r(Cnt+Int);
_ ->
%% ignore
loop_r(Cnt)
after 0 ->
Cnt
end.
init2(PPid, Map) ->
proc_lib:init_ack(PPid, {ok, self()}),
register(?MODULE,self()),
Input = input(),
loop2(Map#{ppid => PPid,
inst => Input,
cur_inst => noop,
x => 1,
cycle => 1
}).
loop2({stop, State}) ->
exit(normal);
loop2(State) ->
NS = case maps:get(cycle, State) of
240 ->
{stop, State};
_ ->
step2(State)
end,
loop2(NS).
init(PPid, Map) ->
proc_lib:init_ack(PPid, {ok, self()}),
register(?MODULE,self()),
Input = input(),
loop(Map#{ppid => PPid,
inst => Input,
cur_inst => noop,
x => 1,
cycle => 1
}).
loop({stop, State}) ->
exit(normal);
loop(State) ->
NS = receive
stop -> {stop, State}
after 0->
step(State)
end,
loop(NS).
step(Map) ->
Cycle = maps:get(cycle, Map),
LastInst = maps:get(cur_inst, Map),
Instructions = maps:get(inst, Map),
RunInst = hd(Instructions),
RestInst = tl(Instructions),
NM = run( RunInst,Cycle, Map#{inst => RestInst}),
notifiable(Cycle+1, NM).
step2(Map) ->
Cycle = maps:get(cycle, Map),
LastInst = maps:get(cur_inst, Map),
Instructions = maps:get(inst, Map),
RunInst = hd(Instructions),
PPid = maps:get(ppid, Map),
RestInst = tl(Instructions),
X = maps:get(x, Map),
PPid ! {Cycle, X},
run( RunInst,Cycle, Map#{inst => RestInst}).
run(noop,Cycle,Map) ->
Map#{cycle => Cycle+1, cur_inst => noop};
run(addx, Cycle, Map) ->
Map#{cycle => Cycle+1, cur_inst => addx};
run(Num, Cycle, Map) ->
X = maps:get(x, Map),
Map#{cycle => Cycle+1, x => X+Num}.
notifiable(NM, Map) when NM == 20;
NM == 60;
NM == 100;
NM == 140;
NM == 180;
NM == 220->
Val = maps:get(x, Map),
PPid = maps:get(ppid, Map),
catch PPid ! NM * Val,
if (NM == 220 ) ->{stop, Map};
true -> Map
end;
notifiable(NM, Map) ->
Map.
render({Cycle, X}) ->
Shift = Cycle - 40 * (Cycle div 40) - 1,
if Shift >= X - 1 andalso Shift =< X + 1 ->
io:format(?print);
true ->
io:format(?blank)
end,
if Cycle rem 40 == 0 ->
io:format("\n");
true ->
ok
end.
%% ====================================================================
%% Internal functions
%% ====================================================================
input() ->
{ok, B} = file:read_file("priv/input.txt"),
parse_to_wanted(binary:split(B, [<<10>>, <<" ">>], [global, trim])).
parse_to_wanted([]) ->
[];
parse_to_wanted([<<"addx">>|Rest]) ->
[addx|parse_to_wanted(Rest)];
parse_to_wanted([<<"noop">>|Rest]) ->
[noop|parse_to_wanted(Rest)];
parse_to_wanted([E|Rest]) ->
[binary_to_integer(E)|parse_to_wanted(Rest)].