Comparing the value of a variable prolog - prolog

Is it possible to compare a variable to an atom?
Is it possible to compare the contents of a variable with an atom as shown below?
Y = [[cirlce], nextTo [square]].
nth0(1, Y, Op),Op == nextTo, doSomething(circle, square).

This can easily be tested as below:
Y = [[cirlce], nextTo, [square]],
nth0(1, Y, nextTo), doSomething(circle, square).
Matching "nextTo" with the element found at index 1 by nth0/3 and will yield true

Related

Checking all of facts in prolog

I have a number of facts that represents a cell with a row,Column and the number in that certain cell, And I want to check those facts just like checking a normal array .
I tried this function but it doesn't seem to work ,I don't think I am checking all my facts.
allcolored(X,Y) :-
cell(X,Y,_),
X1 is X - 1,
Y1 is Y - 1,
allcolored(X1,Y1).
If I understand you correctly, you want to check if, given a pair of X/Y coordinates, all positions in the grid spanned by those coordinates are covered by cell/3 facts. For arguments sake, let's consider that the following facts are currently present:
cell(1,1,100).
cell(1,2,200).
cell(1,3,300).
cell(2,1,110).
cell(2,2,120).
cell(2,3,130).
Looking at your attempt for a recursive rule, you try to check if, for a given pair, say 2/2, there are facts cell/3 for the pairs 2/2 and 1/1. But you probably want to check if the following pairs are covered: 2/2, 1/2, 2/1 and 1/1. As you can see in this sequence, the X-coordinate is being reduced to 1, then the Y-coordinate is decreased while the X-coordinate starts over at 2 again. So you need to preserve the original value of X somehow. This can be done with an auxiliary predicate with an additional argument. Your predicate allcolored/2 would then be the calling predicate for such a predicate, let's call it allcolored_/3:
allcolored(X,Y) :-
allcolored_(X,Y,X).
As #lurker already pointed out, your predicate is lacking a base case, where the recursion can stop. An obvious candidate for that would be the pair 1/1:
allcolored_(1,1,_) :-
cell(1,1,_).
Then a rule is needed to describe that all values between X and 2 have to be covered by cell/3:
allcolored_(X,Y,Max) :-
cell(X,Y,_),
X > 1,
Y >= 1,
X0 is X-1,
allcolored_(X0,Y,Max).
And an additional rule to describe the change to the next lower Y-coordinate, once X reached 1:
allcolored_(1,Y,Max) :-
cell(1,Y,_),
Y > 1,
Y0 is Y-1,
allcolored_(Max,Y0,Max).
Now you can test if a grid, spanned by the coordinates you provide, is covered by facts cell/3:
?- allcolored(2,2).
true ;
false.
?- allcolored(2,3).
true ;
false.
?- allcolored(3,3).
false.
Note that the above code assumes that the smallest coordinate in the grid is 1. To change that, to e.g. 0, you have to replace the 1's in the goals X >1, Y >= 1 and Y > 1 by 0's. Also note that due to the ordering of the goals (the cell/3 goals first) you can also ask questions like What grids are there that are covered by the facts of cell/3? :
?- allcolored(X,Y).
X = Y, Y = 1 ;
X = 2,
Y = 1 ;
X = Y, Y = 2 ;
X = 2,
Y = 3 ;
X = 1,
Y = 2 ;
X = 1,
Y = 3 ;
false.
Instead of checking for the existence of a fact for every pair of indices in range, check for the non-existence of non-existence of the fact for some pair of indices in range:
allcolored(X,Y) :-
\+ (between(1,X,A), between(1,Y,B), \+ cell(A,B,_)).
this says: allcolored(X,Y) holds if there are no indices A, B in allowed ranges (1..X, 1..Y) for which the fact cell(A,B) doesn't exist.
In other words, "there are no empty cells in the given area" is the same thing as "all cells in the given area are full".

Prolog internal variable names

I have a large numbers of facts that are already in my file (position(M,P)), M is the name and P is the position of the player , I am asked to do a player_list(L,N), L is the list of players and N is the size of this list. I did it and it works the problem is that it gives the list without the names it gives me numbers and not names
player_list([H|T],N):- L = [H|T],
position(H,P),
\+ member(H,L),
append(L,H),
player_list(T,N).
what I get is:
?- player_list(X,4).
X = [_9176, _9182, _9188, _9194] .
so what should I do ?
You could use an additional list as an argument to keep track of the players you already have. This list is empty at the beginning, so the calling predicate calls the predicate describing the actual relation with [] as an additional argument:
player_list(PLs,L) :-
pl_l_(PLs,L,[]). % <- actual relation
The definition you posted is missing a base case, that is, if you already have the desired amount of players, you can stop adding others. In this case the number of players to add is zero otherwise it is greater than zero. You also have to describe that the head of the list (PL) is a player (whose position you don't care about, so the variable is preceded by an underscore (_P), otherwise the goal is just like in your code) and is not in the accumulator yet (as opposed to your code, where you check if PL is not in L) but in the recursive call it is in the accumulator. You can achieve the latter by having [PL|Acc0] in the recursive goal, so you don't need append/2. Putting all this together, your code might look something like this:
pl_l_([],0,_). % base case
pl_l_([PL|PLs],L1,Acc0) :-
L1 > 0, % number of players yet to add
L0 is L1-1, % new number of players to add
position(PL,_P), % PL is a player and
\+ member(PL,Acc0), % not in the accumulator yet
pl_l_(PLs,L0,[PL|Acc0]). % the relation holds for PLs, L0 and [PL|Acc0] as well
With respect to your comment, I assume that your code contains the following four facts:
position(zlatan,center).
position(rooney,forward).
position(ronaldo,forward).
position(messi,forward).
Then your example query yields the desired results:
?- player_list(X,4).
X = [zlatan,rooney,ronaldo,messi] ? ;
X = [zlatan,rooney,messi,ronaldo] ? ;
...
If you intend to use the predicate the other way around as well, I suggest the use of CLP(FD). To see why, consider the most general query:
?- player_list(X,Y).
X = [],
Y = 0 ? ;
ERROR at clause 2 of user:pl_l_/3 !!
INSTANTIATION ERROR- =:=/2: expected bound value
You get this error because >/2 expects both arguments to be ground. You can modify the predicate pl_l_/3 to use CLP(FD) like so:
:- use_module(library(clpfd)).
pl_l_([],0,_).
pl_l_([PL|PLs],L1,Acc0) :-
L1 #> 0, % <- new
L0 #= L1-1, % <- new
position(PL,_P),
\+ member(PL,Acc0),
pl_l_(PLs,L0,[PL|Acc0]).
With these modifications the predicate is more versatile:
?- player_list([zlatan,messi,ronaldo],Y).
Y = 3
?- player_list(X,Y).
X = [],
Y = 0 ? ;
X = [zlatan],
Y = 1 ? ;
X = [zlatan,rooney],
Y = 2 ?
...

How can I assert facts about all List members in Prolog?

I'd like to assert facts about all members of a List in prolog, and have any resulting unification retained. As an example, I'd like to assert that each list member is equal to five, but none of the below constructs does this:
?- L=[X,Y,Z], forall(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
?- L=[X,Y,Z], foreach(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
I would like a way to pose the query such that X=5,Y=5, and Z=5.
There is a lot of terminology that you might be getting wrong, or I am misunderstanding you.
"Equal to" is not the same as "could unify", or "unify", but it depends how you mean it.
With SWI-Prolog, from the top level:
?- X == 5.
false. % the free variable X is not the integer 5
?- unifiable(X, 5, U).
U = [X=5]. % you could unify X with 5, then X will be 5
?- X = 5.
X = 5. % X unifies with 5 (and is now bound to the integer 5)
The comment by CapelliC already has the answer that you are most likely after: given a list of variables (either free or not), make so that each variable in the list is bound to the integer 5. This is best done by unification (the third query above). The maplist simply applies the unification to each element of the list.
PS. In case you are wondering how to read the maplist(=(5), L):
These three are equivalent:
maplist(=(5), [X,Y,Z])
maplist(=, [5,5,5], [X,Y,Z])
X=5, Y=5, Z=5
And of course X=5 is the same as =(X,5).

Summation of prolog predicates not working

Like the title states, I am trying to return the sum of the returned values from sub predicates but it's not working. Here is my code:
addlistnum([],[],X).
addlistnum(digits(Y,[A|T]),digits(F,[B|T]),X) :-
X is Y + F.
digits(Num, List) :-
digits(0, List, Num).
digits(Num, [], Num).
digits(N, [A|As], Num) :-
N1 is N * 10 + A,
digits(N1, As, Num).
The sub predicate works fine. It converts list to an integer. Now I want to sum the converted values.
Example:
?- digits(X,[3,3,3]).
X = 333. % works as expected
Building on that, addlistnum([3,3,3,3],[2,2,2],X) is supposed to produce X = 3555 (as 3555 is 3333 + 222), but I get false instead.
I also tried:
addlistnum([],[],X).
addlistnum([A|T],[B|T],X) :-
X is Y + F,
digits(Y,[A|T]),
digits(F,[B|T]).
It simply returns false, which gives no information about is wrong.
Problem is at these rules:
addlistnum([],[],X).
addlistnum(digits(Y,[A|T]),digits(F,[B|T]),X) :-
X is Y + F.
Second one is, "addition of two list is the addition of the integer conversion of these list":
addlistnum(A,B,X) :-
digits(NA,A),
digits(NB,B),
X is NA + NB.
first one is not necessary, "digits" for an empty list is zero, thus, this rule also covers "addition of two empty list is zero"

prolog compare SOS

let say i had this two facts.
animal(fifi,10).
animal(fofo,20).
If i call
animal(X,Y).
then Prolog will return me
X = fifi,
Y = 10 ;
X = fofo,
Y = 20.
What I need to do, to let to Prolog only return me the animal X with the highest value of Y according to the fact?
Is there any possible way that it will just display X only for the highest value of Y instead of displaying X and Y together?
Alternatively :
max_animal(MaxAnimal) :-
findall(Y, animal(X, Y), Ys),
max_list(Ys, Max),
animal(MaxAnimal, Max).
Sure, you can build a list of all the animals and their values, then sort the list and take the element you want from it:
max_animal(MaxAnimal):-
findall(Value-Animal, animal(Animal, Value), L),
keysort(L, Sorted),
reverse(Sorted, [_-MaxAnimal|_]).

Resources