Skip to content

Instantly share code, notes, and snippets.

@2torus
Created May 10, 2020 20:12
Show Gist options
  • Save 2torus/e44951f20332b5565e4838abb119119c to your computer and use it in GitHub Desktop.
Save 2torus/e44951f20332b5565e4838abb119119c to your computer and use it in GitHub Desktop.
Exercise 2.18 of FutureLearn Erlang
-module(ex2_18).
-export([double/1, filter/1, median/1, modes/1]).
% tail recursive solutions, so they need reverse
% there is probably a library function for that.
reverse([], S) -> S;
reverse([X|Xs], S) -> reverse(Xs, [X|S]).
double(X) -> reverse(double(X,[]), []).
double([], L) -> L;
double([X|Xs], L) -> double(Xs, [2 * X|L]).
filter(X) -> reverse(filter(X, []), []).
filter([], L) -> L;
filter([X|Xs], L) when X rem 2 == 0 -> filter(Xs, [X|L]);
filter([_|Xs], L) -> filter(Xs, L).
% the easier solution is to count length and then take the middle element
% that's less interesting. I'll do a more convoluted one:
% two traversals, one at double speed, when the faster one
% reaches the end, the second one should be in the middle
% assumes that list is sorted
median([X]) -> X; %edge case 1
median([X,Y]) -> (X + Y) / 2; %edge case 2
median([X|Xs]) -> median([X|Xs], Xs). % we actually need to skip one in the second traversal since at at element 2k + 1 we want to retrieve k'th element
median([X|_], []) -> X;
median([X, Y|_], [_]) -> (X + Y) / 2;
median([_|Xs], [_, _|Zs]) -> median(Xs, Zs).
% turn [a,a,a,...b,b,b,] into associative array [{a, N}, ...{b, M}...]
% and then find the most frequent element..
to_assoc_array([], Xs) -> Xs;
to_assoc_array([X|Xs], [{X, N}|Ys]) -> to_assoc_array(Xs,[{X, N+1}|Ys]);
to_assoc_array([X|Xs], Ys) -> to_assoc_array(Xs, [{X, 1}|Ys]).
argmax_assoc_array([{X,_}])-> X;
argmax_assoc_array([{X,N}, {_,M}|Xs]) when N >= M ->
argmax_assoc_array([{X,N}|Xs]);
argmax_assoc_array([_|Xs]) -> argmax_assoc_array(Xs).
modes(X) -> argmax_assoc_array(to_assoc_array(X, [])).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment