E-99: 11-20
The second set of 10 problems are now in the bag. Feeling the Erlang-fu! The first set can be found here.
%% Modified run-length encoding.
%% Modify the result of problem P10 in such a way that if an element
%% has no duplicates it is simply copied into the result list.
%% Only elements with duplicates are transferred as (N E) lists.
%% Example: (encode-modified '(a a a a b c c a a d e e e e)) ->
%% ((4 A) B (2 C) (2 A) D (4 E))
p11([]) -> [];
p11(L) ->
p11encode(p09(L), []).
p11encode([], Encoded) ->
lists:reverse(Encoded);
p11encode([[Elem | SubL] | L], Encoded) ->
case length(SubL) of
0 -> p11encode(L, [Elem | Encoded]);
_Else ->
p11encode(L, [[length(SubL)+1, Elem] | Encoded])
end.
%% Decode a run-length encoded list.
%% Given a run-length code list generated as specified in problem
%% P11. Construct its uncompressed version.
p12([]) -> [];
p12(L) -> p12decode(L, []).
p12decode([], Decoded) ->
lists:reverse(Decoded);
p12decode([[N, Elem] | L], Decoded) ->
p12decode(L, lists:duplicate(N, Elem) ++ Decoded);
p12decode([Elem | L], Decoded) ->
p12decode(L, [Elem | Decoded]).
%% Run-length encoding of a list (direct solution).
%% Implement the so-called run-length encoding data compression method
%% directly.
%% I.e. don't explicitly create the sublists containing the
%% duplicates, as in problem P09, but only count them.
%% As in problem P11, simplify the result list by replacing the
%% singleton lists (1 X) by X.
%% Example: (encode-direct '(a a a a b c c a a d e e e e)) ->
%% ((4 A) B (2 C) (2 A) D (4 E))
p13([]) -> [];
p13([H | L]) ->
p13encode(L, H, 1, []).
%% p13encode(The Remaining List,
%% The Current Element,
%% The Number Of Repetitions Thus Far,
%% The Encoded List Thus Far)
p13encode([], Curr, Rep, Encoded) ->
case Rep of
1 -> lists:reverse([Curr | Encoded]);
_Else -> lists:reverse([[Rep, Curr] | Encoded])
end;
p13encode([H | L], Curr, Rep, Encoded) ->
case H of
Curr ->
p13encode(L, Curr, Rep+1, Encoded);
_Else ->
case Rep of
1 ->
p13encode(L, H, 1, [Curr | Encoded]);
_Other -> p13encode(L, H, 1, [[Rep, Curr] | Encoded])
end
end.
%% Duplicate the elements of a list.
%% Example: (dupli '(a b c c d)) -> (A A B B C C C C D D)
p14([]) -> [];
p14([H | L]) -> p14duplicate(L, [H, H]).
p14duplicate([], Cloned) -> lists:reverse(Cloned);
p14duplicate([H | L], Cloned) ->
p14duplicate(L, [H, H | Cloned]).
%% Replicate the elements of a list a given number of times.
%% Example: (repli '(a b c) 3) -> (A A A B B B C C C)
p15([], _Num) -> [];
p15([H | L], Reps) ->
p15replicate(L, Reps, [lists:duplicate(Reps, H)]).
p15replicate([], _Reps, Replicated) ->
lists:append(lists:reverse(Replicated));
p15replicate([H | L], Reps, Replicated) ->
p15replicate(L, Reps, [lists:duplicate(Reps, H) | Replicated]).
%% Drop every N'th element from a list.
%% Example: (drop '(a b c d e f g h i k) 3) -> (A B D E G H K)
p16([], _Nth) -> [];
p16([H | L], Nth) -> p16drop(L, Nth, Nth-1, [H]).
p16drop([], _Nth, _Curr, Dropped) -> lists:reverse(Dropped);
p16drop([_H | L], Nth, Curr, Dropped) when Curr == 1 ->
p16drop(L, Nth, Nth, Dropped);
p16drop([H | L], Nth, Curr, Dropped) ->
p16drop(L, Nth, Curr-1, [H | Dropped]).
%% Split a list into two parts; the length of the first part is given.
%% Do not use any predefined predicates.
%% Example: (split '(a b c d e f g h i k) 3) -> ( (A B C) (D E F G H I K))
p17([], _SplitPoint) -> [];
p17(L, SplitPoint) ->
p17split(L, SplitPoint, []).
p17split([], _SplitPoint, List) ->
lists:reverse(List);
p17split(L, SplitPoint, Head) when SplitPoint == 0 ->
[lists:reverse(Head) | [L]];
p17split([H | L], SplitPoint, Head) ->
p17split(L, SplitPoint-1, [H | Head]).
%% Extract a slice from a list.
%% Given two indices, I and K, the slice is the list containing the
%% elements between the I'th and K'th element of the original list
%% (both limits included). Start counting the elements with 1.
%% Example: (slice '(a b c d e f g h i k) 3 7) -> (C D E F G)
p18([], _Start, _End) -> [];
p18(L, Start, End) -> p18slice(L, Start, End-Start, []).
p18slice([], _Start, _Count, Sliced) ->
lists:reverse(Sliced);
p18slice([H | _L], 1, 0, Sliced) ->
lists:reverse([H | Sliced]);
p18slice([H | L], 1, Count, Sliced) ->
p18slice(L, 1, Count-1, [H | Sliced]);
p18slice([_H | L], Start, Count, Sliced) ->
p18slice(L, Start-1, Count, Sliced).
%% Rotate a list N places to the left.
%% Examples: (rotate '(a b c d e f g h) 3) -> (D E F G H A B C)
%% (rotate '(a b c d e f g h) -2) -> (G H A B C D E F)
%% Hint: Use the predefined functions length and append, as well as
%% the result of problem P17.
p19([], _Rotate) -> [];
p19(L, Rotate) ->
case Rotate of
Point when Rotate > 0 -> Point;
_LT0 ->
Point = length(L) + Rotate
end,
[F, B] = lp:p17(L, Point),
B ++ F.
%% Remove the K'th element from a list.
%% Example: (remove-at '(a b c d) 2) -> (A C D)
p20([], _Point) -> [];
p20(L, Point) ->
p20remove(L, Point, []).
p20remove([], _Point, BeforePoint) ->
lists:reverse(BeforePoint);
p20remove([_H | L], 1, BeforePoint) ->
lists:reverse(BeforePoint) ++ L;
p20remove([H | L], Point, BeforePoint) ->
p20remove(L, Point-1, [H | BeforePoint]).