Generating a list in prolog - prolog

Hello I want to make a program in Prolog, that given a list of numbers and a number, it appends all the concurences of position of the number in a second list.
For example for the list (5,10,4,5,6,5) and number =5 the new list should be
(1,4,6)
here is my code so far
positions(X, [X|_],1).
positions(X, [P|T], N) :- positions(X, T, N1), N is N1+1.
find(X, [H|T] ,Z) :-positions(X,[H|T],N) , append([],N,Z).
the positions returns the first concurrence of X in the list, but I don't know how to proceed. Can you help me?

If it's not an assignment, then you can benefit from using the built-ins findall/3 and nth1/3:
?- findall(Nth, nth1(Nth, [5,10,4,5,6,5], 5), Nths).
Nths = [1, 4, 6].
Taking just the nth1 phrase, and running that, you can see it is backtracking and finding multiple solutions, then we just use findall to collect them into a list.
?- nth1(Nth, [5,10,4,5,6,5], 5).
Nth = 1 ;
Nth = 4 ;
Nth = 6.
nth1/3, when using a variable for the first parameter, is saying 'give me a list index where where the 3rd parameter is found in the list of the second parameter.

You have some good ideas, but I would suggest a couple things:
1) In Prolog, it can be beneficial to give variables meaningful names
2) Use an accumulator and you will only need positions and append
3)Use a different base case
positions([Num|List],Num,[Index|SubResult],Index) :- Index2 is Index+1,
positions(List,Num,SubResult,Index2).
positions([NotNum|List],Num,Result,Index) :- NotNum \= Num,
Index2 is Index+1,
positions(List,Num,Result,Index2).
positions([],Num,[],Index).
In our first general case, we can see the numbers match, so we go find how many results are in our sublist, which we will call the SubResult and then push the current index on to our SubResult
The next general case, the numbers do not unify, and our Result IS the SubResult, so let's call them the same thing.
In our final case (the base case) we can see the list is empty, in this case we return an empty list as we cannot match against an empty list.
You can see that the above rules are order-independent, which is something very valuable in Prolog. This means you can arrange the rules in any order, and the semantics of your Prolog program remain unchanged. Using unification to achieve this will prevent future pain in debugging.
We can wrap our predicate in the following way
positions(Num, List, Positions) :- positions(List, Num, Positions, 1).
This will allow for queries of positions(5,[5,10,4,5,6,5],Positions).

Related

Repeat and Double elements in lists in Prolog

how can I write two predicates that are described below.
1) Define the double(X,Y) predicate, which is true if the list Y contains each of the elements X
repeated twice. Example: double([a,b],[a,a,b,b]) is true.
2) Define the predicate repeat(X,Y,N), which is true if the list Y contains each of the elements X
repeated N times. For example, for the question repeat([a,b],[a,a,a,b,b,b],3), Prolog answers true.
Could you give me the example of those predicates?
If you have repeat/3 you have double/2.
and thus:
multiple(X,N,R) :-
length(R,N),maplist(=(X),R).
repeat(Li,Lo,N) :-
maplist({N}/[Xi,Xo]>>multiple(Xi,N,Xo),Li,Nested),flatten(Nested,Lo).
But it doesn't run backwards due to the flatten/2 I think. Can that be improved?
double([], []).
double([X|Y], [X,X|Z]) :- double(Y,Z).
remove_if_same(_,R,0,R):- !.
remove_if_same(X,[X|Y],N,R) :- Nm1 is N-1,remove_if_same(X,Y,Nm1,R).
repeat([],[],_).
repeat([X|Xr],Y,N) :- remove_if_same(X,Y,N,R), repeat(Xr,R,N).
How double works?
If you've got two empty lists, then that is true, there is nothing to double from the first argument.
Otherwise, you're taking the head from the first list, and 2 head elements from the second list. If all these are the same (so if all are X) you're checking with recursion rest of elements, so accordingly Y and Z. So you'll check once again if lists are empty and so on, and if on any of the steps sth is not possible you return false.
About the repeat predicate, it's quite similar in reasoning.
2 things that I should explain:
The ! mark will make that the command-line interface(like swipl) will not search for other results of the remove_if_same. It would work same if we pass it to the repeat.
remove_if_same statement uses the accumulator (the 4th argument) to return at the end of the search the list without N same elements.

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]).
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.

Why am I getting Type error: `[]' expected, found `[21,3,4,5,6,7,8]' (a list) ("x" must hold one character) with maplist/3 prolog?

I am new to Prolog. I want a predicate that takes a list, process it with maplist/3 creating a corresponding list with zeros in place of numbers less than mean and 1 for number above the mean. I then want a second predicate to sum the 1's to find out how many numbers are above the mean. This second predicate then returns this number which corresponds to total numbers above the mean.
I know the code below works fine:
numAtOrAboveMean(Mean, Num, Val) :- Num > Mean -> Val is 1; Val is 0.
maplist(numAtOrAboveMean(Mean), [], List), sumlist(List, Below).
When I modified it to this, I get a type erros that expected [] but found a list. The comments correspond to how I think the predicate behavior is.
nGMean(Mean, Num, Val) :- Num > Mean -> Val is 1; Val is 0.%sorts list
nGMean([], _ , []). %takes a list, a constant, relates to a list
nGMean(L, Mean, List) : - maplist(nGMean(Mean), L, List). %maplist call sort
Then to sum I will use a second predicate. Something like this:
sumtotal(L,V) :- mean(L, M), M2 is M, nGMean(L, M2, List), sum(List, V).
Which is not working probably mostly because nGMean is throwing an error. nGMean full error is shown below:
So my question is, why am I getting that type error on the nGMean predicate?
Edit -As requested in comments below is the entire thing. As I explained that is the only part because I am testing it separately.
Thank you for answers. Next time I will post complete code.Or make clear that I just want to trouble shoot one predicate.
Maplist for numAtOrAboveMean
Full Pic of code on Editor
You should post complete code that can just be copied and run. In what you have posted, mean/2 and sum/2 are not defined.
(Addition:) the reason for the error seems to be that you are comparing a value and a list (2<[2,3|...]). The reason this happens is because your first clause for nGMean/3 has Mean as first parameter, whereas the other clauses has the list, i.e. the list becomes Mean which is used in the comparison (Num > Mean). I'm not sure how > becomes <.
Also, calling maplist/3 on an empty list does not make sense.
A recursive predicate should have two clauses. A recursive clause that (typically) does something with the head of the list and then calls recursively on the tail, and a base case (empty list).
nGMean([Num|Nums],Mean,[Val|List]) :-
( Num > Mean ->
Val = 1
; Val = 0 ),
nGMean(Nums,Mean,List).
nGMean([],_,[]).
With this definition I get the same output as your first two lines above, so I believe this is what you wanted.
(Earlier addition: you only need to use is when the right-hand side contains mathematical calculations. To just set a value, = is fine.)

Prolog - Comparing Lists that have the same element on the same index

I've been working on Prolog for a few weeks right now. I am now trying to write a function in it called matching:
Write a predicate called matching with three parameters, all lists.
The third list must contain the index of the positions in which
the first two lists contain the same value.
If I run
matching([10,71,83,9,24,5,2],[8,71,26,9],Positions).
The results are:
?- matching([10,71,83,9,24,5,2],[8,71,26,9],Positions).
Positions = [] ;
Positions = [] ;
Positions = [_2420] ;
Positions = [_2420] ;
Positions = [_2420, _2432];...
The correct answer would be that Positions is bound to [1,3]. I have no idea what is wrong with my code. Any hint is appreciated.
A hint? Each of your matchingHelper clauses contains a mistake!
OK, a little more than a hint:
Base cases
Prolog should be giving you a warning about singleton variables here. ListofIndex is a variable, but it is only used in one place. Essentially this means that there is absolutely no constraint on this, and thus can be anything.
The correct thing would be that if either of the input lists is empty, the output is also empty.
matchingHelper([], _, , []).
matchingHelper(, [], _, []).
Equal case
This one you almost have correct, but the way you deal with ListOfIndex is backwards. You construct a NewListOfIndex based on the predicate arguments, and use that in the recursive call. The problem is that the ListOfIndex is actually the output! So you should instead construct the ListOfIndex based on the output from the recursive call.
matchingHelper([X|Xs], [X|Ys], Index, [Index|ListofIndex]) :-
Index2 is Index + 1,
matchingHelper(Xs, Ys, Index2, ListofIndex).
Unequal case
Just 2 little issues with this one. First is that this clause should only apply if X and Y are different. Just using a different variable name does not enforce this. Because there is a previous clause which handles the equal case, the first result prolog finds would be correct, but it will continue to find other, incorrect solutions because of this.
The second issue is that you don't increment the index. If you ignore the first element, the current index has to be incremented to reflect the current position.
matchingHelper([X|Xs], [Y|Ys], Index, ListofIndex) :-
X \= Y,
Index2 is Index + 1,
matchingHelper(Xs, Ys, Index2, ListofIndex).
Here's a sample run:
?- matching([10,71,83,9,24,5,2],[8,71,26,9],Positions).
Positions = [1, 3]
false

Getting unbound list tail in Prolog

I'm trying to write a predicate that will take a list, a number, and a variable that will then give the first N elements of the list to the variable. I'm able to do this, but while trying to make it more flexible so that it will stop when it reaches the end of the list or when N is 0, I started getting a garbage variable returned at the end of my list.
Here is my code:
take(_,0,_) :- !.
take([],_,_) :- !.
take([Head|Tail], Number, [Head|Result]) :-
Number > 0,
N1 is Number - 1,
take(Tail, N1, Result).
and when I try to use take([1,3,5,7], 3, L1), I get L1 = [1, 3, 5|_G2028].
I think it has something to do with how I didn't define Result as an empty list, but I don't know how to do so, while keeping the functionality of the predicate.
Change the first 2 rules to:
take(_,0,[]) :- !.
take([],_,[]) :- !.
From your code I can see that take is a predicate that returns true when the 3rd argument is the result of taking the leading elements from the list in the first argument as many as possible but less than the number specified 2nd argument.
So you can constraint the output when 2nd argument is 0 to [], since you have reached the limit.
And you can constraint the output when the 1st argument is an empty list to [], since you can't take anything anyway.
Without the constraints above, it means that anything is valid when the maximum number of elements to take is 0 or when the original list is empty.
Alternatively, you can write everything in one rule:
take(In, Num, Out) :- append(Out, _, In),
length(Out, OutLen), length(In, InLen),
OutLen is min(Num, InLen), !.
The length of the output list is the minimum between the length of original list and Num, that is used as constraint to the append to take out exactly the appropriate number of elements from the original list.
While the existing answer tells you how to fix it, I'd like to try to explain what that "garbage variable" is.
I get L1 = [1, 3, 5|_G2028].
That variable in your list, _G2028, is an uninstantiated variable. The interpreter knows that something is there, but doesn't know what the something is.
This is happening because of the first two clauses,
take(_,0,_) :- !.
take([],_,_) :- !.
The first one says, paraphrased, if you take 0 items from anything, you can get anything.
The second one says, if you take any number of items from an empty list, you can get anything.
So the interpreter gets to one of these, because it wanted to evaluate take(Tail, N1, Result). At that point, Tail is known, N1 is known, but Result is yet unknown. After calling either of these clauses, the interpreter is none the wiser, since neither tells it what Result is. But the goal succeeded, so it reports back and tells you that L1 = [1, 3, 5|_G2028].

Resources