You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
54 lines
2.3 KiB
54 lines
2.3 KiB
-module(day5).
|
|
|
|
-export([solve/1]).
|
|
|
|
solve(InputData) ->
|
|
[DiagramData, Instructions] = binary:split(InputData, <<"\n\n">>, [trim_all]),
|
|
Diagram = lists:reverse(binary:split(DiagramData, <<"\n">>, [trim_all, global])),
|
|
Stacks = parse_diagram(Diagram),
|
|
EndStacks = eval_instructions(Instructions, Stacks, fun eval_move/4),
|
|
EndStacks2 = eval_instructions(Instructions, Stacks, fun eval_move2/4),
|
|
{print_stacks(EndStacks), print_stacks(EndStacks2)}.
|
|
|
|
print_stacks(Stacks) ->
|
|
lists:reverse(
|
|
maps:fold(fun (_Key, [Top|_Rest], Acc) -> [Top|Acc] end, [], Stacks)
|
|
).
|
|
|
|
eval_instructions(<<>>, Stacks, _MoveFun) -> Stacks;
|
|
eval_instructions(Instructions, Stacks, MoveFun) ->
|
|
<<"move ", Instruction1/binary>> = Instructions,
|
|
{Moves, Instruction2} = parse_int(Instruction1),
|
|
<<" from ", DigitFrom, " to ", DigitTo, $\n, Rest/binary>> = Instruction2,
|
|
eval_instructions(Rest, MoveFun(DigitFrom, DigitTo, Moves, Stacks), MoveFun).
|
|
|
|
parse_int(String) -> parse_int(String, 0).
|
|
parse_int(<<Char, Rest/binary>>, Acc) when Char >= $0 andalso Char =< $9 -> parse_int(Rest, Acc*10+(Char - $0));
|
|
parse_int(String, Acc) -> {Acc, String}.
|
|
|
|
eval_move(_DigitFrom, _DigitTo, 0, Stacks) -> Stacks;
|
|
eval_move(DigitFrom, DigitTo, N, Stacks) when is_integer(N) and (N > 0) ->
|
|
#{DigitFrom := [Item | StackFrom], DigitTo := StackTo} = Stacks,
|
|
eval_move(DigitFrom, DigitTo, N-1, Stacks#{DigitFrom := StackFrom, DigitTo := [Item | StackTo]}).
|
|
|
|
eval_move2(DigitFrom, DigitTo, N, Stacks) when is_integer(N) and (N > 0) ->
|
|
#{DigitFrom := StackFrom, DigitTo := StackTo} = Stacks,
|
|
{Items, NewFrom} = lists:split(N, StackFrom),
|
|
NewTo = Items ++ StackTo,
|
|
Stacks#{DigitFrom := NewFrom, DigitTo := NewTo}.
|
|
|
|
parse_diagram([Program | Boxes]) -> parse_diagram(Program, Boxes, #{}).
|
|
|
|
parse_diagram(<<>>, _Boxes, Stacks) -> Stacks;
|
|
parse_diagram(<<Digit, ProgramRest/binary>>, Boxes, Stacks) when Digit >= $0 andalso Digit =< $9 ->
|
|
parse_diagram(
|
|
ProgramRest,
|
|
lists:map(fun(<<_, Tail/binary>>) -> Tail end, Boxes),
|
|
Stacks#{Digit => build_stack(Boxes, [])}
|
|
);
|
|
parse_diagram(<<_Char, ProgramRest/binary>>, Boxes, Stacks) ->
|
|
parse_diagram(ProgramRest, lists:map(fun(<<_, Tail/binary>>) -> Tail end, Boxes), Stacks).
|
|
|
|
build_stack([], Stack) -> Stack;
|
|
build_stack([<<$\s, _Rest/binary>> | _Rows], Stack) -> Stack;
|
|
build_stack([<<Item, _Rest/binary>> | Rows], Stack) -> build_stack(Rows, [Item | Stack]).
|