Skip to content

Instantly share code, notes, and snippets.

@huseyinyilmaz
Last active August 29, 2015 14:21
Show Gist options
  • Save huseyinyilmaz/db9817ebc334a08c8b1a to your computer and use it in GitHub Desktop.
Save huseyinyilmaz/db9817ebc334a08c8b1a to your computer and use it in GitHub Desktop.
Functional_programming_with_erlang week 1 and week 2
-module(file_index).
-export([clean/1]).
-export([getWord/1]).
-export([tokenize/1]).
-export([get_line/1]).
-export([enumerate/1]).
-export([parse_string/1]).
-export([invert/1]).
-export([get_sequence/2]).
-export([list_to_range/1]).
-export([index_file/1]).
-export([line_number_to_range/1]).
-include_lib("eunit/include/eunit.hrl").
%%%%%%%%%%%%%%%%%%
%% EXTERNAL_API %%
%%%%%%%%%%%%%%%%%%
%% parses given string and returns word mapping.
%% See tests for sample output.
-spec index_file(string()) -> [{string(), [{integer(),integer()}]}].
index_file(Input) ->
line_number_to_range(invert(parse_string(Input))).
%%%%%%%%%%%%%%%%%%%%%%%%
%% INTERNAL FUNCTIONS %%
%%%%%%%%%%%%%%%%%%%%%%%%
% predicate to check if given character is a whitespace
-spec isWhiteSpace(char()) -> boolean().
isWhiteSpace(Char) -> lists:member(Char, [$\n,$\t,$ ]).
% enumerate given list with item numbers
-spec enumerate([T]) -> [{integer(), T}].
enumerate(Xs)-> enumerate_inner(Xs, 1).
-spec enumerate_inner([T],integer())->[{integer(), T}].
enumerate_inner([], _) -> [];
enumerate_inner([X|Xs],Current) -> [{Current, X}|enumerate_inner(Xs, Current+1)].
% Split string into to at the first place given predicate returns true.
-spec splitFrom(string(), fun()) -> {string(), string()}.
splitFrom([], _isSeperator) -> {[],[]};
splitFrom([X|Xs]=Input, IsSeperator) ->
case IsSeperator(X) of
true -> {[], Input};
false ->
{Word, Rest} = splitFrom(Xs, IsSeperator),
{[X|Word], Rest}
end.
% get first word and rest of the string in a tuple.
-spec getWord(string()) -> {string(), string()}.
getWord(Input) -> splitFrom(Input, fun isWhiteSpace/1).
% removes whitespace at the end of the string.
-spec clean(string()) -> string().
clean([])->[];
clean([X|Xs]=Input) ->
case isWhiteSpace(X) of
true -> clean(Xs);
false -> string:to_lower(Input)
end.
% In case there is a whitspace in the beginning.
-spec tokenize(string()) -> [string()].
tokenize(Input) -> inner_tokenize(clean(Input)).
-spec inner_tokenize(string()) -> [string()].
inner_tokenize([])->[];
inner_tokenize(Input) ->
{Word, Rest} = getWord(Input),
[Word| tokenize(Rest)].
% separates a string into first line and the rest.
-spec get_line(string()) -> {string(),string()}.
get_line(Input) -> splitFrom(Input, fun(Char) -> Char == $\n end).
% gets a string and returns list of lines.
-spec get_lines(string()) -> [string()].
get_lines(Input) -> inner_get_lines(clean(Input)).
-spec inner_get_lines(string()) -> [string()].
inner_get_lines([])->[];
inner_get_lines(Input) ->
{Word, Rest} = get_line(Input),
[Word| get_lines(Rest)].
% parses a given string into lines and words.
-spec parse_string(string())-> [{integer(),[string()]}].
parse_string(Input) -> enumerate(parse_lines(get_lines(Input))).
% gets a list of lines and returns list of list of words.
-spec parse_lines([string()]) -> [[string()]].
parse_lines([]) -> [];
parse_lines([Line|Lines]) -> [tokenize(Line)| parse_lines(Lines)].
% convert line to wordlist mapping to word to line list mapping
-spec invert([{T,[V]}]) -> [{V, [T]}].
invert(Input) -> lists:keysort(1, inv(Input, [])).
-spec inv([{T, [V]}], [{V, [T]}]) -> [{V, [T]}].
inv([], Acc) -> Acc;
inv([{Key, Values}|Rest], Acc) -> inv(Rest, insert_keys(Values, Key, Acc)).
% insert given value to given key list.
-spec insert_keys([V], T, [{V, [T]}]) -> [{V, [T]}].
insert_keys([], _Value, Acc) -> Acc;
insert_keys([Key|Keys], Value, Acc)->
case proplists:lookup(Key, Acc) of
{Key, Values} ->
Acc1 = proplists:delete(Key, Acc),
Values1 = Values;
none -> Values1 = [],
Acc1 = Acc
end,
insert_keys(Keys, Value, [{Key, lists:sort([Value|Values1])}|Acc1]).
% split first sequence of numbers and the rest
get_sequence([], []) -> [];
get_sequence([],[X|_]=Seq) -> {{lists:last(Seq),X}, []};
get_sequence([X|Xs], []) -> get_sequence(Xs,[X]);
get_sequence([X|Xs], [Y|_]=Seq) when X == Y+1 -> get_sequence(Xs,[X|Seq]);
get_sequence(Xs, [X|_]=Seq)-> {{lists:last(Seq),X},Xs}.
% converts list of numbers to list of rangetuples
-spec list_to_range([integer()])->[{integer(),integer()}].
% gets a string and returns list of lines.
list_to_range([])->[];
list_to_range(Input) ->
{Seq, Rest} = get_sequence(Input, []),
[Seq| list_to_range(Rest)].
-spec line_number_to_range([{string(),[integer()]}]) -> [{string(), [{integer(), integer()}]}].
line_number_to_range([]) -> [];
line_number_to_range([{Key, LineNumbers}|Rest]) ->
[{Key, list_to_range(LineNumbers)}|line_number_to_range(Rest)].
%%%%%%%%%%
%% Test %%
%%%%%%%%%%
%% getWord
getWord_1_test() -> ?assertEqual(getWord("hello there"), {"hello", " there"}).
getWord_2_test() -> ?assertEqual(getWord(" hello there"), {"", " hello there"}).
getWord_3_test() -> ?assertEqual(getWord([]), {[], []}).
%% clean
clean_1_test() -> ?assertEqual(clean(" \t a"), "a").
clean_2_test() -> ?assertEqual(clean("a"), "a").
clean_3_test() -> ?assertEqual(clean(" \t \n a"), "a").
%% tokenize
tokenize_1_test() -> ?assertEqual(tokenize("a b"), ["a", "b"]).
tokenize_2_test() -> ?assertEqual(tokenize(" a b \t"), ["a", "b"]).
%% get_line
get_line_1_test() -> ?assertEqual(get_line("a\nb"), {"a", "\nb"}).
get_line_2_test() -> ?assertEqual(get_line("a\nb\nc"), {"a", "\nb\nc"}).
%% get_lines
get_lines_1_test() -> ?assertEqual(get_lines("a\nb"), ["a", "b"]).
get_lines_2_test() -> ?assertEqual(get_lines("a\nb\nc"), ["a", "b", "c"]).
get_lines_3_test() -> ?assertEqual(get_lines("a b\nc d\ne f"), ["a b", "c d", "e f"]).
%% enumerate
enumerate_1_test() -> ?assertEqual(enumerate([]), []).
enumerate_2_test() -> ?assertEqual(enumerate(["a","b", "c"]), [{1, "a"}, {2, "b"}, {3, "c"}]).
%% parse_string
parse_string_1_test() -> ?assertEqual(parse_string("a b c\nd e f\ng h i\nj k l"),
[{1,["a","b","c"]},
{2,["d","e","f"]},
{3,["g","h","i"]},
{4,["j","k","l"]}]).
%% invert
invert_1_test() -> ?assertEqual(invert([]), []).
invert_2_test() -> ?assertEqual(invert([{1,["a","b","c"]},
{2,["d","e","f"]},
{3,["g","h","i"]},
{4,["j","k","l"]}]),
[{"a",[1]}, {"b",[1]}, {"c",[1]},
{"d",[2]}, {"e",[2]}, {"f",[2]},
{"g",[3]}, {"h",[3]}, {"i",[3]},
{"j",[4]}, {"k",[4]}, {"l",[4]}]).
invert_3_test() -> ?assertEqual(invert([{1,["a","b","c"]},
{2,["d","e","f"]},
{3,["a","b","c"]},
{4,["d","e","f"]}]),
[{"a",[1,3]},
{"b",[1,3]},
{"c",[1,3]},
{"d",[2,4]},
{"e",[2,4]},
{"f",[2,4]}]).
%% get_sequence
get_sequence_1_test() -> ?assertEqual(get_sequence([],[]), []).
get_sequence_2_test() -> ?assertEqual(get_sequence([1,2,3,5,6],[]), {{1,3}, [5, 6]}).
%% list_to_range
list_to_range_1_test() -> ?assertEqual(list_to_range([]), []).
list_to_range_2_test() -> ?assertEqual(list_to_range([1,2,3,5,6]), [{1, 3}, {5, 6}]).
list_to_range_3_test() -> ?assertEqual(list_to_range([1,2,3,5,6,7,9]),
[{1, 3}, {5, 7}, {9, 9}]).
%% line_number_to_range
line_number_to_range_1_test() -> ?assertEqual(line_number_to_range([]), []).
line_number_to_range_2_test() -> ?assertEqual(line_number_to_range([{"a", [1,2,3,6,7,9]},
{"b", [4, 7]},
{"c",[1,2,3]}]),
[{"a", [{1,3}, {6,7}, {9,9}]},
{"b", [{4,4}, {7,7}]},
{"c", [{1,3}]}]).
%% index file
index_file_1_test() -> ?assertEqual(index_file("a b c\nd e f\ng h i\nj k l"),
[{"a",[{1,1}]},{"b",[{1,1}]},{"c",[{1,1}]},
{"d",[{2,2}]},{"e",[{2,2}]},{"f",[{2,2}]},
{"g",[{3,3}]},{"h",[{3,3}]},{"i",[{3,3}]},
{"j",[{4,4}]},{"k",[{4,4}]},{"l",[{4,4}]}]).
index_file_2_test() -> ?assertEqual(index_file("c b a\na b c\na d e\ne f g"),
[{"a",[{1,3}]},{"b",[{1,2}]},{"c",[{1,2}]},
{"d",[{3,3}]}, {"e",[{3,4}]}, {"f",[{4,4}]},
{"g",[{4,4}]}]).
% test caseinsensitivity
index_file_3__test() -> ?assertEqual(index_file("a b c\nA B C\na D E\ne f g"),
[{"a",[{1,3}]},{"b",[{1,2}]},{"c",[{1,2}]},
{"d",[{3,3}]}, {"e",[{3,4}]}, {"f",[{4,4}]},
{"g",[{4,4}]}]).
-module(nub).
-include_lib("eunit/include/eunit.hrl").
-export([nub/1]).
-export([nub2/1]).
% keep first elements
nub([], Acc) -> Acc;
nub([X|Xs], Acc) ->
Acc1 = case lists:member(X, Acc) of
true -> Acc;
false -> [X|Acc]
end,
nub(Xs, Acc1).
nub(Xs)-> lists:reverse(nub(Xs,[])).
% keep last elements
nub2([])->[];
nub2([X|Xs])->
Rest = nub2(Xs),
case lists:member(X, Rest) of
true -> Rest;
false -> [X| Rest]
end.
%%%===================================================================
%%% Tests
%%%===================================================================
nub_1_test() -> ?assert(nub([]) == []).
nub_2_test() -> ?assert(nub([1, 2, 3]) == [1, 2, 3]).
nub_3_test() -> ?assert(nub([1, 2, 2, 3]) == [1, 2, 3]).
nub_4_test() -> ?assert(nub([1, 2, 3, 2, 4]) == [1, 2, 3, 4]).
nub2_1_test() -> ?assert(nub2([]) == []).
nub2_2_test() -> ?assert(nub2([1, 2, 3]) == [1, 2, 3]).
nub2_3_test() -> ?assert(nub2([1, 2, 2, 3]) == [1, 2, 3]).
nub2_4_test() -> ?assert(nub2([1, 2, 3, 2, 4]) == [1, 3, 2, 4]).
-module(one_five).
-include_lib("eunit/include/eunit.hrl").
-export([product/1]).
-export([product2/1]).
-export([maximum/1]).
-export([maximum2/1]).
product([]) -> 1;
product([X|Xs]) -> X* product(Xs).
product2([], Acc) -> Acc;
product2([X|Xs], Acc) -> product2(Xs, X * Acc).
product2(Xs)-> product2(Xs, 1).
maximum([X]) -> X;
maximum([X|Xs]) -> max(X, maximum(Xs)).
maximum2([], Max) -> Max;
maximum2([X|Xs], Max) -> maximum2(Xs, max(X, Max)).
maximum2([X|Xs]) -> maximum2(Xs, X).
%%%%%%%%%%%
%% TESTS %%
%%%%%%%%%%%
product_1_test() -> ?assert(product([]) == 1).
product_2_test() -> ?assert(product([3]) == 3).
product_3_test() -> ?assert(product([3, 4, 5]) == 60).
product2_1_test() -> ?assert(product2([]) == 1).
product2_2_test() -> ?assert(product2([3]) == 3).
product2_3_test() -> ?assert(product2([3, 4, 5]) == 60).
maximum_1_test() -> ?assert(maximum([2]) == 2).
maximum_2_test() -> ?assert(maximum([2, 5, 4]) == 5).
maximum_3_test() -> ?assert(maximum([2, 4, 4, 3]) == 4).
maximum_4_test() -> ?assert(maximum([2, -5, 4, 3]) == 4).
maximum2_1_test() -> ?assert(maximum2([2]) == 2).
maximum2_2_test() -> ?assert(maximum2([2, 5, 4]) == 5).
maximum2_3_test() -> ?assert(maximum2([2, 4, 4, 3]) == 4).
maximum2_4_test() -> ?assert(maximum2([2, -5, 4, 3]) == 4).
-module(one_seven).
-include_lib("eunit/include/eunit.hrl").
-export([double/1]).
-export([double2/1]).
-export([evens/1]).
-export([evens2/1]).
-export([nub/1]).
-export([member/2]).
%%%===================================================================
%%% API
%%%===================================================================
double([]) -> [];
double([X|Xs]) -> [X*2|double(Xs)].
double2([], Acc) -> Acc;
double2([X|Xs], Acc) -> double2(Xs, [X*2|Acc]).
double2(Xs)-> reverse(double2(Xs,[])).
evens([])-> [];
evens([X|Xs]) when (X rem 2) == 0 -> [X|evens(Xs)];
evens([X|Xs]) when (X rem 2) =/=0 -> evens(Xs).
evens2([], Acc)-> Acc;
evens2([X|Xs], Acc) when (X rem 2) == 0 -> evens2(Xs, [X|Acc]);
evens2([X|Xs], Acc) when (X rem 2) =/= 0 -> evens2(Xs, Acc).
evens2(Xs)-> reverse(evens2(Xs,[])).
% remove all repeated elements
nub([], Acc) -> Acc;
nub([X|Xs], Acc) ->
Acc1 = case member(X, Acc) of
true -> Acc;
false -> [X|Acc]
end,
nub(Xs, Acc1).
nub(Xs)-> reverse(nub(Xs,[])).
% list of numbers
%% median(Xs)->
%% Length = len(xs),
%% case Length rem 1 == 0
%%%===================================================================
%%% Internal functions
%%%===================================================================
reverse([], Acc) -> Acc;
reverse([X|Xs], Acc) -> reverse(Xs, [X|Acc]).
reverse(Xs)->reverse(Xs, []).
member(_Elem,[])->false;
member(Elem,[Elem|_Xs])->true;
member(Elem,[_X|Xs])->member(Elem, Xs).
%% len([]) -> 0;
%% len([_X|Xs]) -> 1 + len(Xs).
%%%%%%%%%%%
%% TESTS %%
%%%%%%%%%%%
double_1_test() -> ?assert(double([]) == []).
double_2_test() -> ?assert(double([3]) == [6]).
double_3_test() -> ?assert(double([3, 4]) == [6, 8]).
double2_1_test() -> ?assert(double2([]) == []).
double2_2_test() -> ?assert(double2([3]) == [6]).
double2_3_test() -> ?assert(double2([3, 4]) == [6, 8]).
evens_1_test() -> ?assert(evens([]) == []).
evens_2_test() -> ?assert(evens([1,2,3,4]) == [2,4]).
evens_3_test() -> ?assert(evens([1,3,5]) == []).
evens2_1_test() -> ?assert(evens2([]) == []).
evens2_2_test() -> ?assert(evens2([1,2,3,4]) == [2,4]).
evens2_3_test() -> ?assert(evens2([1,3,5]) == []).
nub_1_test() -> ?assert(nub([]) == []).
nub_2_test() -> ?assert(nub([1, 2, 3]) == [1, 2, 3]).
nub_3_test() -> ?assert(nub([1, 2, 2, 3]) == [1, 2, 3]).
nub_4_test() -> ?assert(nub([1, 2, 3, 2]) == [1, 2, 3]).
-module(take).
%% API
-export([take/2]).
-include_lib("eunit/include/eunit.hrl").
%%%===================================================================
%%% API
%%%===================================================================
-spec take(integer(), [T]) -> [T].
take(0, _Xs) -> [];
take(_N, []) -> [];
take(N,[X|Xs]) when N>0 -> [X|take(N-1, Xs)].
%%%===================================================================
%%% Tests
%%%===================================================================
take_1_test() -> ?assert(take(0,"hello") == []).
take_2_test() -> ?assert(take(4,"hello") == "hell").
take_3_test() -> ?assert(take(5,"hello") == "hello").
take_4_test() -> ?assert(take(9,"hello") == "hello").
-module(two_ten).
-include_lib("eunit/include/eunit.hrl").
%% API
-export([concat/1]).
-export([join/2]).
-export([getWord/1]).
-export([mergeSort/1]).
-export([split/1]).
-export([pivotSplit/2]).
-export([quickSort/1]).
-export([insertionSort/1]).
%% -export([listAppend/2]).
%% -export([mappend/2]).
%%%===================================================================
%%% API
%%%===================================================================
-spec join([T], [T]) -> [T].
join([], Ys) -> Ys;
join([X|Xs], Ys) -> [X|join(Xs,Ys)].
-spec concat([[T]]) -> [T].
concat([])->[];
concat([Xs|Rest])-> join(Xs, concat(Rest)).
-spec member(_, [_])-> boolean().
member(_Elem,[])->false;
member(Elem,[Elem|_Xs])->true;
member(Elem,[_X|Xs])->member(Elem, Xs).
-spec getWord([T]) -> [T].
getWord([]) -> [];
getWord([X|Xs]) ->
case member(X, [$\n,$\t,$ ]) of
true ->
[];
false ->
[X|getWord(Xs)]
end.
-spec mergeSort([T]) -> [T].
mergeSort([])-> [];
mergeSort([X]) -> [X];
mergeSort(Xs)->
{First, Second} = split(Xs),
merge(mergeSort(First),mergeSort(Second)).
quickSort([]) -> [];
quickSort([X|Xs])->
{Smaller, Larger} = pivotSplit(X, Xs),
quickSort(Smaller) ++ [X] ++ quickSort(Larger).
insertionSort([]) -> [];
insertionSort([X|Xs]) ->
orderInsert(X, insertionSort(Xs)).
%% perms([])-> [];
%% perms([X|Xs])->
%% mappend(X,perms(Xs)).
%Add list of elements to list of lists.
%% mappend([], Xs)->[];
%% mappend([Y|Ys], Xs)-> listAppend(Y, Xs)++mappend(Ys,Xs).
%% % Add element Y to all lists in the list.
%% listAppend(Y, []) -> [];
%% listAppend(Y, [Xs|Rest])-> [[Y|Xs]|listAppend(Y, Rest)].
%%%===================================================================
%%% Internal functions
%%%===================================================================
% split a list into 2
-spec split([T])->{[T], [T]}.
split(Xs) -> split(Xs, {[],[]}).
split([], {_First, _Second}=Result) -> Result;
split([X], {First, Second}) -> {[X|First], Second};
split([X,Y|Xs],{First, Second}) -> split(Xs, {[X|First], [Y|Second]}).
% split a list into 2 according to a pivot value.
% if element is smaller than the pivot it goes to first list otherwise
% it goes to second list.
-spec pivotSplit(T, [T]) -> {[T], [T]}.
pivotSplit(Pivot, Xs) -> pivotSplit(Pivot,Xs,{[],[]}).
pivotSplit(_Pivot, [], {_Smaller, _Larger}=Result) -> Result;
pivotSplit(Pivot, [X|Xs],{Smaller,Larger}) when X<Pivot ->
pivotSplit(Pivot, Xs, {[X|Smaller],Larger});
pivotSplit(Pivot, [X|Xs], {Smaller,Larger}) when X>=Pivot->
pivotSplit(Pivot, Xs, {Smaller, [X|Larger]}).
% merges two sorted lists into one merge("ace", "bd") -> "abcde"
-spec merge([T],[T]) -> [T].
merge([],Ys) -> Ys;
merge(Xs,[]) -> Xs;
merge([X|XRest],[Y|_]=Ys) when X<Y -> [X|merge(XRest,Ys)];
merge([X|_]=Xs,[Y|YRest]) when X>=Y -> [Y|merge(Xs,YRest)].
% insert Elem into Xs list in right place.
orderInsert(Elem, []) -> [Elem];
orderInsert(Elem, [X|_]=Xs) when Elem<X -> [Elem|Xs];
orderInsert(Elem, [X|Xs]) when Elem>=X -> [X|orderInsert(Elem, Xs)].
%%%===================================================================
%%% Tests
%%%===================================================================
join_1_test() -> ?assert(join("hel", "lo") == "hello").
join_2_test() -> ?assert(join("hello", []) == "hello").
join_3_test() -> ?assert(join([], "hello") == "hello").
concat_1_test() -> ?assert(concat([]) == []).
concat_2_test() -> ?assert(concat(["h","e","l","l","o"]) == "hello").
concat_3_test() -> ?assert(concat(["hel","lo"]) == "hello").
member_1_test() -> ?assert(member(2, [2, 0, 0, 1]) == true).
member_2_test() -> ?assert(member(2, [0, 2, 0, 1]) == true).
member_3_test() -> ?assert(member(20, [2, 0, 0, 1]) == false).
getWord_1_test() -> ?assert(getWord("hello there") == "hello").
getWord_2_test() -> ?assert(getWord(" hello there") == "").
getWord_3_test() -> ?assert(getWord([]) == []).
split_1_test() -> ?assert(split("abcde") == {"eca", "db"}).
split_2_test() -> ?assert(split("a") == {"a", []}).
split_3_test() -> ?assert(split([]) == {[], []}).
mergeSort_1_test() -> ?assert(mergeSort([]) == []).
mergeSort_2_test() -> ?assert(mergeSort([1]) == [1]).
mergeSort_3_test() -> ?assert(mergeSort([1, 3, 2]) == [1, 2, 3]).
pivotSplit_1_test() -> ?assert(pivotSplit($c, "abcde") == {"ba", "edc"}).
pivotSplit_2_test() -> ?assert(pivotSplit($a, "abcde") == {[], "edcba"}).
pivotSplit_3_test() -> ?assert(pivotSplit($e, "abcde") == {"dcba","e"}).
pivotSplit_4_test() -> ?assert(pivotSplit($a, []) == {[],[]}).
quickSort_1_test() -> ?assert(quickSort([]) == []).
quickSort_2_test() -> ?assert(quickSort([1]) == [1]).
quickSort_3_test() -> ?assert(quickSort([1, 3, 2]) == [1, 2, 3]).
insertionSort_1_test() -> ?assert(insertionSort([]) == []).
insertionSort_2_test() -> ?assert(insertionSort([1]) == [1]).
insertionSort_3_test() -> ?assert(insertionSort([1, 3, 2]) == [1, 2, 3]).
%% perms_1_test() -> ?assert(perms([]) == [[]]).
%% perms_2_test() -> ?assert(perms([1,2,3]) == [[1,2,3],[2,3,1],[3,1,2],
%% [2,1,3],[1,3,2],[3,2,1]]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment