Trying to break elements which are lists in a list? - prolog

I am trying to write a program which make the following:
?- g([2,3, [22,[3],9] ,4,[5],99],X).
X= [2,3,22,[3],9 ,4,5,99]
So it searches for lists in the given list and replace it by their elements without brackets [].
So I wrote this program:
The first block just searches for the first element in the list which is list
If there is no such element it returns [there_is_no_list].
first_list_in_the_list([],[there_is_no_list]):-!.
first_list_in_the_list([H|_],X):-is_list(H),X=H,!.
first_list_in_the_list([_|T],X):-first_list_in_the_list(T,X).
The first block works in prolog perfectly.
The second block just search in the list for an element X and then split the list into a two lists one is the list of all elements before X and the second is the elements after X.
splite_when_find_element([H|T],H,[],T):-!.
splite_when_find_element([H|T],X,F,G):-
splite_when_find_element(T,X,F1,G),append([H],F1,F).
it also works fine in Prolog.
and the third block is append, and it joins two list together in a new list.
append([],L,L).
append([H|T],L,[H|U1]):- append(T,L,U1).
and the last part is:
gg(L,L):-first_list_in_the_list(L,[there_is_no_list]),!.
gg(L,U):-first_list_in_the_list(L,X),
splite_when_find_element(L,X,F,G),gg(G,R),append(F,X,E),
append(E,R,U).
When I give a query [2,[3],5] I get also [2,[3],5] and I really don't understand why it does this.

A simple recursive solution will also work. Recursion is done by the head of the input list. In the non-trivial case, when the head is a list itself, we just append the rest of the flattened list to it. In the code below, it has not flattened Rest yet in append(H, Rest, Out), but it will be, after the recursive call of g(In, Rest). Cut after the append call ensures that backtracking won't consider the last case, where the head will appear in the output as-is.
% Base case, empty list.
g([], []).
% First recursive case: head is list.
% Append remaining elements to it.
g([H|In], Out):-
append(H, Rest, Out), !,
g(In, Rest).
% Second recursive case: head is not list.
% Will appear as-is in the output.
g([H|In], [H|Out]):-
g(In, Out).

also a DCG can do
lev, X --> [X], {is_list(X)}, lev.
lev, [X] --> [X], lev.
lev --> [].
test:
?- phrase(lev,[a,[b,c,[d]],e],L).
L = [a, b, c, [d], e] .

To flatten 1 level of a nested list, try something like this:
flatten1( Xs , Ys ) :- % to flatten a list
flatten1( Xs , [] , Ys ) , % - invoke the worker predicate
. %
flatten1( [] , T , R ) :- % if we get to to the empty list
reverse(T,R) % - just reverse the accumulator and we're done.
. %
flatten1( [X|Xs] , T , R ) :- % if the head of the list is unbound
var(X) , % - check for being a var
! , % - cut (to eliminate problems on backtracking
T1 = [X|T] , % - prepend the head of the list to the accumulator
flatten( Xs , T1 , R ) % - and recurse down
. %
flatten1( [[]|Xs] , T , R ) :- % if head of the list is an empty list, skip it
flatten1( Xs , T , R ) % - ignore it and recurse down
. %
flatten1( [[X|Ns]|Xs] , T , R ) :- % if head of the list is a non-empty list
X1 = [Ns|Xs] , % - prepend the tail of the sublist to the list
T1 = [X|T] , % - prepend the head of the sublist to the accumulator
flatten( X1 , T1 , R ) % - and recurse down
. %
flatten( [X|Xs] , T , R ) :- % if the head of the list is something else (except an unbound variable)
T1 = [X|T] , % - prepend the list head to the accumulator and
flatten( Xs , T1 , R ) % - recurse down
. %

Related

Find substrings of certain length

I'm a beginner at prolog and I'm having trouble getting started with the following problem:
Define the predicate partstr/3, where the first argument is a list, that generates a list A of length L that you find consecutive in the first list.
You should be able to present all answers with backtracking.
E.g.:
?- partstr([1, 2 , 3], L, A).
If L = 2 then A = [1,2] and [2,3],
or if L = 2 then F=[1,2] and [2,3].
and so on...
I feel like you would use recursion to solve it, but I'm not sure where to start. I would really appreciate some tips on how to solve this because I feel like I'm getting nowhere.
The core of this problem is that you need a way to pull all the sublist of length N from a list, correct?
So...
Consider that append/3 can concatenate two lists: append( [a,b,c], [1,2,3], L) returns L as [a,b,c,1,2,3]. But it can also decompose a list into a prefix and a suffix, so
append( Pfx, Sfx, [a,b,c])
will, on backtracking, successively yield:
Pfx
Sfx
[]
[a,b,c]
[a]
[b,c]
[a,b]
[c]
[a,b,c]
[]
...and... length/2 can not only tell you the length of a list, but
can generate lists of a specified length populated with unique,
unbound variables, so length(L,3) returns [V1,V2,V3].
You can combine those to get the behavior you want:
partstr( Xs, N, SL ) :- % To get all the contiguous sublists of length N from Xs...
append(_,Sfx,Xs) , % - repeatedly get all possible suffixes of Xs, and...
length(SL,N) , % - construct an empty, unbound list of the desired length (N), and...
append(SL,_,Sfx) % - pull that prefix off the suffix
. % Easy!
That's one approach. I imagine that this is coursework and that your instructor likely would like you to roll your own solution from scratch.
To do that, we first need a predicate that will yield the source list, and on backtracking remove the head of the list. Something like:
suffix( Xs , Xs ) .
suffix( [_|Xs] , Sfx ) :- suffix(Xs,Sfx).
Then we need a way to grab the 1st n elements from a list, something like this:
take( _ , 0 , [] ) :- ! .
take( [X|Xs] , N , [X|Sfx] ) :- N1 is N-1 , take(Xs,N1,Sfx) .
Given those two...
partstr( Xs, N , SL ) :-
suffix(Xs,Sfx),
take(Sfx,N, SL )
.
You can even dispense with the suffix/2 predicate, thus, rolling its functionality into partstr/3 itself:
partstr( Xs , N , SL ) :- take(Xs,N,SL).
partstr( [_|Xs] , N , SL ) :- partstr(Xs,N,SL).
And that, I think, is the sweet spot: it is hard to beat 4 lines of code —
partstr( Xs , N , SL ) :- take(Xs,N,SL) .
partstr( [_|Xs] , N , SL ) :- partstr(Xs,N,SL) .
take( _ , 0 , [] ) :- ! .
take( [X|Xs] , N , [X|Sfx] ) :- N > 0 , N1 is N-1 , take(Xs,N1,Sfx) .\

In a List of Lists, Append all Lists together into one List

I need to write a predicate partition/2 such that partition(L, P) is satisfied when the concatenation of every List in the List of Lists P is the same as list L. The List of Lists P can contain an arbitrary number of Lists.
Example queries:
? - partition ([1 ,2 ,3] , P ).
P = [[1] , [2] , [3]];
P = [[1] , [2 , 3]];
P = [[1 , 2] , [3]];
P = [[1 , 2 , 3]];
no
? - partition (L , [[1] ,[2] ,[3 ,4 ,5]]).
L = [1 , 2 , 3 , 4 , 5];
no
I tried concatenating the lists in P together then checking to see if it is equal to L. This is what I have so far but it doesn't work. It loops indefinitely for any P that contains more than 1 list.
partition([], []). ;; Partition of empty list is the empty list
partition(L, [L]). ;; Base case where if P contains 1 element (list), L is equal to this list.
partition(L, [X|[Y1|Y2]]) :-
append(X, Y1, XY1),
partition(L, [XY1|Y2]). ;; Append each list in P to the list after it, repeating until one list is created. X is the head of the list, Y1 is the second element, and Y2 is the rest of the list.
Any help is appreciated.
The tricky part of this is to use append/3 in a way that universally terminates.
Let's code list_sublists/2 (a somewhat more declarative name than partition):
list_sublists([],[]).
list_sublists([X|Xs],[[Y|Ys]|Yss]) :-
append([Y|Ys],Xs0,[X|Xs]),
list_sublists(Xs0,Yss).
Consider the goal append([Y|Ys],Xs0,[X|Xs]) in the second clause: it terminates universally when either [Y|Ys] or [X|Xs] (or both) are/is bounded in length.
Now let's run the queries you gave:
?- list_sublists([1,2,3],Pss).
Pss = [[1],[2],[3]] ;
Pss = [[1],[2,3]] ;
Pss = [[1,2],[3]] ;
Pss = [[1,2,3]] ;
false.
?- list_sublists(Ls,[[1],[2],[3,4,5]]).
Ls = [1,2,3,4,5].
I tried to minimally correct your code: it ends up to something very similar (identical, really) to #repeat answer (+1), of course
partition([], []). % Partition of empty list is the empty list
%partition(L, [L]). % Base case where if P contains 1 element (list), L is equal to this list.
% Append each list in P to the list after it, repeating until one list is created. X is the head of the list, Y1 is the second element, and Y2 is the rest of the list.
partition(L, [[X|Xs]|Zs]) :-
append([X|Xs], Ys, L),
partition(Ys, Zs).
I would say the trick it's forcing the first argument of append/3 to have length > 0, accomplished giving it the pattern [X|Xs] instead of simply Xs

Remove the element in list

I want to remove the element in list1 when it is equal to element in list2.
The query and the expected output is:
filter( [[1,2,3],[1]] , [[1]] , X ).
X = [[1, 2, 3]] ;
filter( [[1,2,3],[1],[2,3,4],[2]] , [[1],[2]] , X ).
X = [[1, 2, 3],[2,3,4]] ;
What I have done right now is :
filter(_,[],_).
filter([A|B],[A|D],E):-
filter(B,D,E).
filter([A|B],[C|D],[A|E]):-
A\=C,
filter(B,D,E).
but it seems not right and gives the output like this:
11 ?- filter([[1,2,3],[1]],[[1]],X).
X = [[1, 2, 3]|_G488] ;
Can anyone help? Maybe I was near success.
Your program will not work correctly because you are removing one element from the second list each time. Also your base case (the first clause) should not be an uninstantiated variable (that is what is giving you the |_G488 in your output.
You have to iterate over the first list filtering the elements found in the second list, but not remove the elements of the second list.
For example:
filter([], _, []).
filter([Item|L1], L2, L3):-
(member(Item, L2) -> L4=L3;L3=[Item|L4]),
filter(L1, L2, L4).
The first clase is the base case of the recursion. It states that the output for an empty list would be an empty list.
The second clause checks to see if the first item of the input list is found on the second list. If it is found then it won't be added to the resulting list; otherwise it is added. Then it recursively calls itself with the rest of the input list.
But in no case it removes the elements from the second list.
Well, the lazy way would be to use the build-ins, findall/3 and member/2:
filter( Xs , Ys , Rs ) :-
findall( X , ( member(X,Xs), \+ member(X,Ys) ) , Rs ) .
which says to find all X such that X is a member of the list Xs and Xs is *not* a member of the listYs`.
Assuming your instructor wants you to come up with your own implementation, you probably first want to decompose your problem. You need to do two things:
Iterate over a list, removing items that are found in another list.
Given an item, determine whether it is contained in another list.
Both of these are simple. To determine if an item is contained in a list, you could say something like:
contained_in( X , [X|Ys] ) :- % if we find the item in the list,
! . % - we succeed and eliminate any alternatives.
contained_in( X , [_|Ys] ) :- % otherwise, we discard the head of the list,
contained_in(X,Ys) . % - and keep looking by recursing down.
The actual filtering is pretty simple, too:
filter( [] , _ , [] ) . % once the source list is exhausted, we're done.
filter( [X|Xs] , Ys , [X|R] ) :- % otherwise...
\+ contained_in(X,Ys) , % - if the current list item is not contained in the list of items to be removed,
! , % - cut off alternatives,
filter( Xs , Ys , R ) . % - add the current item to the result list and recurse down.
. %
filter( [_|Xs] , Ys , R ) :- % if the current list item IS contained in the list of items to be removed,
filter(Xs , Ys , R ) % - discard it and recurse down.
. % Easy!
Your filter is just subtract available with many Prolog systems (I've tested with B-Prolog, SWI-Prolog and ECLiPSe):
?- subtract( [[1,2,3],[1]] , [[1]] , X ).
X = [[1, 2, 3]].
?- subtract( [[1,2,3],[1],[2,3,4],[2]] , [[1],[2]] , X ).
X = [[1, 2, 3], [2, 3, 4]].
You can look at the sources of SWI-Prolog or ECLiPSe for implementation details.

Prolog Split list into list of lists

i want to make one list split into list of lists, and skip the 'solid' and separate the list into sublist.
the input and output is below
split_s([A,B,C,solid,D,E,F],X).
X = [[A,B,C],[D,E,F]].
Can anyone help me?
Try something along the following lines. It helps if you decompose your problem. In this case, the heart of the problem is this:
find the longest prefix of a list that doesn't contain the atom solid.
Which you can do like this with a predicate like take_until( List , Separator , Prefix , Remainder ):
take_until( [] , _ , [] , [] ) . % if we hit the end of the source list, we're done.
take_until( [X|Xs] , X , [] , Xs ) . % if we hit the separator, we're done
take_until( [X|Xs] , S , [X|Ps] , Rs ) :- % otherwise...
X \= S , % - when the head of the list is NOT the separator
take_until( Xs , S , Ps , Rs ) % - we take it on to the sublist and keep going.
. %
Once you have that down, the rest is easy:
use the above predicate to extract the first such prefix, then
recurse down on what's left over.
Like this:
split( [] , [] ) . % splitting the empty list results in the empty list.
split( [X|Xs] , [Y|Ys] ) :- % splitting a non-empty list...
take_until( [X|Xs] , solid , Y , R ) , % - get the desired prefix
split(R, , Ys ) % - recurse down on what's left
. % Easy!
The following works for me:
split_s([],[[]]).
split_s([H|T],[[H|XH]|XR]) :- var(H),!,split_s(T,[XH|XR]).
split_s([solid|T],[[]|X]) :- !,split_s(T,X).
split_s([H|T],[[H|XH]|XR]) :- split_s(T,[XH|XR]).
EDIT: moved the cut in the 3rd clause in front of the split.
If you don't want empty lists, then try the following:
split_s([],[]).
split_s([H|T],[[H|XT]|XXT]) :- var(H),!,split_s([[H]|T],[[[H]|XT]|XXT]).
split_s([solid|T],X) :- !,split_s(T,X).
split_s([H],[[H]]) :- !.
split_s([H,M|T],[[H,M|XT]|XXT]) :- var(M),!,split_s([[M]|T],[[[M]|XT]|XXT]).
split_s([H,solid|T],[[H]|XT]) :- !,split_s(T,XT).
split_s([H|T],[[H|XH]|XR]) :- split_s(T,[XH|XR]).

SICStus Prolog Lists

Having trouble understanding how Prolog works. I'm tryig to write a rule that takes three lists of integers as input (representing sets) and puts the integers that belong to both the first and second list in the third list.
Example:
?-inter([10,20,30,40],[10,50,40,60], List3 )
List3 = [10, 40]
So far I have this, that can recognize if a list contains a certain letter:
mymember(X,[X|T]).
mymember(X,[H|T]) :- mymember(X,T).
There's actually an inbuilt library to sort that all out for you, known as ordsets.
inter(X, Y, Z) :-
list_to_ord_set(X, L1),
list_to_ord_set(Y, L2),
ord_intersection(L1, L2, Z).
Using your example input you get the following
| ?- inter([10,20,30,40],[10,50,40,60],X).
X = [10,40] ? ;
no
inter(Xs, Ys, Zs) will be true when each element in Zs also is in Xs and in Ys.
But Zs are unknown, then a more constructive approach is required.
Here it is: iterate on Xs and store in Zs each element that is in Ys.
An example of iteration is mymember/2, you can see that it requires a recursive predicate.
The other idiomatic part of the above statement is store in Zs, Prolog has a peculiar way to do such things, using pattern matching.
inter([X|Xs], Ys, [X|Zs]) :-
mymember(X, Ys), inter(Xs, Ys, Zs).
You will need to complete inter/3 with other 2 clauses: base recursion, i.e. when all Xs elements have been processed, and the case where X is not a member of Ys.
Try something like this, using the builtins member/2 and setof\3:
set_intersection( As , Bs , Xs ) :-
set_of( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
One should note that this will fail if the lists As and Bs have no elements in common. An alternative would be use findall/3 rather than set_of/3. findall/3 will hand back and empty list rather than failure if the goal is not satisfied:
set_intersection( As , Bs , Xs ) :-
findall( X , ( member(X,As) , member(X,Bs) ) , Xs )
.
However findall/3 returns a bag (duplicates are allowed) rather than a set (no duplicates allowed), so if your two source lists aren't sets, you won't get a set out.
member/2 is a builtin predicate that unifies its first argument with an element of the list — the equivalent of
member(X,[X|_).
member(X,[_|Xs) :- member(X,Xs) .
And, finally, as #chac noted in his answer, you can recursively traverse the list.
set_intersection( [] , _ , [] ) . % the intersection of the empty set with anything is the empty set.
set_intersection( [A|As] , Bs , [A|Xs] ) :- % if the list is non-empty,
member(A,Bs) , % - and A is a member of the 2nd set
! , % - we cut off alternatives at this point (deterministic)
set_intersection( As , Bs , Xs ) % - and recurse down on the tail of the list.
.
set_intersection( [_|As] , Bs , Xs ) :- % if the list is non-empty, and A is NOT a embmer of the 2nd set
set_intersection( As , Bs , Xs ) % we just recurse down on the tail of the list.
.
#chac's technique builds the result list as he goes, something like:
[a|X]
[a,b|X]
[a,b,c|X]
The final unification, the special case of the empty list unifies the unbound tail of the list with [] making the list complete, so the final [a,b,c|X] becomes
[a,b,c]
A little prolog magic. An alternative that might be easier to understand is to use a worker predicate with an accumulator:
%
% set_intersection/3: the public interface predicate
%
set_intersection( As , Bs , Xs ) :-
set_intersection( As , Bc , [] , T ) % we seed our accumulator with the empty list here
.
%
% set_intersection/4: the private worker bee predicate
%
set_intersection( [] , _ , T , Xs ) :- % since our accumulator is essentially a stack
reverse(T,Xs) % we need to reverse the accumulator to
. % put things in the expected sequence
set_intersection( [A|As] , Bs , T , Xs ) :-
member( A, Bs ) ,
! ,
T1 = [A|T] ,
set_intersection( As , Bs , T1 , Xs )
.
set_intersection( [_|As] , Bs , T , Xs ) :-
set_intersection( As , Bs , T , Xs )
.

Resources