Assignment 5

Rewrite the following Picat functions and predicates in Java or C++, using recursion if possible.

%%% Arithmetic functions and relations
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

succ(X) = X+1.

pred(X) = X-1.

add(0,Y) = Y.
add(X,Y) = succ(add(pred(X),Y)).

sub(X,0) = X.
sub(X,Y) = sub(pred(X),pred(Y)).

mul(0,_) = 0.
mul(X,Y) = add(mul(pred(X),Y),Y).

% name it my_div, because div/2 is a built-in in Picat
my_div(X,Y) = 0, lt(X,Y) => true.
my_div(X,Y) = succ(my_div(sub(X,Y),Y)).

% rem/2 is a built-in function
my_rem(X,Y) = X, lt(X,Y) => true.   % if X < Y
my_rem(X,Y) = my_rem(sub(X,Y),Y).

exp(_,0) = succ(0).
exp(X,Y) = mul(X,exp(X,pred(Y))).

% factorial/1 is a built-in function
fact(0) = 1.
fact(X) = mul(X,fact(pred(X))).

% gcd/2 is a built-in function
my_gcd(0,Y) = Y.
my_gcd(X,0) = X.
my_gcd(X,Y) = my_gcd(Y,rem(X,Y)).

fib(1) = succ(0).
fib(2) = succ(0).
fib(X) = add(fib(pred(X)),fib(pred(pred(X)))).

%% predicates
% X <= Y
le(0,_) => true.
le(_,0) => fail.
le(X,Y) => le(pred(X),pred(Y)).

% X < Y
lt(X,Y) => le(succ(X),Y).

gt(X,Y) => lt(Y,X).

ge(X,Y) => le(Y,X).

eq(X,Y) => ge(X,Y), ge(Y,X).

%%% Functions and predicates on lists.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

my_first([H|_]) = H.

my_last([X]) = X.
my_last([_|T]) = my_last(T).

contains([E|_],E) => true.
contains([_|T],E) => contains(T,E).

find_first_of(L,E) = find_first_of(L,E,1).

find_first_of([E|_],E,I) = I.
find_first_of([_|T],E,I) = find_first_of(T,E,I+1).
find_first_of([],_E,_I) = -1.

find_last_of(L,E) = find_last_of(L,E,1,-1).

find_last_of([],_E,_I,PreI) = PreI.
find_last_of([E|T],E,I,_PreI) = find_last_of(T,E,I+1,I).
find_last_of([_|T],E,I,PreI) = find_last_of(T,E,I+1,PreI).

% the kth_elm(L,K) is the same as L[K]
kth_elm([E|_],1) = E.
kth_elm([_|T],K) = kth_elm(T,K-1).

my_len([]) = 0.
my_len([_|T]) = my_len(T)+1.

my_reverse([]) = [].
my_reverse([H|T]) = my_reverse(T) ++ [H].

main =>
   test_arith,
   test_list.

test_arith =>
   X = succ(succ(succ(0))),   % 3
   Y = succ(succ(0)),         % 2
   printf("%w + %w = %w\n", X, Y, add(X,Y)),
   printf("%w - %w = %w\n", X, Y, sub(X,Y)),   
   printf("%w * %w = %w\n", X, Y, mul(X,Y)),
   printf("%w / %w = %w\n", X, Y, my_div(X,Y)),
   printf("%w %% %w = %w\n", X, Y, my_rem(X,Y)),
   printf("%w ^ %w = %w\n", X, Y, exp(X,Y)),
   printf("%w! = %w\n", X, fact(X)),
   printf("gcd(%w,%w) = %w\n", X, Y, my_gcd(X,Y)),
   printf("fib(%w) = %w\n", X, fib(X)).

test_list =>
   L = [a,b,c,a,b],
   writef("first(%w) = %w\n", L, my_first(L)),
   writef("last(%w) = %w\n", L, my_last(L)),
   if contains(L,a) then
       writef("%w contains %w.\n", L, a)
   end,
   writef("find_first_of(%w,%w) = %w\n", L, b, find_first_of(L,b)),
   writef("find_last_of(%w,%w) = %w\n", L, b, find_last_of(L,b)),
   writef("kth(%w,%w) = %w\n", L, 3, kth_elm(L,3)),
   writef("len(%w) = %w\n", L, my_len(L)),
   writef("reverse(%w) = %w\n", L, my_reverse(L)).