175 lines
6.2 KiB
Erlang
175 lines
6.2 KiB
Erlang
-module(day18).
|
|
-export([start/0]).
|
|
|
|
value_or_register(X, Registers)
|
|
when X >= <<"a">>, X =< <<"z">> -> maps:get(X, Registers, 0);
|
|
value_or_register(X, _Registers)
|
|
-> { NewValue, _ } = string:to_integer(X),
|
|
NewValue.
|
|
|
|
assemble(Input)
|
|
-> Instructions = lists:map(fun(X) -> [A|Args] = re:split(X, " "), { A, Args } end, re:split(Input, "\n")),
|
|
assemble(Instructions, length(Instructions), 1, 0, maps:new()).
|
|
|
|
assemble(_Instructions, MaxInstructions, Ip, LastFrequency, _Registers)
|
|
when Ip < 1; Ip > MaxInstructions -> LastFrequency;
|
|
assemble(Instructions, MaxInstructions, Ip, LastFrequency, Registers)
|
|
-> { Op, Args } = lists:nth(Ip, Instructions),
|
|
case Op of
|
|
<<"add">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue + NewValue, Registers));
|
|
<<"jgz">> ->
|
|
[Src,Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
RegisterValue = maps:get(Src, Registers, 0),
|
|
if RegisterValue > 0 -> assemble(Instructions, MaxInstructions, Ip + NewValue, LastFrequency, Registers);
|
|
true -> assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers)
|
|
end;
|
|
<<"mod">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue rem NewValue, Registers));
|
|
<<"mul">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue * NewValue, Registers));
|
|
<<"rcv">> ->
|
|
[Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
if NewValue /= 0 -> LastFrequency;
|
|
true -> assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers)
|
|
end;
|
|
<<"set">> ->
|
|
[Src,Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, NewValue, Registers));
|
|
<<"snd">> ->
|
|
[Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
assemble(Instructions, MaxInstructions, Ip + 1, NewValue, Registers)
|
|
end.
|
|
|
|
assemble2(Input)
|
|
-> Instructions = lists:map(fun(X) -> [A|Args] = re:split(X, " "), { A, Args } end, re:split(Input, "\n")),
|
|
assemble2(Instructions, length(Instructions), 1, maps:put(<<"p">>, 0, maps:new()), [], 0, 1, maps:put(<<"p">>, 1, maps:new()), []).
|
|
|
|
assemble2(Instructions, MaxInstructions, Ip0, Registers0, Queue0, SndCount, Ip1, Registers1, Queue1)
|
|
-> { NewIp0, NewRegisters0, NewQueue0, NewQueue1, _ } = assemble3(Instructions, MaxInstructions, Ip0, Registers0, Queue0, Queue1),
|
|
{ NewIp1, NewRegisters1, AnotherNewQueue1, AnotherNewQueue0, Count } = assemble3(Instructions, MaxInstructions, Ip1, Registers1, NewQueue1, NewQueue0),
|
|
NewSndCount = SndCount + Count,
|
|
%io:fwrite("newsndcount ~p~n", [NewSndCount]),
|
|
%io:fwrite("ip0 ~p ip1 ~p~nq0 ~p~nq1 ~p~n", [NewIp0, NewIp1, AnotherNewQueue0, AnotherNewQueue1]),
|
|
if Ip0 == NewIp0, Ip1 == NewIp1 -> NewSndCount;
|
|
true -> assemble2(Instructions, MaxInstructions, NewIp0, NewRegisters0, AnotherNewQueue0, NewSndCount, NewIp1, NewRegisters1, AnotherNewQueue1)
|
|
end.
|
|
|
|
assemble3(_Instructions, MaxInstructions, Ip, Registers, Queue, OtherQueue)
|
|
when Ip < 1; Ip > MaxInstructions -> { Ip, Registers, Queue, OtherQueue, 0 };
|
|
assemble3(Instructions, _MaxInstructions, Ip, Registers, Queue, OtherQueue)
|
|
-> { Op, Args } = lists:nth(Ip, Instructions),
|
|
case Op of
|
|
<<"add">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
{ Ip + 1, maps:put(Src, ExistingValue + NewValue, Registers), Queue, OtherQueue, 0 };
|
|
<<"jgz">> ->
|
|
[Src,Dest|_] = Args,
|
|
SrcValue = value_or_register(Src, Registers),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
if SrcValue > 0 -> { Ip + NewValue, Registers, Queue, OtherQueue, 0 };
|
|
true -> { Ip + 1, Registers, Queue, OtherQueue, 0 }
|
|
end;
|
|
<<"mod">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
{ Ip + 1, maps:put(Src, (ExistingValue rem NewValue), Registers), Queue, OtherQueue, 0 };
|
|
<<"mul">> ->
|
|
[Src,Dest|_] = Args,
|
|
ExistingValue = maps:get(Src, Registers, 0),
|
|
NewValue = value_or_register(Dest, Registers),
|
|
{ Ip + 1, maps:put(Src, (ExistingValue * NewValue), Registers), Queue, OtherQueue, 0 };
|
|
<<"rcv">> ->
|
|
[Dest|_] = Args,
|
|
QueueLen = length(Queue),
|
|
if QueueLen == 0 -> { Ip, Registers, Queue, OtherQueue, 0 };
|
|
true -> [Head|Tail] = Queue, { Ip + 1, maps:put(Dest, Head, Registers), Tail, OtherQueue, 0 }
|
|
end;
|
|
<<"set">> ->
|
|
[Src,Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
{ Ip + 1, maps:put(Src, NewValue, Registers), Queue, OtherQueue, 0 };
|
|
<<"snd">> ->
|
|
[Dest|_] = Args,
|
|
NewValue = value_or_register(Dest, Registers),
|
|
{ Ip + 1, Registers, Queue, lists:append(OtherQueue, [NewValue]), 1 }
|
|
end.
|
|
|
|
start()
|
|
-> io:fwrite("~p~n", [ assemble("set a 1
|
|
add a 2
|
|
mul a a
|
|
mod a 5
|
|
snd a
|
|
set a 0
|
|
rcv a
|
|
jgz a -1
|
|
set a 1
|
|
jgz a -2") ]),
|
|
Instructions = "set i 31
|
|
set a 1
|
|
mul p 17
|
|
jgz p p
|
|
mul a 2
|
|
add i -1
|
|
jgz i -2
|
|
add a -1
|
|
set i 127
|
|
set p 952
|
|
mul p 8505
|
|
mod p a
|
|
mul p 129749
|
|
add p 12345
|
|
mod p a
|
|
set b p
|
|
mod b 10000
|
|
snd b
|
|
add i -1
|
|
jgz i -9
|
|
jgz a 3
|
|
rcv b
|
|
jgz b -1
|
|
set f 0
|
|
set i 126
|
|
rcv a
|
|
rcv b
|
|
set p a
|
|
mul p -1
|
|
add p b
|
|
jgz p 4
|
|
snd a
|
|
set a b
|
|
jgz 1 3
|
|
snd b
|
|
set f 1
|
|
add i -1
|
|
jgz i -11
|
|
snd a
|
|
jgz f -16
|
|
jgz a -19",
|
|
io:fwrite("~p~n", [ assemble(Instructions) ]),
|
|
io:fwrite("~p~n", [ assemble2("snd 1
|
|
snd 2
|
|
snd p
|
|
rcv a
|
|
rcv b
|
|
rcv c
|
|
rcv d") ]),
|
|
io:fwrite("~p~n", [ assemble2(Instructions) ]).
|