69 lines
3.1 KiB
Erlang
69 lines
3.1 KiB
Erlang
|
-module(day16).
|
||
|
-export([start/0]).
|
||
|
|
||
|
dance([], Registers)
|
||
|
-> Registers;
|
||
|
dance([Head|Tail], Registers)
|
||
|
-> Instr = string:slice(Head, 0, 1),
|
||
|
Args = string:slice(Head, 1),
|
||
|
NewRegisters = process_instruction(Instr, Args, Registers),
|
||
|
dance(Tail, NewRegisters).
|
||
|
|
||
|
process_instruction(Instr, Args, Registers)
|
||
|
when Instr == <<"s">> -> Len = string:length(Registers),
|
||
|
{ Count, _ } = string:to_integer(Args),
|
||
|
Index = Len - Count,
|
||
|
First = string:slice(Registers, Index),
|
||
|
Second = string:slice(Registers, 0, Index),
|
||
|
string:concat(First, Second);
|
||
|
process_instruction(Instr, Args, Registers)
|
||
|
when Instr == <<"x">> -> [FirstRegister|Rest] = re:split(Args, "/"),
|
||
|
[SecondRegister|_] = Rest,
|
||
|
{ FirstIndex, _ } = string:to_integer(FirstRegister),
|
||
|
{ SecondIndex, _ } = string:to_integer(SecondRegister),
|
||
|
swap_registers(FirstIndex, SecondIndex, Registers);
|
||
|
process_instruction(Instr, Args, Registers)
|
||
|
when Instr == <<"p">> -> [FirstRegister|Rest] = re:split(Args, "/"),
|
||
|
[SecondRegister|_] = Rest,
|
||
|
IndexA = char_index(FirstRegister, Registers),
|
||
|
IndexB = char_index(SecondRegister, Registers),
|
||
|
swap_registers(IndexA, IndexB, Registers).
|
||
|
|
||
|
char_index(Char, String)
|
||
|
-> StrLen = string:length(String),
|
||
|
StrLen - string:length(string:find(String, Char)).
|
||
|
|
||
|
find_char_index(Index)
|
||
|
when Index == nomatch -> 0;
|
||
|
find_char_index(Index)
|
||
|
-> Index.
|
||
|
|
||
|
swap_registers(A, B, Registers)
|
||
|
when B < A -> swap_registers(B, A, Registers);
|
||
|
swap_registers(A, B, Registers)
|
||
|
-> RegisterList = list_to_tuple(Registers),
|
||
|
ValueA = element(A + 1, RegisterList),
|
||
|
ValueB = element(B + 1, RegisterList),
|
||
|
tuple_to_list(setelement(B + 1, setelement(A + 1, RegisterList, ValueB), ValueA)).
|
||
|
|
||
|
dance_countdown(Steps, Instructions, Registers)
|
||
|
-> dance_countdown(Steps, Instructions, Registers, Steps, []).
|
||
|
|
||
|
dance_countdown(Steps, _Instructions, Registers, _OriginalSteps, _PreviousSteps)
|
||
|
when Steps == 0 -> Registers;
|
||
|
dance_countdown(Steps, Instructions, Registers, OriginalSteps, PreviousSteps)
|
||
|
-> CurrentRegisters = dance(Instructions, Registers),
|
||
|
Found = lists:any(fun(X) -> string:equal(X, CurrentRegisters) end, PreviousSteps),
|
||
|
if Found -> Index = OriginalSteps rem length(PreviousSteps),
|
||
|
lists:nth(Index, PreviousSteps);
|
||
|
true -> dance_countdown(Steps - 1, Instructions, CurrentRegisters, OriginalSteps, lists:append(PreviousSteps, [CurrentRegisters]))
|
||
|
end.
|
||
|
|
||
|
start()
|
||
|
-> SampleInstructions = re:split("s1,x3/4,pe/b", ","),
|
||
|
io:fwrite("~p~n", [dance(SampleInstructions, "abcde")]),
|
||
|
{ ok, File } = file:read_file("input"),
|
||
|
InputInstructions = re:split(unicode:characters_to_list(string:chomp(File)), ","),
|
||
|
io:fwrite("~p~n", [dance(InputInstructions, "abcdefghijklmnop")]),
|
||
|
io:fwrite("~p~n", [dance_countdown(1000000000, InputInstructions, "abcdefghijklmnop")]).
|