Last active
December 15, 2015 16:59
-
-
Save german/5293049 to your computer and use it in GitHub Desktop.
Polynom substitution task for Erlang master classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(polynom). | |
-export([digest/1, polynom/1]). | |
%% auxiliary functions | |
to_power_acc(_, Acc, 0) -> Acc; | |
to_power_acc(X, Acc, Power) -> to_power_acc(X, (Acc * X), (Power - 1)). | |
to_power(X, Power) -> to_power_acc(X, 1, Power). | |
concat_list_acc([], Acc) -> Acc; | |
concat_list_acc([H|T], Acc) -> concat_list_acc(T, string:concat(Acc, H)). | |
concat_list(L) -> concat_list_acc(L, ""). | |
to_float_or_skip(X) -> | |
case string:to_float(X) of | |
{error, _} -> 0; | |
{K, _Rest} -> K | |
end. | |
calculate_symbolic_operator(K) -> | |
if K >= 0 -> " + "; | |
true -> " " | |
end. | |
calculate_symbolic_addendum(Coeff, X, Power) -> | |
if | |
Power =:= 0 -> Coeff; | |
Power =:= 1 -> concat_list([Coeff, "*", io_lib:write(X)]); %% we should write "4.5*7.0" instead of "1.0*(7.0^1)" | |
true -> concat_list([Coeff, "*(", io_lib:write(X), "^", integer_to_list(Power), ")"]) | |
end. | |
%% core function | |
make_substitution_acc([H | T], X, StringAcc, Result, Len) -> | |
case is_float(H) of | |
false -> | |
case is_integer(H) of | |
false -> make_substitution_acc(T, X, StringAcc, Result, (Len - 1)); %% just skip current coeff | |
true -> make_substitution_acc([(H * 1.0)] ++ T, X, StringAcc, Result, Len ) %% convert coeff to float | |
end; | |
true -> | |
ToStringAcc = calculate_symbolic_addendum(io_lib:write(H), X, Len), | |
NewResult = Result + (H * to_power(X, Len)), | |
Op = if | |
StringAcc =:= "" -> ""; %% in beginning of the calculations '+' sign is unnecessary | |
true -> calculate_symbolic_operator(H) | |
end, | |
make_substitution_acc(T, X, concat_list([StringAcc, Op, ToStringAcc]), NewResult, (Len - 1)) | |
end; | |
make_substitution_acc([], _, Acc, Result, _) -> | |
list_to_binary(concat_list([Acc, " = ", io_lib:write(Result)])). | |
%% accumulator here will be a string | |
make_substitution(Koeffs, X) -> make_substitution_acc(Koeffs, X, "", 0, (length(Koeffs) - 1)). | |
polynom(Koeffs) -> | |
fun(Y) -> make_substitution(Koeffs, (Y * 1.0)) end. | |
%% test function to work with coefficients stored in file | |
digest(X) -> | |
{_Ok, S} = file:open("polynom.dat", read), | |
Coeffs = io:get_line(S, ''), | |
file:close(S), | |
Coeffs_splited = re:split(Coeffs, ",", [{return,list}]), | |
PolynomFun = polynom(lists:map(fun(Y) -> to_float_or_skip(Y) end, Coeffs_splited)), | |
io:format("~p~n", [PolynomFun(X)]). | |
-include_lib("eunit/include/eunit.hrl"). | |
polynom_test() -> | |
P = polynom([1,1,1]), | |
[?assertEqual(P(1), <<"1.0*(1.0^2) + 1.0*1.0 + 1.0 = 3.0">>)], | |
P1 = polynom([1.0, 2.0, -4.5]), | |
[?assertEqual(P1(7), <<"1.0*(7.0^2) + 2.0*7.0 -4.5 = 58.5">>)]. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
1> c(polynom).
{ok,polynom}
2> eunit:test(polynom).
Test passed.