-module(fastbeust2). -export([challenge/1, test_challenge/0]). challenge(Max) -> statistics(wall_clock), Digits = new_digits(), {_,BiggestJump,CountOfNumbers} = find_loop(1, 10, Digits, 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, _Digits, _Max, State) when N > NMax -> State; find_loop(N, NMax, Digits, Max, State) -> {_Zero, One} = gb_sets:next(gb_sets:iterator(Digits)), case find(One, Digits, N, 0, Max, State) of {done, NewState} -> NewState; NewState -> find_loop(N+1, NMax, Digits, Max, NewState) end. find(Current, Digits, Remaining, Value, Max, State) -> case gb_sets:next(Current) of none -> State; {CurrentValue, Next} -> NewValue = Value + CurrentValue, case Remaining of 1 -> if NewValue > Max -> {done, State}; true -> NewState = update(State, NewValue), find(Next, Digits, Remaining, Value, Max, NewState) end; _ -> NewDigits = gb_sets:delete(CurrentValue, Digits), case find(gb_sets:iterator(NewDigits), NewDigits, Remaining - 1, NewValue * 10, Max, State) of {done, NewState} -> {done, NewState}; NewState -> find(Next, Digits, Remaining, Value, Max, NewState) end end end. update({RunStart,MaxGap,Counter},Element) when Element - RunStart >= MaxGap -> {Element,Element - RunStart,Counter + 1}; update({_RunStart,MaxGap,Counter},Element) -> {Element,MaxGap,Counter + 1}. new_digits() -> gb_sets:from_list(lists:seq(0,9)).