outten.net - random thoughts

RPCFN #4 in Erlang

A few weeks ago I wanted to start learning Erlang. A co-worker pointed out the Ruby Programming Challenge for Newbies that they were completing in Ruby. I decided to try the RPCFN #4, but write it in Erlang. This probably isn’t the most concise or best implementation, but it was a good exercise to encourage me to look at Erlang.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
%% This was inspired from the ruby programming challenge for newbies.
%%   http://rubylearning.com/blog/2009/11/26/rpcfn-rubyfun-4/

-module (polynomials). %% -compile(export_all). -export([poly_epr/1]). -import(string, [concat/2]). -import(lists, [append/1]).

%% include the test module -include_lib("eunit/include/eunit.hrl").

%% Create a polynomial expression from an array of numbers polyepr(List) when is_list(List), length(List) >= 2 -> P = gen_epr([], List), case R=join_epr(P) of "" -> "0"; -> R end; polyepr() -> {error, "Need at least 2 coefficients"}.

%% generate the polyonmial expression genepr(Poly, []) -> case Poly of [] -> "0"; -> Poly end; gen_epr(Poly, [H|T]) -> Poly ++ gen_epr([term(H, length(T))], T).

%% join the expressions term together join_epr([]) -> "0"; join_epr([H|T]) -> H ++ append([check_neg(X) || X <- T]).

%% add appropreiate sign in front of expression term checkneg([]) -> ""; check_neg(Val="-" ++ T) -> Val; check_neg(Val) -> concat("+",Val).

%% create an expression term term(1, Expo) -> expo(Expo); term(-1, Expo) -> "-" ++ expo(Expo); term(0, Expo) -> ""; term(Val, 0) -> integer_to_list(Val); term(Val, Expo) when is_number(Val), is_number(Expo) -> concat(integer_to_list(Val), expo(Expo)); term(Val, _Expo) -> "".

%% create the exponent expression expo(1) -> "x"; expo(E) -> concat("x^", integer_to_list(E)).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% TESTS

%% term tests term1_test() -> "x^2" = term(1,2).

term_negative_value_test() -> "-x^2" = term(-1,2).

term0_test() -> "" = term(0,5).

term_zero_exponent_test() -> "5" = term(5,0).

term_bad_values_test() -> "" = term("str","more").

%% poly tests from the rpcfn poly_epr1_test() -> ?assert("3x^3+4x^2-3" =:= poly_epr([3,4,0,-3])).

poly_first_negative_test() -> ?assert("-3x^4-4x^3+x^2+6" =:= poly_epr([-3,-4,1,0,6])).

poly_simple_test() -> ?assert("x^2+2" =:= poly_epr([1,0,2])).

poly_first_minus_one_test() -> ?assert("-x^3-2x^2+3x" =:= poly_epr([-1,-2,3,0])).

poly_all_zera_test() -> ?assert("0" =:= poly_epr([0,0,0])).

poly_test_error_test() -> {error,Msg} = poly_epr([1]), ?assert("Need at least 2 coefficients" =:= Msg).

You need to have eunit setup in your code path. Then you can start the Erlang shell and run the tests. Really, they pass!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.4 (abort with ^G) 1> c(polynomials). {ok,polynomials} 2> polynomials:test(). All 11 tests passed. ok 3>