diff --git a/day23.erl b/day23.erl index dd16794..d465955 100644 --- a/day23.erl +++ b/day23.erl @@ -2,63 +2,49 @@ -export([solve/1]). --compile(export_all). - solve(InputData) -> - {part1(InputData), none}. + {part1(InputData), part2(InputData)}. part1(Input) -> State = parse_input(Input), EndState = step(10, State), - {XMin, XMax, YMin, YMax} = Bounds = get_bounds(EndState), - %io:format("~p~n", [Bounds]), + {XMin, XMax, YMin, YMax} = get_bounds(EndState), (XMax - XMin + 1) * (YMax - YMin + 1) - num_elves(State). +part2(InputData) -> + State = parse_input(InputData), + step_until(0, State). + parse_input(Input) -> parse_input(Input, 0, 0, 1, {#{}, #{}}). parse_input(<<>>, _X, _Y, _NumElves, State) -> State; parse_input(<<$., Rest/binary>>, X, Y, ElfId, State) -> parse_input(Rest, X+1, Y, ElfId, State); -parse_input(<<$\n, Rest/binary>>, X, Y, ElfId, State) -> +parse_input(<<$\n, Rest/binary>>, _X, Y, ElfId, State) -> parse_input(Rest, 0, Y+1, ElfId, State); parse_input(<<$#, Rest/binary>>, X, Y, ElfId, {ActiveElves, Positions}) -> parse_input(Rest, X+1, Y, ElfId+1, {ActiveElves#{ElfId => {X, Y}}, Positions#{{X, Y} => ElfId}}). num_elves({_ActiveElves, Positions}) -> map_size(Positions). - -board_put(X, Y, Char, {W, Data}) -> - Index = Y * (W+1) + X, - Before = binary_part(Data, {0, Index}), - After = binary_part(Data, {Index + 1, byte_size(Data) - Index - 1}), - {W, <>}. - -mkboard(W, H) -> - mkboard(W, H, <<>>). - -mkboard(W, 0, Acc) -> {W, Acc}; -mkboard(W, H, Acc) -> - MkRow = fun MkRow(0, R) -> R; - MkRow(N, R) -> MkRow(N-1, <>) end, - WithRow = MkRow(W, Acc), - mkboard(W, H-1, <>). - -render({_Active, Positions} = State) -> - {MinX, MaxX, MinY, MaxY} = get_bounds(State), - {_, Data} = maps:fold(fun ({X, Y}, Id, Board) -> board_put(X - MinX, Y - MinY, (Id rem 10) + $0, Board) end, - mkboard(MaxX - MinX + 1, MaxY - MinY + 1), - Positions), - Data. - step(N, State) -> step(0, N, State). +step_until(I, State) -> + NewState = do_step(State, I), + if + State == NewState -> I+1; + true -> step_until(I+1, NewState) + end. + step(N, N, State) -> State; step(I, N, State) when N - I > 0 -> step(I+1, N, do_step(State, I)). do_step({ActiveElves, PositionsIn}, Round) -> - %io:format(" Stepping ~n", []), + %io:format(" Stepping ~p ~n", [Round]), %io:format("~s~n", [render({ActiveElves, PositionsIn})]), {PlannedMoves, _Inactive} = plan_moves(ActiveElves, PositionsIn, Round), + %io:format(" moves ~p ~n", [map_size(PlannedMoves)]), + maps:fold(fun (NewPos, ElfId, {Active, Positions}) -> #{ElfId := OldPos} = Active, Updooted = maps:remove(OldPos, Positions), @@ -140,8 +126,8 @@ get_move({ElfX, ElfY}, Positions, Round) -> end end. -mark_inactive(ElfId, {ActiveElves, Positions}) -> maps:remove(ElfId, ActiveElves). -mark_active(ElfId, ElfPosition, {ActiveElves, Positions}) -> ActiveElves#{ElfId => ElfPosition}. +mark_inactive(ElfId, {ActiveElves, _Positions}) -> maps:remove(ElfId, ActiveElves). +mark_active(ElfId, ElfPosition, {ActiveElves, _Positions}) -> ActiveElves#{ElfId => ElfPosition}. get_bounds({_ActiveElves, Positions}) -> maps:fold(fun ({X, Y}, _Value, {MinX, MaxX, MinY, MaxY}) -> @@ -149,3 +135,27 @@ get_bounds({_ActiveElves, Positions}) -> end, {50000000, 0, 50000000, 0}, Positions). + +mkboard(W, H) -> + mkboard(W, H, <<>>). + +mkboard(W, 0, Acc) -> {W, Acc}; +mkboard(W, H, Acc) -> + MkRow = fun MkRow(0, R) -> R; + MkRow(N, R) -> MkRow(N-1, <>) end, + WithRow = MkRow(W, Acc), + mkboard(W, H-1, <>). + +render({_Active, Positions} = State) -> + {MinX, MaxX, MinY, MaxY} = get_bounds(State), + {_, Data} = maps:fold(fun ({X, Y}, Id, Board) -> board_put(X - MinX, Y - MinY, (Id rem 10) + $0, Board) end, + mkboard(MaxX - MinX + 1, MaxY - MinY + 1), + Positions), + Data. + +board_put(X, Y, Char, {W, Data}) -> + Index = Y * (W+1) + X, + Before = binary_part(Data, {0, Index}), + After = binary_part(Data, {Index + 1, byte_size(Data) - Index - 1}), + {W, <>}. +