Skip to content

Instantly share code, notes, and snippets.

@german
Last active December 15, 2015 16:59
Show Gist options
  • Save german/5293049 to your computer and use it in GitHub Desktop.
Save german/5293049 to your computer and use it in GitHub Desktop.
Polynom substitution task for Erlang master classes
-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">>)].
@german
Copy link
Author

german commented Apr 2, 2013

1> c(polynom).
{ok,polynom}
2> eunit:test(polynom).
Test passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment