1
listelements([i|o],listelements) :-
    u is abs((listmax)-(listmin)),
    listelements(u,listelements).

listmin([min],min).
listmin([x|y],z) :-
    listmin(y,h),
    min(x,h,z).

min(Q,W,Q) :-
    Q =< W.
min(Q,W,W) :-
    W < Q.

listmax([max],max).
listmax([a|b],c) :-
    listmax(b,f),
    max(a,f,c).

max(M,N,M) :-
    M =< N.
max(M,N,N) :-
    N < M.

Arithmetic: `listmax' is not a function

This is the error. Help please!

When I ask ?- listmin([1,2,3,4,5,6],z). it answers false instead of 1. Why?

repeat
  • 18,496
  • 4
  • 54
  • 166
George
  • 11
  • 2
  • Many basic Prolog problems here. When you use `is/2`, it expects the expression on the right to be an evaluable arithmetic expression consisting of known operators or known functions that Prolog understands. `listmax` is not a known function. It's one of your predicates, and predicates don't return values. A predicate succeeds or fails (not to mention you call it with no arguments, but your predicate is defined with 2 arguments). You can, alternatively, do `listmax(MyList, Result)`, then use `Result` in your `is/2` expression. More in my next comment... – lurker Oct 28 '15 at 19:41
  • Another problem is that you aren't consistent in variable syntax. Prolog uses initial capital letter (or underscore) to represent a variable. If the identifier begins with a lower case letter, it's an atom (constant). So, for example, `listmax([max], max).` sees `max` as an atom, not a variable. You need `listmax([Max], Max).`. Likewise with your other predicate definitions. You really should read through a basic Prolog tutorial to get the basics understood before going further your you'll just keep tripping over this stuff. – lurker Oct 28 '15 at 19:43

2 Answers2

1

Considering your concrete choice of arithmetic predicates, I guess you want to support all kinds of Prolog numbers (floating point numbers, integers, and rational numbers).

If you only work with integer numbers here then make sure you are using !

In this answer we proceed step-by-step, like this:

  1. We define an auxiliary predicate num_num_absdiff/3 which computes the absolute difference of its first two arguments.

    num_num_absdiff(X,Y,D) :-
       D is abs(X-Y).
    
  2. To apply num_num_absdiff/3 to all adjacent items and gather the results, we use mapadj/3:

    ?- mapadj(num_num_absdiff,[1,2,4,8,16,100],Ds).
    Ds = [1, 2, 4, 8, 84].
    
  3. The maximum absolute difference is the maximum number in above list.
    We employ list_maxnum/2 to get said number.

    ?- list_maxnum([1,2,4,8,84], Max).
    Max = 84.
    
  4. Let's put it all together and define maxabsdiff_of/2:

    maxabsdiff_of(D,Nums) :-
       mapadj(num_num_absdiff,Nums,Ds),
       list_maxnum(Ds,D).
    
  5. Here are some sample queries:

    ?- maxabsdiff_of(D,[1,2,3,4,5,6]).           % as given by the OP 
    D = 1.                                     
    
    ?- maxabsdiff_of(D,[1,2,3,4,5,6,8]).
    D = 2.
    
    ?- maxabsdiff_of(D,[1,2,3,100,4,5,6,8]).
    D = 97.
    
Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166
1

Of course, you could also use together with foldl/4, like so:

:- use_module(library(lambda)).

maxabsdiff_of(X,[V0,V1|Vs]) :-
   foldl(\E^(E0+D0)^(E+D)^(D is max(D0,abs(E-E0))), Vs, V1+abs(V1-V0),_+X).

Sample queries:

?- maxabsdiff_of(D,[1,2,3,4,5,6]).
D = 1.

?- maxabsdiff_of(D,[1,2,3,4,5,6,8]).
D = 2.

?- maxabsdiff_of(D,[1,2,3,100,4,5,6,8]).
D = 97.

Same results as before!

repeat
  • 18,496
  • 4
  • 54
  • 166