dividing a list up to a point in prolog - prolog

my_list([this,is,a,dog,.,are,tigers,wild,animals,?,the,boy,eats,mango,.]).
suppose this is a list in prolog which i want to divide in three parts that is up to three full stops and store them in variables.
how can i do that...
counthowmany(_, [], 0) :- !.
counthowmany(X, [X|Q], N) :- !, counthowmany(X, Q, N1), N is N1+1.
counthowmany(X, [_|Q], N) :- counthowmany(X, Q, N).
number_of_sentence(N) :- my_list(L),counthowmany(.,L,N).
i already counted the number of full stops in the list(my_list) now i want to divide the list up to first full stop and store it in a variable and then divide up to second full stop and store in a variable and so on.........

UPDATE: the code slightly simplified after #CapelliC comment.
One of the many ways to do it (another, better way - is to use DCG - definite clause grammar):
You don't really need counthowmany.
split([], []).
split(List, [Part | OtherParts]) :-
append(Part, ['.' | Rest], List),
split(Rest, OtherParts).
Let's try it:
?- my_list(List), split(List, Parts).
List = [this, is, a, dog, '.', tigers, are, wild, animals|...],
Parts = [[this, is, a, dog], [tigers, are, wild, animals], [the, boy, eats, mango]]

Your problem statement did not specify what a sequence without a dot should correspond to. I assume that this would be an invalid sentence - thus failure.
:- use_module(library(lambda)).
list_splitted(Xs, Xss) :-
phrase(sentences(Xss), Xs).
sentences([]) --> [].
sentences([Xs|Xss]) -->
sentence(Xs),
sentences(Xss).
sentence(Xs) -->
% {Xs = [_|_]}, % add this, should empty sentences not be allowed
allseq(dif('.'),Xs),
['.'].
% sentence(Xs) -->
% allseq(\X^maplist(dif(X),['.',?]), Xs),
% (['.']|[?]).
allseq(_P_1, []) --> [].
allseq( P_1, [C|Cs]) -->
[C],
{call(P_1,C)},
allseq(P_1, Cs).

In this answer we define split_/2 based on splitlistIf/3 and list_memberd_t/3:
split_(Xs, Yss) :-
splitlistIf(list_memberd_t(['?','.','!']), Xs, Yss).
Sample queries:
?- _Xs = [this,is,a,dog,'.', are,tigers,wild,animals,?, the,boy,eats,mango,'.'],
split_(_Xs, Yss).
Yss = [ [this,is,a,dog] ,[are,tigers,wild,animals] ,[the,boy,eats,mango] ].
?- split_([a,'.',b,'.'], Yss).
Yss = [[a],[b]]. % succeeds deterministically

Related

I cant understand how the function subset(X,Y) works

Can somebody to explain me this code? I try for hours to understand but i can't understand this...
subset([],[]).
subset([X|L],[X|S]) :- subset(L,S).
subset(L, [_|S]) :- subset(L,S).
Imagine that you have a list [1,4], then there are four possible solutions: [1,4], [1], [4], and [], so if you call subset(L, [1,4]), we get:
?- subset(L, [1,4]).
L = [1, 4] ;
L = [1] ;
L = [4] ;
L = [].
The Prolog predicate returns for an empty list an empty list, which is indeed the only sublist we can generate:
sublist([], []).
for a sublist with at least one element X there are each time two possibilities: include X in the result, or do not include X in the result. In both cases we recurse on the tail of the list. The tail thus contains the remaining elements, and for each of these elements, there is again a decision point whether to include these elements or not.
In pseudo-code, an evaluation tree could thus look like:
subset(L, [1,4]) :-
subset([1|L], [1|S]) :-
subset([4|L], [1|S]) :-
subset([], []). % outer L=[1,4]
subset(L, [1|S]) :-
subset([], []). % outer L=[1]
subset(L, [1|S]) :-
subset([4|L], [1|S]) :-
subset([], []). % outer L=[4]
subset(L, [1|S]) :-
subset([], []). % outer L=[]
We can re-write it (nearly) equivalently to push the unifications out of the rules' headers, to make the code's structure more visually apparent:
subset(A,B) :- B=[], A=[].
subset(A,B) :- B=[X | S],
A=[X | L],
subset(L, S).
subset(A,B) :- B=[_ | S],
A= L,
subset(L, S).
So A is a subset of B, if
B=[] and A=[], or
A contains the first element of B, etc. or
A does not contain the first element of B, etc.
That is all.

Prolog: Swapping two halves of a list

I am writing a predicate in prolog that will break a list with an even number of variables into two halves and swap them. For example [a,b,c,d] --> [c,d,a,b].
append([], List, List).
append([Head|Tail], List, [Head|Rest]) :-
append(Tail, List, Rest).
divide(L, X, Y) :-
append(X, Y, L),
length(X, N),
length(Y, N).
swap([], []).
swap([A], D) :-
divide(A, B, C),
append(C, B, D).
I would expect this to work by dividing [A] into two smaller equal sized lists, then appending them together in the reverse order, and then assigning the variable "D" to the list.
What I am getting is "false", why does this not work?
I'm very new to prolog so this might be a silly/simple question, thanks!
Your question is why swap([a,b,c,d],[c,d,a,b]) fails. And here is the actual reason:
?- swap([_/*a*/,_/*b*/|_/*,c,d*/],_/*[c,d,a,b]*/).
:- op(950, fy, *).
*(_).
swap([], _/*[]*/).
swap([A], D) :-
* divide(A, B, C),
* append(C, B, D).
So, not only does your original query fail, but even this generalization fails as well. Even if you ask
?- swap([_,_|_],_).
false.
you just get failure. See it?
And you can ask it also the other way round. With above generalization, we can ask:
?- swap(Xs, Ys).
Xs = []
; Xs = [_A].
So your first argument must be the empty list or a one-element list only. You certainly want to describe also longer lists.
Maybe this helps
:- use_module(library(lists), []).
divide(L, X, Y) :-
append(X, Y, L),
length(X, N),
length(Y, N).
swap([], []).
swap(L, D) :-
divide(L, B, C),
append(C, B, D).

How to check if a list is a non-empty sublist of another list in Prolog

I am trying to create an included_list(X,Y) term that checks if X is a non-empty sublist of Y.
I already use this for checking if the elements exist on the Y list
check_x(X,[X|Tail]).
check_x(X,[Head|Tail]):- check_x(X,Tail).
And the append term
append([], L, L).
append([X | L1], L2, [X | L3]) :- append(L1, L2, L3).
to create a list, in order for the program to finish on
included_list([HeadX|TailX],[HeadX|TailX]).
but I am having problems handling the new empty list that I am trying to create through "append" (I want to create an empty list to add elements that are confirmed to exist on both lists.)
I have found this
sublist1( [], _ ).
sublist1( [X|XS], [X|XSS] ) :- sublist1( XS, XSS ).
sublist1( [X|XS], [_|XSS] ) :- sublist1( [X|XS], XSS ).
but it turns true on sublist([],[1,2,3,4)
Since you're looking for a non-contiguous sublist or ordered subset, and not wanting to include the empty list, then:
sub_list([X], [X|_]).
sub_list([X], [Y|T]) :-
X \== Y,
sub_list([X], T).
sub_list([X,Y|T1], [X|T2]) :-
sub_list([Y|T1], T2).
sub_list([X,Y|T1], [Z|T2]) :-
X \== Z,
sub_list([X,Y|T1], T2).
Some results:
| ?- sub_list([1,4], [1,2,3,4]).
true ? a
no
| ?- sub_list(X, [1,2,3]).
X = [1] ? a
X = [2]
X = [3]
X = [1,2]
X = [1,3]
X = [1,2,3]
X = [2,3]
(2 ms) no
| ?- sub_list([1,X], [1,2,3,4]).
X = 2 ? a
X = 3
X = 4
(2 ms) no
Note that it doesn't just tell you if one list is a sublist of another, but it answers more general questions of, for example, What are the sublists of L? When cuts are used in predicates, it can remove possible valid solutions in that case. So this solution avoids the use of cut for this reason.
Explanation:
The idea is to generate a set of rules which define what a sublist is and try to do so without being procedural or imperative. The above clauses can be interpreted as:
[X] is a sublist of the list [X|_]
[X] is a sublist of the list [Y|T] if X and Y are different and [X] is a sublist of the list T. The condition of X and Y different prevents this rule from overlapping with rule #1 and greatly reduces the number of inferences required to execute the query by avoiding unnecessary recursions.
[X,Y|T1] is a sublist of [X|T2] if [Y|T1] is a sublist of T2. The form [X,Y|T1] ensures that the list has at least two elements so as not to overlap with rule #1 (which can result in any single solution being repeated more than once).
[X,Y|T1] is a sublist of [Z|T2] if X and Z are different and [X,Y|T1] is a sublist of T2. The form [X,Y|T1] ensures that the list has at least two elements so as not to overlap with rule #2, and the condition of X and Z different prevents this rule from overlapping with rule #3 (which can result in any single solution being repeated more than once) and greatly reduces the number of inferences required to execute the query by avoiding unnecessary recursions.
Here is what you an do:
mysublist(L,L1):- sublist(L,L1), notnull(L).
notnull(X):-X\=[].
sublist( [], _ ).
sublist( [X|XS], [X|XSS] ) :- sublist( XS, XSS ).
sublist( [X|XS], [_|XSS] ) :- sublist( [X|XS], XSS ).
Taking a reference from this:
Prolog - first list is sublist of second list?
I just added the condition to check if it was empty beforehand.
Hope this helps.
If order matters. Example [1,2,3] is sublist of [1,2,3,4] but [1,3,2] not.
You can do something like this.
sublist([],L).
sublist([X|L1],[X|L2]):- sublist(L1,L2)
I would use append :
sublist(X, []) :-
is_list(X).
sublist(L, [X | Rest]) :-
append(_, [X|T], L),
sublist(T, Rest).
Basically we can check if M is a sublist of L if M exists in L by appending something on its back and/or its front.
append([], Y, Y).
append([X|XS],YS,[X|Res]) :- append(XS, YS, Res).
sublist(_, []).
sublist(L, M) :- append(R, _, L), append(_, M, R).

Select N elements from a List in Prolog

I'm trying to write a Prolog predicate (SWI) that would select N elements from a List, like this:
selectn(+N, ?Elems, ?List1, ?List2) is true when List1, with all Elems removed, results in List2.
selectn(N,Lps,L1s,[]) :- length(L1s,L), N >= L, permutation(L1s,Lps).
selectn(0,[],L1s,Lps) :- permutation(L1s,Lps).
selectn(N,[E|Es],L1s,L2s) :-
select(E,L1s,L0s),
N0 is N-1,
selectn(N0,Es,L0s,L2s).
My problem is that in some cases, I get duplicated results and I don't know how to avoid them:
?- findall(L,selectn(2,Es,[a,b,c],L),Ls),length(Ls,Solutions).
Ls = [[c], [b], [c], [a], [b], [a]],
Solutions = 6.
This is no homework, but if you want to help me as if it was, I'll be pleased as well.
this could answer your question (albeit I don't understand your first clause selectn/4, permutation is already done by 'nested' select/3)
selectn(0, [], Rest, Rest).
selectn(N, [A|B], C, Rest) :-
append(H, [A|T], C),
M is N-1,
selectn(M, B, T, S),
append(H, S, Rest).
yields
?- findall(L,selectn(2,Es,[a,b,c],L),Ls),length(Ls,Solutions).
Ls = [[c], [b], [a]],
Solutions = 3.

Prolog: Matching One or More Anonymous Variables

[_, [ X , _ ],_] will match a list like [d, [X,a], s]. Is there a way to match it to any pattern where there is one or more anonymous variables? ie. [[X,a],s] and [[d,a],[p,z], [X,b]] would match?
I am trying to write a program to count the elements in a list ie. [a,a,a,b,a,b] => [[a,4],[b,2]] but I am stuck:
listcount(L, N) :- listcountA(LS, [], N).
listcountA([X|Tail], [? [X, B], ?], N) :- B is B+1, listcountA(Tail, [? [X,B] ?], N).
listcountA([X|Tail], AL, N) :- listcountA(Tail, [[X,0]|AL], N).
Thanks.
A variable match a term, and the anonimus variable is not exception. A list is just syntax sugar for a binary relation, between head and tail. So a variable can match the list, the head, or the tail, but not an unspecified sequence.
Some note I hope will help you:
listcount(L, N) :- listcountA(LS, [], N).
In Prolog, predicates are identified by name and num.of.arguments, so called functor and arity. So usually 'service' predicates with added arguments keep the same name.
listcountA([X|Tail], [? [X, B], ?], N) :- B is B+1, listcountA(Tail, [? [X,B] ?], N).
B is B+1 will never succeed, you must use a new variable. And there is no way to match inside a list, using a 'wildcard', as you seem to do. Instead write a predicate to find and update the counter.
A final note: usually pairs of elements are denoted using a binary relation, conveniently some (arbitrary) operator. For instance, most used is the dash.
So I would write
listcount(L, Counters) :-
listcount(L, [], Counters).
listcount([X | Tail], Counted, Counters) :-
update(X, Counted, Updated),
!, listcount(Tail, Updated, Counters).
listcount([], Counters, Counters).
update(X, [X - C | R], [X - S | R]) :-
S is C + 1.
update(X, [H | T], [H | R]) :-
update(X, T, R).
update(X, [], [X - 1]). % X just inserted
update/3 can be simplified using some library predicate, 'moving inside' the recursion. For instance, using select/3:
listcount([X | Tail], Counted, Counters) :-
( select(X - C, Counted, Without)
-> S is C + 1
; S = 1, Without = Counted
),
listcount(Tail, [X - S | Without], Counters).
listcount([], Counters, Counters).
I'll preface this post by saying that if you like this answer, consider awarding the correct answer to #chac as this answer is based on theirs.
Here is a version which also uses an accumulator and handles variables in the input list, giving you the output term structure you asked for directly:
listcount(L, C) :-
listcount(L, [], C).
listcount([], PL, PL).
listcount([X|Xs], Acc, L) :-
select([X0,C], Acc, RAcc),
X == X0, !,
NewC is C + 1,
listcount(Xs, [[X0, NewC]|RAcc], L).
listcount([X|Xs], Acc, L) :-
listcount(Xs, [[X, 1]|Acc], L).
Note that listcount/2 defers to the accumulator-based version, listcount/3 which maintains the counts in the accumulator, and does not assume an input ordering or ground input list (named/labelled variables will work fine).
[_, [X, _], _] will match only lists which have 3 elements, 1st and 3rd can be atoms or lists, second element must be list of length 2, but i suppore you know that. It won't match to 2 element list, its better to use head to tail recursion in order to find element and insert it into result list.
Heres a predicate sketch, wich i bet wont work if copy paste ;)
% find_and_inc(+element_to_search, +list_to_search, ?result_list)
find_and_inc(E, [], [[E, 1]]);
find_and_inc(E, [[E,C]|T1], [[E,C1]|T2]) :- C1 is C+1;
find_and_inc(E, [[K,C]|T1], [[K,C]|T2]) :- find_and_inc(E, T1, T2).

Resources