1
votes

I have this

initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]).

I would like to find which sublist inside the list is the same with the number 1. And after delete the sublist who had the number one.

It would be something like that :

?- initialstate(_,_,[X,_]), initialstate(_,_,list),
 delete(list,X,Newlist),assertz(initialstate(A,B,Newlist)).

I know this is wrong but i am trying to explain you what i want to do.

I want my final list to be :

initialstate(0,[],[[2,3],[2,3]]).
2
Try breaking it down in steps. First, define the main predicate which reads initialstate and instantiates a variable L with the list you want to process (which is [[1,0], ...]). Then define another predicate which will go through a list and omit those members that have a 1. Note, you left open some questions, such as are you only looking for 1 in the fist position? Are there always only two positions in the inner lists? Do you only care about the list that is the 3rd parameter of initialstate? Etc.lurker
I looking only in first position of all sublists which have the number X at first position. Number X it will be given for me.NickName

2 Answers

1
votes

I think you've chosen the right builtin (delete/3), but there is some detail wrong. Here is a working 'query':

?- retract(initialstate(A,B,C)), C=[[X,_]|_], delete(C,[X,_],Newlist), assertz(initialstate(A,B,Newlist)).
A = 0,
B = [],
C = [[1, 0], [2, 3], [1, 2], [2, 3]],
X = 1,
Newlist = [[2, 3], [2, 3]].

First of all: if you do a assertz without first doing a retract you'll end with having an almost duplicate of your data, and probably is not what you want. assertz stores the updated initialstate after the old one (there is asserta, but I doubt will correct the bug).

Second, note how to use pattern matching to extract the essential information:

C=[[X,_]|_]

the use of _ (i.e. an anonymous var) is essential, because allows to specify which part of the complex structure we must ignore when using it. And we must use it also to indicate to delete/3 what to match.

delete(C,[X,_],Newlist)
1
votes

Edit: A new answer to incorporate CapelliC's endorsement of delete/3 and OPs further queries in the comments.

Predicate:

initial_state_without_elements(initialstate(A,B,List), Element,
                               initialstate(A,B,FilteredList) ):-
    delete(List, Element, FilteredList).

Query:

?- initial_state_without_elements(initialstate(0,[],[[1,0],[2,3],[1,2],[2,3]]), [2,_], NewState).
NewState = initialstate(0, [], [[1, 0], [1, 2]]).

We want to take some list of lists, ListOfLists, and remove all the sublists, Ls, that contain a given Element. In general, to check if an element X is in some list List, we we can use member(X, List). So we want a list of lists, SubListsWithout, which contains all Ls of ListOfLists for which member(Element, SubList) is false.

Here is a predicate sublists_without_elements/3, which takes a list of lists, an element, and a variable as arguments, and unifies the variable with a list of the sublists of the first which do not contain the element. This predicate uses the standard recursive technique for describing lists:

sublists_without_element([], _, []).
sublists_without_element([L|Ls], Element, SubListsWithout) :-
    member(Element, L), !, 
    sublists_without_element(Ls, Element, SubListsWithout).
sublists_without_element([L|Ls], Element, [L|SubListsWithout]) :-
    sublists_without_element(Ls, Element, SubListsWithout).

The first clause is our base case: the empty list has no sublists, regardless of the element.

The second clause is true if (1) Element is a member of L, and (2) SubListsWithout is a list of the sublists of Ls which do not contain Element. (note: *L has not been added to SubListsWithout in this clause, which means it has been excluded from the lits we are accumulating. The ! is used to prune the search path here, because once we know that an Element is a member of L, we don't want to have anything to do with L again.)

The third clause is true if L is added to SubListsWithout, and SubListsWithout contains the rest of the sublists of Ls which do not have Element as a member.

The above is one way to write your own predicate to filter a list. It is important that you be able to write and read predicates of this form, because you will see tons of them. However, you'll also want to get to know the standard libraries of your Prolog implementation. In SWI-Prolg, you can simply use exclude\3 to accomplish the above task. Thus, you could achieve your desired goal in with the following:

filter_initial_state(initial_state(A,B,List),
                     Element,
                     initial_state(A,B,FilteredList)) :-

    exclude(member(Element), List, FilteredList).

You can use it thus,

?- filter_initial_state(initial_state(0,[],[[1,0],[2,3],[1,2],[2,3]]), 1, Filtered).

and prolog will reply,

Filtered = initial_state(0, [], [[2, 3], [2, 3]]).