Internal Prolog Variable Names

I have a large number of facts already in my file (position(M,P))

, M is the name and P is the position of the player I am asked to do player_list(L,N)

, L is the list of players and N is the size of that list. I did this and it works, the problem is that it gives a list with no names it gives me numbers, 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:

?- player_list(X,4).
  X = [_9176, _9182, _9188, _9194] .

      

so what should I do?

+3


source to share


1 answer


You can 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 invocation predicate invokes a predicate describing the actual relation with []

as an additional argument:

player_list(PLs,L) :-
   pl_l_(PLs,L,[]).            % <- actual relation

      

The definition you provided is missing the base code, meaning if you already have the required number 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 must also indicate that the head of the list ( PL

) is the player (whose position you don't need, so the variable is preceded by an underscore ( _P

), otherwise the target will be the same as in your code) and is not yet in the accumulator (unlike yours the code where you are checking for PL

c L

), but in the recursive call it is in the accumulator. You can achieve the latter by having [PL|Acc0]

a recursive target, so you don't need to append/2

. Putting it all 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

      

As for your comment, I assume your code contains the following four facts:

position(zlatan,center).
position(rooney,forward).
position(ronaldo,forward).
position(messi,forward).

      

Then your example query gives the desired results:



   ?- player_list(X,4).
X = [zlatan,rooney,ronaldo,messi] ? ;
X = [zlatan,rooney,messi,ronaldo] ? ;
...

      

If you intend to use the predicate in a different way, I suggest using the CLP (FD). To understand why, consider the most common query:

   ?- player_list(X,Y).
X = [],
Y = 0 ? ;
     ERROR at  clause 2 of user:pl_l_/3 !!
     INSTANTIATION ERROR- =:=/2: expected bound value

      

You are getting this error because you >/2

expect both arguments to be grounded. You can change the predicate pl_l_/3

to use CLP (FD) as follows:

:- 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 changes, 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 ?
...

      

+4


source







All Articles