I want to create a predicate in Prolog which will check if a list A is a sublist of a list B. Moreover I do not want my program to consider an empty list as a subset of another one.
E.g. included_list([1,4],[1,2,3,4,5]).
true.
included_list([2,3],[1,2,3,4,5]).
true.
included_list([1,6],[1,2,3,4,5]).
false.
included_list([],[1,2,3,4,5]).
false.
and so on...
So, I have written the following code so far:
member(X,[X|Tail]).
member(X,[Head|Tail]):- member(X,Tail).
included_list([X],_).
included_list([Head|Tail],List):- member(Head,List), included_list(Tail,List).
But the above code seems to be wrong, because in one specific case it throws true, instead of throwing wrong. I wish I'd made it clear having presented the following screenshot:
As you might have noticed the fifth(5th) sentence gives true, instead of wrong. That is, when I write a sentence of the form:
included_list([x,y],[w,x,v,z]).
whereas only x is included in the second list(and not y) the program gives me true(and this is wrong).
In general, if the first argument of the first list is included in the second list then, no matter if the rest of the former are included in the latter, the program gives me true.
In any other case the program gives me the right result(true or false).
What do I do wrong?
I will be waiting for your answers!
Thank you in advance!
Your problem is the first clause of included_list/2. This:
included_list([X], _).
What does it mean? It means, "If the first argument is a list with one element, succeed, ignoring the second argument."
A short aside: if you would not ignore compiler warnings, you would have caught this mistake already. You should get a loud and clear "Singleton variable" warning, hinting that the code you have written does not do what you think it does.
What you actually mean is more along the lines of:
subset_list([X|Xs], Ys) :-
subset_list_1(Xs, X, Ys).
subset_list_1([], X, Ys) :-
member(X, Ys).
subset_list_1([X|Xs], X0, Ys) :-
member(X0, Ys),
subset_list_1(Xs, X, Ys).
But I don't know why you don't simply use the available subset/2, and simply add a requirement that the subset is not an empty list:
subset_list(Subset, List) :-
Subset = [_|_], % a list with at least one element
subset(Subset, List).
Despite what the documentation claims, the second argument to subset/2 does not have to be a true "set", but it does expect that both lists are ground (do not contain any free variables). You can see the source code here.
In this answer we let meta-predicate maplist/2 handle recursion and define:
all_included(Sub, Es) :-
same_length(Es, Xs),
Sub = [_|_], % minimum length: 1
append(_, Sub, Xs), % maximum length: as long as `Es`
maplist(list_member(Es), Sub).
Let's run the queries the OP gave!
First up, use-cases we expect to succeed:
?- member(Xs, [[1,4],[2,3],[2,3,5],[3,4]]), all_included(Xs, [1,2,3,4,5]).
Xs = [1,4]
; Xs = [2,3]
; Xs = [2,3,5]
; Xs = [3,4]
; false.
Next up, some use-cases we expect to fail:
?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.
?- all_included([3,5], [1,2,5]).
false.
Related
How can I make prolog answer No , if search_answer didn't find an answer , and
Yes with L = [Answer]
search_answer : predicate that returns a list or let's A as a free variable.
found_list(L) :-
search_answer(L).
For example , when asked found_list(L) , although search_answer didn't find an answer , Prolog still answers Yes. I print L , and it is equal to _496 , a free variable.
Given the above piece of code, found_list answers L = [...] if search_answer found a list , else returns L = L, while I want to answer no
I tried the following , but doesn't work
found_list(L) :-
search_answer(L) , is_list(L).
liar_detector is my search_answer predicate , with L = answer
and liars is my found_answer
In found_list(L) :- search_answer(A). both L and A are singleton. I assume you saw the warning. You need to fix that for this predicate to make sense. Do you really want L = [Answer] or L = Answer?
You can achieve what you're after this way:
found_list(A) :-
search_answer(A).
This will fail (result in "no") if search_answer(A) doesn't succeed, and your result will be A if it does succeed.
If you want the result as an answer within a list, you can do this:
found_list([A]) :-
search_answer(A).
I'm not sure what the value is of either of these. The first found_list/1 is just a simple wrapper on search_answer/1 without any additional logic. The second simply makes a single-element list out of the search_answer/1 result. If A is already a list, you don't need to put it inside of brackets ([...]), otherwise you just get a list within a list. I suspect you are really trying to do something else but haven't explained.
In response to the updated question, the following code should work if A is a simple unbound term:
found_list(A) :-
search_answer(A),
is_list(A).
However, is_list/1 will succeed if its argument has a list structure even though it's elements may be unbound:
| ?- X = [_], is_list(X).
X = [_]
yes
| ?-
So, for example, if search_answer(A) succeeds with A = [_], then found_list(A) will suceed with A = [_].
ground/1 can be useful here since:
| ?- ground(X).
no
| ?- ground([_|_]).
no
| ?- ground([a,b]).
yes
| ?-
Thus, the following solution should work:
found_list(A) :-
search_answer(A),
ground(A).
If your intention is not to backtrack to search_answer(A) if A is not ground, but just fail, you could implement found_list/1 as:
found_list(A) :-
search_answer(A),
( ground(A) -> true ; !, false ).
I think, though, there may be a more fundamental issue with the code, as it shouldn't have a behavior that you feel compelled to work around like this.
I'm new to Prolog and I am trying to understand it.
I started with some simple program, this one should:
check if an element is contained in the rest of the list
if FALSE do nothing
if TRUE add it to a second list. (only one occurrence of a char should be added to the second list).
Some examples with expected results:
?- occ([a,b,c,a,a,b,e,f,g], Y).
Y = [a,b].
?- occ([a,a,a,a,a], Y).
Y = [a].
?- occ([a,b,c,d,e,f,g], Y).
Y = [].
Here's the code I wrote, but I have some problems (it always returns true).
occ([],[]).
occ([],_Y).
occ([X|Xs],[X|Y]) :-
occ(Xs,Y),
member(X,Xs),
not(member(X,Y)),
!.
occ([_X|_Xs],_Y).
I tried using the debugger and I found that the not(member(X,Y)) is always false and in the binding section there is only X and Xs and never Y. Any advice is much appreciated! Thank you.
UPDATE
I think I solved it, here's the code:
occ([],[]).
occ([X|Xs],[X|Y]) :-
occ(Xs,Y),
member(X,Xs),
not(member(X,Y)),
!.
occ([_X|_Xs],[]).
But I'm not really sure why it works now... in the 3-th occ I changed the _Y with []..
But why does it change the results?
In this answer we use meta-predicate tpartition/4 in combination with if_/3 and (=)/3.
We define list_duplicateset/2 like this:
list_duplicateset([], []).
list_duplicateset([E|Xs0], Ys0) :-
tpartition(=(E), Xs0, Es, Xs),
if_(Es = [],
Ys0 = Ys,
Ys0 = [E|Ys]),
list_duplicateset(Xs, Ys).
First, we run a sample query taken from this answer to a similar question:
?- list_duplicateset([1,2,2,3,4,5,7,6,7], Xs).
Xs = [2,7].
Next, let's run the queries the OP gave:
?- list_duplicateset([a,b,c,a,a,b,e,f,g], Xs).
Xs = [a, b].
?- list_duplicateset([a,a,a,a,a], Xs).
Xs = [a].
?- list_duplicateset([a,b,c,d,e,f,g], Xs).
Xs = [].
Note that all queries presented above
give the expected answers and succeed deterministically.
I'm trying to write a predicate to remove the head from every list in list of lists and add the tails to a new list. The resulting list should be returned as the second parameter.
Here's the attempt:
construct_new(S,New) :-
New = [],
new_situation(S,New).
new_situation([],_).
new_situation([H|T], New) :-
chop(H, H1),
new_situation(T, [H1|New]).
chop([_|T], T).
You would call it like this:
construct_new([[x,x],[b,c],[d,e,f]],S).
This, however, only produces output true..
Step-by-step execution
Your query is construct_new(Input,Output), for some instanciated Input list.
The first statement in construct_new/2 unifies Output (a.k.a. New) with the empty list. Where is the returned list supposed to be available for the caller? Both arguments are now unified.
You call new_situation(Input,[])
You match the second clause new_situation([H|T],[]), which performs its task recursively (step 4, ...), until ...
You reach new_situation([],_), which successfully discards the intermediate list you built.
Solutions
Write a simple recursive predicate:
new_situation([],[]).
new_situation([[_|L]|T],[L|R]) :-
new_situation(T,R).
Use maplist:
construct_new(S,R) :-
maplist(chop,S,R).
Remark
As pointed out by other answers and comments, your predicates are badly named. construct_new is not a relation, but an action, and could be used to represent almost anything. I tend to like chop because it clearly conveys the act of beheading, but this is not an appropriate name for a relation. repeat's list_head_tail(L,H,T) is declarative and associates variables to their roles. When using maplist, the other predicate (new_situation) doesn't even need to exist...
...even though guillotine/3 is tempting.
This could be done with a DCG:
owth(Lists, Tails) :-
phrase(tails(Tails), Lists).
tails([]) --> [].
tails([T|Tails]) --> [[_|T]], tails(Tails).
Yielding these queries:
| ?- owth([[x,x],[b,c],[d,e,f]], T).
T = [[x],[c],[e,f]] ? ;
no
| ?- owth(L, [[x],[c],[e,f]]).
L = [[_,x],[_,c],[_,e,f]]
yes
(owth = Off with their heads! or, if used the other direction, On with their heads!)
If you also want to capture the heads, you can enhance it as follows:
owth(Lists, Heads, Tails) :-
phrase(tails(Heads, Tails), Lists).
tails([], []) --> [].
tails([H|Hs], [T|Tails]) --> [[H|T]], tails(Hs, Tails).
We use meta-predicate maplist/[3-4] with one of these following auxiliary predicates:
list_tail([_|Xs],Xs).
list_head_tail([X|Xs],X,Xs).
Let's run some queries!
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],Heads,Tails).
Heads = [x,b,d],
Tails = [[x],[c],[e,f]].
If you are only interested in the tails, use maplist/4 together with list_head_tail/3 ...
?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],_,Tails).
Tails = [[x],[c],[e,f]].
... or, even simpler, maplist/3 in tandem with list_tail/2:
?- maplist(list_tail,[[x,x],[b,c],[d,e,f]],Tails).
Tails = [[x],[c],[e,f]].
You can also use the somewhat ugly one-liner with findall/3:
?- L = [[x,x],[b,c],[d,e,f]],
findall(T, ( member(M, L), append([_], T, M) ), R).
R = [[x], [c], [e, f]].
(OK, technically a two-liner. Either way, you don't even need to define a helper predicate.)
But definitely prefer the maplist solution that uses chop as shown above.
If you do the maplist expansion by hand, and name your chop/2 a bit better, you would get:
lists_tails([], []).
lists_tails([X|Xs], [T|Ts]) :-
list_tail(X, T),
lists_tails(Xs, Ts).
And since you can do unification in the head of the predicate, you can transform this to:
lists_tails([], []).
lists_tails([[_|T]|Xs], [T|Ts]) :-
lists_tails(Xs, Ts).
But this is identical to what you have in the other answer.
Exercise: why can't we say:
?- maplist(append([_]), R, [[x,x],[b,c],[d,e,f]]).
I want to solve the following exercise in Prolog:
For a list of integers Zs, max_sequence(Zs,Xs) finds a longest increasing subsequence Xs.
Sample queries:
?- max_sequence([1,2,1,2,3,4,2,1,2,1],Xs).
Xs = [1,2,3,4]. % expected result
?- max_sequence([1,2,1,2,3,4,2,1,6,7,7,2,1,8],Xs).
Xs = [1,2,3,4,6,7,8]. % expected result
I can't understand why... but my code is wrong, the result is always false.
max_sequence(L,R) :-
cresc(L,[],R).
cresc([],[],[]).
cresc([H|T],C,[H|C]) :-
maxList(H,C),
\+ member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
member(H,C),
cresc(T,C,C).
cresc([H|T],C,C) :-
\+ maxList(H,C),
cresc(T,C,C).
maxList(_,[]).
maxList(N, [H|T]) :-
N>H,
maxList(N,T).
I would like to know if my approach to the problem is correct.
Thanks for any help!
TL;DR: Solve problems on a high-level: Think idiomatically; and don't reinvent the wheel :)
Use clpfd!
:- use_module(library(clpfd)).
We proceed by taking the following two steps:
We start by using the meta-predicate splitlistIfAdj/3 together with (#>=)/3:
?- splitlistIfAdj(#>=,[1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zss).
Zss = [[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]].
We are only interested in sublists of maximum size. max_of_by/3 can exclude all other ones:
?- max_of_by(Xs,[[1,2],[2],[2],[1,2,3,4],[2],[1,3,5,7],[1]],length).
Xs = [1,2,3,4]
; Xs = [1,3,5,7].
That's it! Let's put it together and define list_longest_ascending_sublist/2:
list_longest_ascending_sublist(Xs,Zs) :-
splitlistAdjIf(#>=,Xs,Yss),
max_of_by(Zs,Yss,length).
Sample queries:
?- list_longest_ascending_sublist([1,2,2,2,1,2,3,4,2,1,3,5,7,1],Zs).
Zs = [1,2,3,4]
; Zs = [1,3,5,7].
?- list_longest_ascending_sublist([1,2,2,3,4,5,6,2,1,2,3,4,2,1,3,5,7,1],Zs).
Zs = [2,3,4,5,6].
I can't understand your approach at all, but using Trace command in swi-prolog you can see your program execution step by step to see where it fails. Try it and you will see what's wrong with your code.
Anyway this could be one possible solution: starting from the first element of the list you should simply collect a list until elements are increasing, keeping also the length of this sublist, this is the first candidate. Then start again collecting a new list and its length, and if is longer than the candidate, you switch them, and so on..
Here you can find the code: max_seqs , the first part.
How can I check if an element in the list is an empty list: [] ?
I've got the following:
display_degrees([A,B,C,D]):- write(B).
display_degrees([A,B,C,D]):- B==[], nl,write('has no degree'), nl, !.
When I enter in something like:
display_degrees([1,[],3,4]).
I just get: [] instead of 'has no degree'. Is my syntax wrong? Can I not add a clause to this predicate like this?
You're getting this behavior because proof search stops when a goal has succeeded. When you type
display_degrees([1,[],3,4]).
the first rule unifies, and it writes B. Since it was a success, it stops. You can ask Prolog to keep searching, and then it will find the second clause. In swipl, I get
?- [foo].
?- display_degrees([1,[],3,4]).
[]
true r % I type 'r' there
has no degree
true.
If you're just learning Prolog, I suggest you avoid the cut operator ! for some time. Also, doing IO is not the most intuitive thing. I would try some exercises with defining things like natural numbers and recursive functions. E.g., plus:
plus(z, X, X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
The problem with what you have is that the more general rule will fire first. You could switch the order:
display_degrees([A,[],C,D]) :- nl, write('has no degree'), nl, !.
display_degrees([A,B,C,D]) :- write(B).
I could just as well have written for the first predicate:
display_degrees([A,B,C,D]) :- B == [], nl, write('has no degree'), nl, !.
But the "shortcut" I show initially is more idiomatic for a Prolog predicate like this.
I kept the cut since you know you deterministically want one choice. The first rule will match if and only if the second list element is [].
| ?- display_degrees([1,[],3,4]).
has no degree
yes
| ?- display_degrees([1,2,3,4]).
2
yes
| ?-