Christmas Erlang Exercises delivered today

Okay, this is something I was going to blog about a month ago, but then the January storm hit and derailed that.

So, these are the first 22 exercises of the 99 Prolog Problems. I am doing them in Erlang. I know, I know, this is super cryptic by naming the functions after its problem number rather than by nice descriptive problems, but I was taking the easy way out; I just wanted to do them pretty quickly rather than show them off as an exercise on proper programming technique.

For what it is worth, here they are:

-module(p99a).
-export([a1/1, a2/1, a3/2, a4/1, a4b/1, a5/1,
a6/1, a7/1, a7b/1, a8/1, a8b/1, a9/1, a10/1,
a11/1, a12/1, a13/1, a14/1, a15/2,
a16/2, a17/2, a18/3, a19/2, a20/2,
a21/3, a22/2]).

%Find the last element of a list.
a1([], Result) -> Result;
a1([H|T], _) -> a1(T,H).

a1(List) -> a1(List, "Not a list").

%Find the last but one element of a list.
a2([_|[]], Result) -> Result;
a2([H|T], _) -> a2(T,H).

a2(List) -> a2(List, "not a list").

%Find the K'th element
a3([], _, _) -> {error, "out of range"};
a3([H|T], Nth, Index) ->
if Index == Nth -> H;
true -> a3(T, Nth, Index + 1)
end.

a3(List, Nth) -> a3(List, Nth, 1).

%Find the number of elements of a list.
a4([], Result) -> Result;
a4([_|T], Result) -> a4(T, Result + 1).

a4(L) -> a4(L, 0).

a4b([]) -> 0;
a4b([_|T]) -> a4b(T) + 1.

%Reverse a list.
a5([], R) -> R;
a5([H|T], R) -> a5(T, [H|R]).

a5(L) -> a5(L, []).

%Find out whether a list is a palindrome.
equal([], []) -> true;
equal([H|T], [H1|T1]) ->
if H == H1 -> equal(T, T1);
true -> false
end.

a6(L) -> equal(L, a5(L)).

%Flatten a nested list structure.
% a7 is concat in the O'Reilly Erlang book
% a7b is flatten per se
strip([], R) -> a5(R);
strip([H|T], R) -> strip(T, [H|R]).

a7([], R) -> R;
a7([H|T], R) -> a7(T, strip(H, R)).

a7(L) -> a7(L, []).

a7b([],R) -> R;
a7b([H|T], R) when is_list(H) -> a7b(T, a7b(H, R));
a7b([H|T], R) -> a7b(T, [H|R]).

a7b(L) -> a5(a7b(L, [])).

% Eliminate consecutive duplicates of list elements.
a8([], _, R) -> R;
a8([H|T], P, R) when P == H -> a8(T, P, R);
a8([H|T], P, R) when P /= H -> a8(T, H, [H | R]).

a8([H|T]) -> a5(a8(T, H, [H|[]])).

a8b([], _) -> [];
a8b([H|T], P) when P == H -> a8b(T, P);
a8b([H|T], P) when P /= H -> [H|a8b(T, H)].

a8b([H|T]) -> [H|a8b(T,H)].

% Pack consecutive duplicates of list elements into sublists.

pack([], _, R) -> [R];
pack([H|T], P, R) when H == P -> pack(T, P, [H|R]);
pack([H|T], _, R) -> [R| a9([H|T], H)].

a9([], _) -> [];
a9([H|T], P) when H == P -> pack([H|T], P, []);
a9([H|T], _) -> a9(T, H).

a9([H|T]) -> a9([H|T], H).

% Run-length encoding of a list.

a4c(L,[H|_]) -> [a4(L), H].

a10h([]) -> [];
a10h([H|T]) -> [a4c(H,H)| a10h(T)].

a10(L) -> a10h(a9(L)).

% Run-length encoding of a list.

a4d(L,[H|_]) ->
X = a4(L),
case X of
1 -> H;
_Other -> [X,H]
end.

a11h([]) -> [];
a11h([H|T]) -> [a4d(H,H)| a11h(T)].

a11(L) -> a11h(a9(L)).

% Decode a run-length encoded list.

unpack([0,_], R) -> R;
unpack([N,C|_],R) -> unpack([N-1,C], [C|R]).

a12([], R) -> R;
a12([H|T], R) when is_list(H) -> a12(T, unpack(H,R));
a12([H|T], R) -> a12(T, [H|R]).

a12(L) -> a5(a12(L, [])).

% Run-length encoding of a list (direct solution).
a13([],P,C, R) ->
case C of
1 -> [P|R];
_Other -> [[C,P]|R]
end;
a13([H|T], P, C, R) when H =:= P -> a13(T, P, C+1, R);
a13([H|T], P, C, R) when H =/= P ->
case C of
1 -> a13(T,H,1,[P|R]);
_Other -> a13(T,H,1,[[C,P]|R])
end.

a13([H|T]) -> a5(a13([H|T], H, 0, [])).

% Duplicate the elements of a list.
a14([]) -> [];
a14([H|T]) -> [H,H|a14(T)].

% https://prof.ti.bfh.ch/hew1/informatik3/prolog/p-99/
repeat(_,0) -> [];
repeat(C,T) -> [C|repeat(C, T-1)].

a15([],_) -> [];
a15([H|T],C) -> a7b([repeat(H,C)|a15(T, C)]).

% Drop every N'th element from a list.
a16([], _, _) -> [];
a16([_|T],C,N) when N rem C =:= 0 -> a16(T, C, N+1);
a16([H|T],C,N) -> [H|a16(T,C,N+1)].

a16(L,C) -> a16(L,C,1).

% Split a list into two parts; the length of the first part is given.
a17([],_,_,L) -> {a5(L),[]};
a17([H|T],N,R,L) when N =:= R -> {a5([H|L]), a5(T)};
a17([H|T],N,R,L) -> a17(T,N,R+1,[H|L]).

a17(L, 0) -> {L, []};
a17(L,N) -> a17(L,N,1,[]).

% Extract a slice from a list.
a18([],_,_,_) -> [];
a18([H|T],I,K,N) when N >= I, N =< K -> [H|a18(T,I,K,N+1)];
a18([_|T],I,K,N) -> a18(T,I,K,N+1).

a18(L,I,K) ->a18(L,I,K,1).

% Rotate a list N places to the left.
a19(L, N) -> SP = N rem a4(L),
if
SP < 0 -> S = a4(L) + SP;
true -> S = SP
end,
{H, T} = a17(L, S),
a7([T,H]).

% Remove the K'th element from a list.
a20([],_,_, L) -> L;
a20([H|T],N,I,L) when N =:= I -> {H, a5(a20(T,N,I+1,L))};
a20([H|T],N,I, L) -> a20(T,N, I+1, [H|L]).

a20(L,N) -> a20(L,N,1,[]).

% Insert an element at a given position into a list.

a21([],E,P,N) when P =:= N -> [E];
a21([],_,_,_) -> [];
a21([H|T], E, P, N) when P =:= N -> [E,H| a21(T,E,P,N + 1)];
a21([H|T], E, P, N) -> [H|a21(T, E, P, N+1)].

a21(L, E, P) -> a21(L, E, P, 1).

%*) Create a list containing all integers within a given range.
a22(A,B) when A > B -> [];
a22(A,B) -> [A|a22(A+1,B)].