-module(bitmask2). -export([challenge/1, test_challenge/0]). challenge(Max) -> statistics(wall_clock), {_,BiggestJump,CountOfNumbers} = find_loop(1, 10, Max, {0,0,0}), {_, Elapsed} = statistics(wall_clock), io:format("~p ms elapsed to complete count to ~p~n", [Elapsed, Max]), {BiggestJump, CountOfNumbers}. test_challenge() -> {1,10} = challenge(10), {2,90} = challenge(100), {11,738} = challenge(1000), {105,5274} = challenge(10000), {1047,32490} = challenge(100000). find_loop(N, NMax, _Max, State) when N > NMax -> State; find_loop(N, NMax, Max, State) -> case find(1, N, 1, 0, Max, State) of {done, NewState} -> NewState; NewState -> find_loop(N+1, NMax, Max, NewState) end. find(Digit, _, _, _, _, State) when Digit >= 10 -> State; find(Digit, Remaining, Value, Used, Max, State) -> Mask = 1 bsl Digit, case Used band Mask of 0 -> case Remaining of 1 -> if Value > Max -> {done, State}; true -> NewState= update(State, Value), find(Digit+1, Remaining, Value+1, Used, Max, NewState) end; _ -> case find(0, Remaining - 1, Value * 10, Used bor Mask, Max, State) of {done, NewState} -> {done, NewState}; NewState -> find(Digit+1, Remaining, Value+1, Used, Max, NewState) end end; _ -> find(Digit+1, Remaining, Value+1, Used, Max, State) end. update({RunStart,MaxGap,Counter},Element) when Element - RunStart >= MaxGap -> {Element,Element - RunStart,Counter + 1}; update({_RunStart,MaxGap,Counter},Element) -> {Element,MaxGap,Counter + 1}.