Skip to content

Instantly share code, notes, and snippets.

@ferd

ferd/day04.erl Secret

Last active December 4, 2019 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ferd/5d8c2997bb2b834af302e4856681d91f to your computer and use it in GitHub Desktop.
Save ferd/5d8c2997bb2b834af302e4856681d91f to your computer and use it in GitHub Desktop.
%%% @doc [17/950]
%%% fill this with the sorrows of the fourth challenge
%%% @end
-module(day04).
-export([p1/0, p2/0]).
-export([valid/1, valid2/1]).
p1() ->
count_passwords(206938,679128, fun valid/1).
p2() ->
count_passwords(206938,679128, fun valid2/1).
count_passwords(A, B, F) ->
count_passwords(A, B, F, 0).
count_passwords(A, B, _Pred, N) when A > B -> N;
count_passwords(A, B, Pred, N) ->
case Pred(A) of
true -> count_passwords(A+1, B, Pred, N+1);
false -> count_passwords(A+1, B, Pred, N)
end.
valid(N) ->
valid(N, 10, undefined, false, true).
valid(_, _, _, _, false) ->
%% This clause is an optimization I thought of after the video was done
%% and cuts down run-time in half by bailing out early.
false;
valid(N, Div, undefined, Doubles, Incr) ->
{ok, D, NextDiv} = next_digit(N, Div),
valid(N, NextDiv, D, Doubles, Incr);
valid(N, Div, Last, Doubles, Incr) ->
case next_digit(N, Div) of
undefined ->
Doubles andalso Incr;
{ok, D, NextDiv} ->
valid(N, NextDiv, D,
Doubles orelse D =:= Last,
Incr andalso D =< Last)
end.
valid2(N) ->
valid2(N, 10, undefined, 0, false, true).
valid2(_, _, _, _, _, false) ->
%% This clause is an optimization I thought of after the video was done
%% and cuts down run-time in half by bailing out early.
false;
valid2(N, Div, undefined, _, Double, Incr) ->
{ok, D, NextDiv} = next_digit(N, Div),
valid2(N, NextDiv, D, 1, Double, Incr);
valid2(N, Div, Last, Seq, Double, Incr) ->
case next_digit(N, Div) of
undefined ->
(Double orelse Seq == 2) andalso Incr;
{ok, D, NextDiv} ->
NewSeq = if D =:= Last -> Seq+1;
D =/= Last -> 1
end,
valid2(N, NextDiv, D, NewSeq,
Double orelse (Seq == 2 andalso NewSeq == 1),
Incr andalso D =< Last)
end.
%% @doc `Div' must start at 10.
next_digit(N, Div) when Div > N*10 -> undefined;
next_digit(N, Div) -> {ok, (N rem Div) div (Div div 10), Div*10}.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment