0

This is my code, problem is, that last element of list is not in absolute value. Can anybody help?

maxlist( [X], X ).
maxlist( [X,Y|Rest], AbsMax ) :-
  abs( [X], AbsX ),
  maxlist( [Y|Rest], AbsMaxRest ),
  max( AbsX, AbsMaxRest, AbsMax ).


max( X, Y, X ) :- X >= Y.
max( X, Y, Y ) :- X <  Y.

abs( [X], Y ) :-
  X < 0 -> Y is -X ; Y = X.

For a list that goes like this:

maxlist( [-4110,-11,-885,-45,-154,-995] , X )

I get X = 4110, but for the last item

maxlist( [-995,-11,-885,-45,-154,-4110], X )j

I get X = 995, when I should get 4110.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • Solved it right now. – MatejMistik Apr 01 '21 at 19:02
  • maxlist([X],X). maxlist([X,Y|Rest],AbsMax) :- abs(X,AbsX), abs(Y,AbsY), maxlist([AbsY | Rest],AbsMaxRest), max(AbsX,AbsMaxRest,AbsMax). max(X,Y,X) :- X>= Y. max(X,Y,Y) :- X < Y. abs(X,Y) :- X < 0 -> Y is -X ; Y = X. – MatejMistik Apr 01 '21 at 19:02
  • If you have solved it, feel free to answer your own question. And even to mark it as the accepted answer (though you won't get any reputation points for that). Doing so helps others see your problem and the solution. – Nicholas Carey Apr 01 '21 at 20:06

2 Answers2

1

The essential problem in your code is that the last element of the list never has its absolute value taken. Also, you don't need to implement predicates for absolute value or max: they're baked into Prolog.

A common idiom in Prolog is the use of a public predicate with a "private" helper predicate that takes one or more additional arguments that carry state necessary for the computation. This also helps get things into the form necessary for tail recursion optimization, where the recursion is transformed into simple iteration by allowing the stack frame to be reused.

Try something like this:

max_list( [X|Xs] , M ) :-     % to compute the maximum absolute value of a list ...
  A is abs( X ) ,             % * Pop the head of the list and take its absolute value, then...
  max_list( Xs, A, M ) .      % * Invoke the helper, seeding the accumulator with A

max_list( []     , M , M ) .  % If the source list is empty, we're done.
max_list( [X|Xs] , T , M ) :- % Otherwise...
  X1 is abs(X) ,              % * Take the absolute value of X
  T1 is max(X1,T) ,           % * Determine the max of X1 and T
  max_list(Xs, T1, M )        % * Recurse down with the remainder of the list and the new accumulator value
  .                           % Easy!

And if you need to figure out max or abs on your own, it's pretty trivial:


max( X , Y , Max ) :- X >  Y -> Max is X ; Max is  Y .
abs( X ,     Abs ) :- X >= 0 -> Abs is X ; Abs is -X .
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • My task was changed a little. And I need to implement abs and max also in prolog. I need to take list of integer and tell if abs value of max is greater then abs value of min. – MatejMistik Apr 03 '21 at 19:42
0
maxlist([X],X).
maxlist([X,Y|Rest],AbsMax) :- 
abs(X,AbsX),
abs(Y,AbsY), 
maxlist([AbsY | Rest],AbsMaxRest),
max(AbsX,AbsMaxRest,AbsMax).
max(X,Y,X) :- X>= Y.
max(X,Y,Y) :- X < Y.
abs(X,Y) :- X < 0 -> Y is -X ; Y = X.

This solves whole list of integer