-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(<>, 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(<>, 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([<> | Rows], Stack) -> build_stack(Rows, [Item | Stack]).