Skip to content

Instantly share code, notes, and snippets.

@tank-bohr
Last active January 4, 2016 05:58
Show Gist options
  • Save tank-bohr/9755ff4aadb2aa27117f to your computer and use it in GitHub Desktop.
Save tank-bohr/9755ff4aadb2aa27117f to your computer and use it in GitHub Desktop.
-module(cozy_lists).
-include_lib("eunit/include/eunit.hrl").
-export ([
even/1,
odd/1,
uniq/1,
find_index/2,
count/2,
all_sublists/1,
permutaions/1,
take/2,
detect/2,
prime_division/1
]).
even(N) ->
(N band 1) =:= 0.
odd(N) ->
not even(N).
uniq(List) ->
uniq(List, []).
uniq([], Acc) ->
lists:reverse(Acc);
uniq([X|Rest], Acc) ->
case lists:member(X, Acc) of
true ->
uniq(Rest, Acc);
false ->
uniq(Rest, [X|Acc])
end.
find_index(Elem, List) ->
find_index(Elem, List, 0).
find_index(_Elem, [], _Idx) ->
-1;
find_index(Elem, [Elem|_], Idx) ->
Idx + 1;
find_index(Elem, [_|Rest], Idx) ->
find_index(Elem, Rest, Idx + 1).
count(Pred, List) when is_function(Pred) ->
count(Pred, List, 0);
count(Elem, List) ->
count(fun(X) -> X =:= Elem end, List).
count(_Pred, [], Cnt) ->
Cnt;
count(Pred, [X|Rest], Cnt) ->
case Pred(X) of
true ->
count(Pred, Rest, Cnt + 1);
false ->
count(Pred, Rest, Cnt)
end.
all_sublists(List) ->
Len = length(List),
uniq(lists:foldl(fun(I, Acc) ->
lists:foldl(fun(J, Acc0) ->
Sublist = lists:sublist(List, I + 1, J + 1),
[Sublist | Acc0]
end, Acc, lists:seq(0, Len - I))
end, [], lists:seq(0, Len))).
permutaions([]) ->
[[]];
permutaions(L) ->
[[H|T] || H <- L, T <- permutaions(L -- [H])].
take(N, List) ->
take(N, List, []).
take(_N, [], Acc) ->
lists:reverse(Acc);
take(N, _List, Acc) when length(Acc) =:= N ->
lists:reverse(Acc);
take(N, [X|Rest], Acc) ->
take(N, Rest, [X|Acc]).
detect(_Pred, []) ->
null;
detect(Pred, [X|Rest]) ->
case Pred(X) of
true ->
X;
false ->
detect(Pred, Rest)
end.
prime_division(N) ->
prime_division(N, []).
prime_division(N, Acc) when N < 0 ->
prime_division(-N, [{-1, 1}|Acc]);
prime_division(N, Acc) ->
prime_division(N, N, {2, 1}, Acc).
prime_division(N, Rem, {Prime, _}, Acc) when Rem =< Prime ->
case N > 1 of
true ->
[{N, 1} | Acc];
false ->
[Acc]
end;
prime_division(N, _, {Prime, Step}, Acc) ->
Next = generate_next_pseudo_prime(Prime, Step),
case prime_division_count_divisors(N, Prime) of
{_, 0} ->
prime_division(N, N div Prime, Next, Acc);
{Rem, Cnt} ->
prime_division(Rem, Rem, Next, [{Prime, Cnt} | Acc])
end.
prime_division_count_divisors(N, Prime) ->
prime_division_count_divisors(N, Prime, 0).
prime_division_count_divisors(N, Prime, Cnt) ->
case {N div Prime, N rem Prime} of
{N1, 0} ->
prime_division_count_divisors(N1, Prime, Cnt + 1);
{_, _} ->
{N, Cnt}
end.
generate_next_pseudo_prime(2, _) ->
{3, 2};
generate_next_pseudo_prime(3, _) ->
{5, 2};
generate_next_pseudo_prime(Prime, Step) ->
{Prime + Step, 6 - Step}.
%% Tests
even_test() ->
?assert(even(2)),
?assert(even(14)),
?assertNot(even(3)),
?assertNot(even(15)).
odd_test() ->
?assert(odd(5)),
?assert(odd(15)),
?assertNot(odd(4)),
?assertNot(odd(16)).
uniq_test() ->
?assertEqual([1, 2, 3], uniq([1, 1, 2, 3, 1, 2, 3])).
find_index_test() ->
?assertEqual(1, find_index(15, [15, 17, 11])),
?assertEqual(2, find_index(17, [15, 17, 11])),
?assertEqual(3, find_index(11, [15, 17, 11])),
?assertEqual(-1, find_index(12, [15, 17, 11])).
count_test() ->
?assertEqual(2, count(fun even/1, [11, 22, 33, 44])),
?assertEqual(2, count(11, [11, 22, 33, 44, 11])),
?assertEqual(0, count(12, [11, 22, 33, 44, 11])).
all_sublists_test() ->
?assertEqual([
[],
[3],
[2,3],
[2],
[1,2,3],
[1,2],
[1]
], all_sublists(lists:seq(1, 3))).
permutaions_test() ->
?assertEqual([
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
], permutaions(lists:seq(1, 3))).
take_test() ->
?assertEqual([1, 2, 3], take(3, lists:seq(1, 5))).
detect_test() ->
?assertEqual(2, detect(fun even/1, lists:seq(1, 5))).
prime_division_test() ->
?assertEqual([{521,1},{7,1},{2,2}], prime_division(14588)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment