user7589276
user7589276

Reputation:

List with if - plus and minus

I should create a list with integer.It should be ziga_arnitika(L,ML).Which take L list (+) integer and will return the list ML only (-) integer the even numbers of list L. Warning:The X mod Y calculates X:Y.

Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]

i know for example with not list to use if but not with lists,what i did is..:

something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).

Upvotes: 0

Views: 287

Answers (1)

Paulo Moura
Paulo Moura

Reputation: 18683

You want to compute a list with elements satisfying some properties from a given list. Lists in Prolog have a very simple representation. The empty list is represent by []. A non-empty list is a sequence of elements separated by a comma. E.g. [1,2,3]. Prolog also provides handy notation to split a list between its head (or first element) and its tail (a list with the remaining arguments):

?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].

Walking a list (from its first element to its last element) can be done easily using a simple recursive predicate. The trivial case is when a list is empty:

walk([]).

If a list is not empty, we move to the list tail:

walk([Head| Tail]) :- walk(Tail).

However, if you try this predicate definition in virtually any Prolog system, it will warn you that Head is a singleton variable. That means that the variable appears once in a predicate clause. You can solve the warning by replacing the variable Head with an anonymous variable (which we can interpret as "don't care" variable). Thus, currently we have:

walk([]).
walk([_| Tail]) :- walk(Tail).

We can try it with our example list:

?- walk([1,2,3]).
true.

Prolog being a relational language, what happens if we call the walk/1 predicate with a variable instead?

?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...

Now back to the original problem: constructing a list from elements of other list. We want to process each element of the input list and, if it satisfies some property, adding it to the output list. We need two arguments. The simple case (or base case) is again when the input list is empty:

process([], []).

The general case (or recursive case) will be:

process([Head| Tail], [Head| Tail2]) :-
    property(Head),
    process(Tail, Tail2).

assuming a predicate property/1 that is true when its argument satisfies some property. In your case, being a even, negative integer. But not all elements will satisfy the property. To handle that case, we need a third clause that will skip an element that doesn't satisfy the property:

 process([Head| Tail], List) :-
    \+ property(Head),
    process(Tail, List).

The \+/1 predicate is Prolog standard negation predicate: it's true when its argument is false.

Let's try our process/2 predicate it by defining a property/1 predicate that is true if the argument is the integer zero:

property(0).

A sample call would then be:

?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false

We have successfully written a predicate that extracts all the zeros from a list. Note that our query have a single solution. If we type a ; to ask for the next solution at the prompt, the Prolog top-level interpreter will tell us that there are no more solutions (the exact printout depends on the chosen Prolog system; some will print e.g. no instead of falsebut the meaning is the same).

Can you now solve your original question by defining a suitable property/1 predicate?

Update

You can combine the two recursive clauses in one by writing for example:

process([Head| Tail], List) :-
    (   % condition
        property(Head) ->
        % then
        List = [Head| Tail2],
        process(Tail, Tail2)
    ;   % else
        process(Tail, List)
    ).

In this case, we use the Prolog standard if-then-else control construct. Note, however, that this construct does an implicit cut in the condition. I.e. we only take the first solution for the property/1 predicate and discard any other potential solutions. The use of this control construct also prevents using the process/2 predicate in reverse (e.g. calling it with an unbound first argument and a bound second argument) or using it to generate pairs of terms that satisfy the relation (e.g. calling it with both arguments unbound). These issues may or may not be significant depending on the property that you're using to filter the list and on the details of the practical problem that you're solving. More sophisticated alternatives are possible but out of scope for this introductory answer.

Upvotes: 1

Related Questions