Compare list in prolog - list

I just started learning prolog and i don't understand why this returning false. I tried find solutions, but i not found. Can someone tell me why this return false?
[[A],B,C]=[[a,b,c],[d,e,f],1].

Short answer: [A] is a singleton list, but the corresponding element [a,b,c] has three elements.
You aim to match [[A], B, C] with [[a,b,c], [d,e,f], 1]. This thus means that you want to match a list with three elements with [[a,b,c], [d,e,f], 1]. Furthermore it means that you want to match [A] = [a,b,c], B = [d,e,f] and C = 1. The [A] can however not match with [a,b,c], since [A] means a singleton list.
You probably want to match this with [A,B,C] instead:
?- [[A],B,C]=[[a,b,c],[d,e,f],1].
false.
?- [A,B,C]=[[a,b,c],[d,e,f],1].
A = [a, b, c],
B = [d, e, f],
C = 1.
If you want to match with a non-empty list, with A the first element, you can match this with [A|_] instead:
?- [[A|_],B,C]=[[a,b,c],[d,e,f],1].
A = a,
B = [d, e, f],
C = 1.

Here is another way to answer why your query fails using library(diadem):
?- [[A],B,C]=[[a,b,c],[d,e,f],1].
false.
?- [[A],B,C]=[[a,b,c],[d,e,f],1].?X.
X = ([[A]|_]=[[_,_|_]|_]) /* 1 */
; X = (dif(A100,B100),[[A|A100]|_]=[[_|B100]|_]) /* 2 */
; X = (dif(A100,B100),[A100|_]=[B100|_]) /* 3 */
; X = (dif(A100,B100),A100=B100) /* 4 */
; ... .
Here the system generates most general generalizations that still fail.
The first generalization removes all irrelevant parts, what remains is this [A] and [_,_|_].
The second generalization insists that the tail of both lists is just different (instead of insisting that they are [] and [_|_] as stated in the first generalization).
The third and fourth are just more general views of it.

Related

Write a predicate called rlen(X,N) to be true when N counts the total number of occurrences of atoms in the list X

I want to get this solution for my question. For example, ?- rlen([a,[a,b],c],X). returns X = 4. I tried the following code but it returns answer 3. Maybe, it's taking [a,b] as one element. I am new to prolog and learning, any help would be really appreciated.
rlen([],0).
rlen([_|T],N) :- rlen(T,N1),N is N1+1.
The code you wrote returns the number of elements in a list and [a,[a,b],c] has exactly 3 elements: a, [a,b] and c. If you want to do a nested count, I would suggest using the build-in predicate flatten/2 to flatten the list.
example (tested with SWISH):
?- rlen([a,[a,b],c],X).
X = 3.
?- flatten([a,[a,b],c],L).
L = [a, a, b, c].
?- flatten([a,[a,b],c],L), rlen(L,N).
L = [a, a, b, c],
N = 4.
However not using inbuild predicates is a bit more challenging, because you have to go through your list like in any normal length predicate, and for every Head element you have to distinguish between the case that the head element is a list or is not a list. If A is a list, count the elements of A, otherwise just add 1. (a -> b ; c ) is an if-then else: if a, then b, else c. Tested with SWISH:
rlen([],0).
rlen([A|T],N) :-
( is_list(A)
-> rlen(A,NA)
; NA is 1
),
rlen(T,NT),
N is NA+NT.
?- rlen([a,[a,b],c],X).
X = 4.

Is there a way to select only the first and last element of a list in PROLOG?

I am trying to write a predicate that will be true if X is a sublist of Y, without taking into account the first term and the last term of Y. For example, query listWithinList([b,c,d],[a,b,c,d,e]) would return True, but query listWithinList([b,c,d,e],[a,b,c,d,e]) would yield False because e, the last element of Y, should not be part of X.
Currently I have
listWithinList(X,Y):-append(_,Y2,Y), append(X,_,Y2).
but I am not sure how to change the code so that it does the same trick but without taking into account the first and last term of Y.
When you write _ in an argument to append, it refers to an arbitrary list. So arbitrary that its length is arbitrary too.
For example:
?- append(_, Suffix, [a, b, c]).
Suffix = [a, b, c] ;
Suffix = [b, c] ;
Suffix = [c] ;
Suffix = [] ;
false.
Here _ can stand for any of the lists [], [a], [a, b], [a, b, c]. But I don't need to tell you this. Prolog can tell you this if you give the anonymous variable _ a proper name instead:
?- append(Prefix, Suffix, [a, b, c]).
Prefix = [],
Suffix = [a, b, c] ;
Prefix = [a],
Suffix = [b, c] ;
Prefix = [a, b],
Suffix = [c] ;
Prefix = [a, b, c],
Suffix = [] ;
false.
In contrast, the term [_] stands not for an abitrary list. It stands for a list that definitely has exactly one element. That element (denoted _) is arbitrary.
For example:
?- append([_], Suffix, [a, b, c]).
Suffix = [b, c].
Or, again, with a proper variable name so we can see the binding:
?- append([X], Suffix, [a, b, c]).
X = a,
Suffix = [b, c].
All this is to say that the definition from the question:
listWithinList(X,Y):-append(_,Y2,Y), append(X,_,Y2).
Is close to being correct. But the two uses of _ don't "remove" one element each. They "remove" an arbitrary number of elements each. So you don't just get the middle of the list:
?- listWithinList(Middle, [a, b, c, d, e]).
Middle = [] ;
Middle = [a] ;
Middle = [a, b] ;
Middle = [a, b, c] ;
Middle = [a, b, c, d] ;
Middle = [a, b, c, d, e] ;
Middle = [] ;
Middle = [b] ;
Middle = [b, c] ;
Middle = [b, c, d] ;
Middle = [b, c, d, e] ;
Middle = [] ;
Middle = [c] ;
Middle = [c, d] ;
Middle = [c, d, e] ;
Middle = [] ;
Middle = [d] ;
Middle = [d, e] ;
Middle = [] ;
Middle = [e] ;
Middle = [] ;
false.
If we want to "remove" lists of exactly one element from the front and the back, we must write [_]:
listWithinList(X, Y) :-
append([_], Y2, Y),
append(X, [_], Y2).
This now behaves like this:
?- listWithinList(Middle, [a, b, c, d, e]).
Middle = [b, c, d] ;
false.
Additionally, note the difference between [_] and [_|_]. The former stands for a list of exactly one element. The latter stands for a list of one or more elements. In this case you don't want to "remove" more than one element, so using [_|_], like one of the other answers suggests, is absolute nonsense.
Finally, Prolog can suggest a further simplification to us:
?- append([X], Xs, Ys).
Ys = [X|Xs].
Appending a one-element list [X] and an arbitrary list Xs gives a list that we can also write as [X | Xs] without using append. So one of the append calls is not needed. I might write this predicate like this:
list_middle(List, Middle) :-
append([_First | Middle], [_Last], List).
And use it like this:
?- list_middle([a, b, c, d, e], Middle).
Middle = [b, c, d] ;
false.
Or like this:
?- list_middle(List, [1, 2, 3]).
List = [_2658, 1, 2, 3, _2664].
Grammars are very intuitive for such tasks. Just describe what we have:
list_within(Xs, Ys) :-
phrase(( [_First], seq(Ys), [_Last] ), Xs).
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
That is, first the element _First, then the sequence Ys, and finally the element _Last.
Due to how lists are represented in Prolog, you can easily remove the first element by destructuring it as its head and tail, and unifying the result with tail, as follows:
tail([_|L], L).
On success, the predicates unifies the second parameter with the tail of the first.
To remove the last element, you can say that your input list is the result of appending a prefix to a list of one element (whose value is not important):
butlast(List, Prefix) :-
append(Prefix, [_LastValue], List).
You can combine them both to remove both extremities:
chop(List, Middle):
tail(List, Tail),
butlast(Tail, Middle).
Here is my approach:
First: Create all combinations of the List that are acceptable when the first letter is removed and last letter is removed.
listWithinList(M,L):-
append([_|_],L2,L),
append(S,[_|_],L2),
The first append removes the first element from the list, and the second append removes the last element from the list. The combinations of List are stored in S.
Second: We use the same predicate to check if M is same as any of the combinations in S.
same(L1,L2):-
L1==L2.
Putting the code together:
listWithinList(M,L):-
append([_|_],L2,L),
append(S,[_|_],L2),
( same(M,S)->write(S),
write('This combination is correct.') ).
same(L1,L2):-
L1==L2.
Examples:
?-listWithinList([b,c,d],[a,b,c,d,e]).
[b, c, d]This combination is correct.
1true
false
?-listWithinList([b,c,d,e],[a,b,c,d,e]).
false
?-listWithinList([a,b,c,d,e],[a,b,c,d,e]).
false

Copy certain characters from a list to another on prolog

So i have this code which copies everything from a list to another one.
How should I modify it in order to copy, lets say the first two character.
$copy(L,R) :-
copy2(L,R).
copy2([X],[X]).
copy2([H|T1],[H|T2]) :-
copy2(T1,T2).
example of what i want it to be: ?- copy([a,b,c,d,e,f],X,2). --> X = [a,b]
You can copy lists just with unification:
?- [a,b,c,d,e] = List.
List = [a, b, c, d, e].
?- [a,b,c,d,e] = [V,W,X,Y,Z].
V = a,
W = b,
X = c,
Y = d,
Z = e.
?- [a,b,c,d,e] = [V,W|Rest].
V = a,
W = b,
Rest = [c, d, e].
A predicate like the one you describe, copying the first N elements of a list, can be defined thus:
first_n(List, N, Xs) :-
length(Xs, N),
append(Xs _, List).
Which works like so:
?- first_n([a,b,c,d,e], 2, X).
X = [a, b].
There are a bunch of different ways to write a similar predicate. The way I have defined first_n/3, it will fail if N is larger than the length of List (this was pointed to out by #false in the comments). One could instead write an analog of the common function take, which will return List in its entirety in the event that N is greater than List's length:
take_n(N, List, Taken) :-
( length(List, M),
N > M
->
Taken = List
;
length(Taken, N),
append(Taken, _, List)
).
This answer was corrected (several times) under the guidance of #false's helpful criticism.

Add two more occurrences using prolog

I have a list [a, b, a, a, a, c, c]
and I need to add two more occurrences of each element.
The end result should look like this:
[a, a, a, b, b, b, a, a, a, a, a, c, c, c, c]
If I have an item on the list that is the same as the next item, then it keeps going until there is a new item, when it finds the new item, it adds two occurrences of the previous item then moves on.
This is my code so far, but I can't figure out how to add two...
dbl([], []).
dbl([X], [X,X]).
dbl([H|T], [H,H|T], [H,H|R]) :- dbl(T, R).
Your code looks a bit strange because the last rule takes three parameters. You only call the binary version, so no recursion will ever try to derive it.
You already had a good idea to look at the parts of the list, where elements change. So there are 4 cases:
1) Your list is empty.
2) You have exactly one element.
3) Your list starts with two equal elements.
4) Your list starts with two different elements.
Case 1 is not specified, so you might need to find a sensible choice for that. Case 2 is somehow similar to case 4, since the end of the list can be seen as a change in elements, where you need to append two copies, but then you are done. Case 3 is quite simple, we can just keep the element and recurse on the rest. Case 4 is where you need to insert the two copies again.
This means your code will look something like this:
% Case 1
dbl([],[]).
% Case 2
dbl([X],[X,X,X]).
% Case 3
dbl([X,X|Xs], [X|Ys]) :-
% [...] recursion skipping the leading X
% Case 4
dbl([X,Y|Xs], [X,X,X|Ys]) :-
dif(X,Y),
% [...] we inserted the copies, so recursion on [Y|Xs] and Ys
Case 3 should be easy to finish, we just drop the first X from both lists and recurse on dbl([X|Xs],Ys). Note that we implicitly made the first two elements equal (i.e. we unified them) by writing the same variable twice.
If you look at the head of case 4, you can directly imitate the pattern you described: supposed the list starts with X, then Y and they are different (dif(X,Y)), the X is repeated 3 times instead of just copied and we then continue with the recursion on the rest starting with Y: dbl([Y|Xs],Ys).
So let's try out the predicate:
?- dbl([a,b,a,a,a,c,c],[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]).
true ;
false.
Our test case is accepted (true) and we don't find more than one solution (false).
Let's see if we find a wrong solution:
?- dif(Xs,[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]), dbl([a,b,a,a,a,c,c],Xs).
false.
No, that's also good. What happens, if we have variables in our list?
?- dbl([a,X,a],Ys).
X = a,
Ys = [a, a, a, a, a] ;
Ys = [a, a, a, X, X, X, a, a, a],
dif(X, a),
dif(X, a) ;
false.
Either X = a, then Ys is single run of 5 as; or X is not equal to a, then we need to append the copies in all three runs. Looks also fine. (*)
Now lets see, what happens if we only specify the solution:
?- dbl(X,[a,a,a,b,b]).
false.
Right, a list with a run of only two bs can not be a result of our specification. So lets try to add one:
?- dbl(X,[a,a,a,b,b,b]).
X = [a, b] ;
false.
Hooray, it worked! So lets as a last test look what happens, if we just call our predicate with two variables:
?- dbl(Xs,Ys).
Xs = Ys, Ys = [] ;
Xs = [_G15],
Ys = [_G15, _G15, _G15] ;
Xs = [_G15, _G15],
Ys = [_G15, _G15, _G15, _G15] ;
Xs = [_G15, _G15, _G15],
Ys = [_G15, _G15, _G15, _G15, _G15] ;
Xs = [_G15, _G15, _G15, _G15],
Ys = [_G15, _G15, _G15, _G15, _G15, _G15] ;
[...]
It seems we get the correct answers, but we see only cases for a single run. This is a result of prolog's search strategy(which i will not explain in here). But if we look at shorter lists before we generate longer ones, we can see all the solutions:
?- length(Xs,_), dbl(Xs,Ys).
Xs = Ys, Ys = [] ;
Xs = [_G16],
Ys = [_G16, _G16, _G16] ;
Xs = [_G16, _G16],
Ys = [_G16, _G16, _G16, _G16] ;
Xs = [_G86, _G89],
Ys = [_G86, _G86, _G86, _G89, _G89, _G89],
dif(_G86, _G89) ;
Xs = [_G16, _G16, _G16],
Ys = [_G16, _G16, _G16, _G16, _G16] ;
Xs = [_G188, _G188, _G194],
Ys = [_G188, _G188, _G188, _G188, _G194, _G194, _G194],
dif(_G188, _G194) ;
[...]
So it seems we have a working predicate (**), supposed you filled in the missing goals from the text :)
(*) A remark here: this case only works because we are using dif. The first predicates with equality, one usually encounters are =, == and their respective negations \= and \==. The = stands for unifyability (substituting variables in the arguments s.t. they become equal) and the == stands for syntactic equality (terms being exactly equal). E.g.:
?- f(X) = f(a).
X = a.
?- f(X) \= f(a).
false.
?- f(X) == f(a).
false.
?- f(X) \== f(a).
true.
This means, we can make f(X) equal to f(a), if we substitute X by a. This means if we ask if they can not be made equal (\=), we get the answer false. On the other hand, the two terms are not equal, so == returns false, and its negation \== answers true.
What this also means is that X \== Y is always true, so we can not use \== in our code. In contrast to that, dif waits until it can decide wether its arguments are equal or not. If this is still undecided after finding an answer, the "dif(X,a)" statements are printed.
(**) One last remark here: There is also a solution with the if-then-else construct (test -> goals_if_true; goals_if_false, which merges cases 3 and 4. Since i prefer this solution, you might need to look into the other version yourself.
TL;DR:
From a declarative point of view, the code sketched by #lambda.xy.x is perfect.
Its determinacy can be improved without sacrificing logical-purity.
Code variant #0: #lambda.xy.x's code
Here's the code we want to improve:
dbl0([], []).
dbl0([X], [X,X,X]).
dbl0([X,X|Xs], [X|Ys]) :-
dbl0([X|Xs], Ys).
dbl0([X,Y|Xs], [X,X,X|Ys]) :-
dif(X, Y),
dbl0([Y|Xs], Ys).
Consider the following query and the answer SWI-Prolog gives us:
?- dbl0([a],Xs).
Xs = [a,a,a] ;
false.
With ; false the SWI prolog-toplevel
indicates a choicepoint was left when proving the goal.
For the first answer, Prolog did not search the entire proof tree.
Instead, it replied "here's an answer, there may be more".
Then, when asked for more solutions, Prolog traversed the remaining branches of the proof tree but finds no more answers.
In other words: Prolog needs to think twice to prove something we knew all along!
So, how can we give determinacy hints to Prolog?
By utilizing:
control constructs !/0 and / or (->)/2 (potentially impure)
first argument indexing on the principal functor (never impure)
The code presented in the earlier answer by #CapelliC—which is based on !/0, (->)/2, and the meta-logical predicate (\=)/2—runs well if all arguments are sufficiently instantiated. If not, erratic answers may result—as #lambda.xy.x's comment shows.
Code variant #1: indexing
Indexing can improve determinacy without ever rendering the code non-monotonic. While different Prolog processors have distinct advanced indexing capabilities, the "first-argument principal-functor" indexing variant is widely available.
Principal? This is why executing the goal dbl0([a],Xs) leaves a choicepoint behind: Yes, the goal only matches one clause—dbl0([X],[X,X,X]).—but looking no deeper than the principal functor Prolog assumes that any of the last three clauses could eventually get used. Of course, we know better...
To tell Prolog we utilize principal-functor first-argument indexing:
dbl1([], []).
dbl1([E|Es], Xs) :-
dbl1_(Es, Xs, E).
dbl1_([], [E,E,E], E).
dbl1_([E|Es], [E|Xs], E) :-
dbl1_(Es, Xs, E).
dbl1_([E|Es], [E0,E0,E0|Xs], E0) :-
dif(E0, E),
dbl1_(Es, Xs, E).
Better? Somewhat, but determinacy could be better still...
Code variant #2: indexing on reified term equality
To make Prolog see that the two recursive clauses of dbl1_/3 are mutually exclusive (in certain cases), we reify the truth value of
term equality and then index on that value:
This is where reified term equality (=)/3 comes into play:
dbl2([], []).
dbl2([E|Es], Xs) :-
dbl2_(Es, Xs, E).
dbl2_([], [E,E,E], E).
dbl2_([E|Es], Xs, E0) :-
=(E0, E, T),
t_dbl2_(T, Xs, E0, E, Es).
t_dbl2_(true, [E|Xs], _, E, Es) :-
dbl2_(Es, Xs, E).
t_dbl2_(false, [E0,E0,E0|Xs], E0, E, Es) :-
dbl2_(Es, Xs, E).
Sample queries using SWI-Prolog:
?- dbl0([a],Xs).
Xs = [a, a, a] ;
false.
?- dbl1([a],Xs).
Xs = [a, a, a].
?- dbl2([a],Xs).
Xs = [a, a, a].
?- dbl0([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b] ;
false.
?- dbl1([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b] ;
false.
?- dbl2([a,b,b],Xs).
Xs = [a, a, a, b, b, b, b].
To make above code more compact, use control construct if_/3 .
I was just about to throw this version with if_/3 and (=)/3 in the hat when I saw #repeat already suggested it. So this is essentially the more compact version as outlined by #repeat:
list_dbl([],[]).
list_dbl([X],[X,X,X]).
list_dbl([A,B|Xs],DBL) :-
if_(A=B,DBL=[A,B|Ys],DBL=[A,A,A,B|Ys]),
list_dbl([B|Xs],[B|Ys]).
It yields the same results as dbl2/2 by #repeat:
?- list_dbl([a],DBL).
DBL = [a,a,a]
?- list_dbl([a,b,b],DBL).
DBL = [a,a,a,b,b,b,b]
The example query by the OP works as expected:
?- list_dbl([a,b,a,a,a,c,c],DBL).
DBL = [a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]
Plus here are some of the example queries provided by #lambda.xy.x. They yield the same results as #repeat's dbl/2 and #lambda.xy.x's dbl/2:
?- dif(Xs,[a,a,a,b,b,b,a,a,a,a,a,c,c,c,c]), list_dbl([a,b,a,a,a,c,c],Xs).
no
?- list_dbl(X,[a,a,a,b,b]).
no
?- list_dbl(L,[a,a,a,b,b,b]).
L = [a,b] ? ;
no
?- list_dbl(L,DBL).
DBL = L = [] ? ;
DBL = [_A,_A,_A],
L = [_A] ? ;
DBL = [_A,_A,_A,_A],
L = [_A,_A] ? ;
DBL = [_A,_A,_A,_A,_A],
L = [_A,_A,_A] ? ;
...
?- list_dbl([a,X,a],DBL).
DBL = [a,a,a,a,a],
X = a ? ;
DBL = [a,a,a,X,X,X,a,a,a],
dif(X,a),
dif(a,X)
?- length(L,_), list_dbl(L,DBL).
DBL = L = [] ? ;
DBL = [_A,_A,_A],
L = [_A] ? ;
DBL = [_A,_A,_A,_A],
L = [_A,_A] ? ;
DBL = [_A,_A,_A,_B,_B,_B],
L = [_A,_B],
dif(_A,_B) ? ;
DBL = [_A,_A,_A,_A,_A],
L = [_A,_A,_A] ?
dbl([X,Y|T], [X,X,X|R]) :- X \= Y, !, dbl([Y|T], R).
dbl([H|T], R) :-
T = []
-> R = [H,H,H]
; R = [H|Q], dbl(T, Q).
The first clause handles the basic requirement, adding two elements on sequence change.
The second one handles list termination as a sequence change, otherwise, does a plain copy.

Trimming off uninitialized list values in prolog

I'm writing something in prolog and the way I used append, it ends up returning a list like [a,b,c|_]. Is there any standard predicate (or simple way) to cut off all the uninitialized/arbitrary values?
Edit to add: Length won't work because the list could be of an arbitrary length, I don't know what it's going to be ahead of time, otherwise I would have already used that to trim it.
You should check into why append is giving you a list like that. Because observe this behavior of append that fixes the problem you are seeing:
?- append([a,b,c|_], X, L).
L = [a,b,c|X]
?- append([a,b,c|_], X, L), X=[].
L = [a,b,c]
If you're list isn't terminated with [], you're almost certainly building your list incorrectly.
You can use length/2 to this end!
?- Xs = [1,2,3|_], length(Xs, N).
Xs = [1,2,3], N = 3
; Xs = [1,2,3,_A], N = 4
; Xs = [1,2,3,_A,_B], N = 5
; ... .
However, it is not clear to me what you want to describe here. If you want to stick with the smallest solution use once(length(Xs, N)) instead.
You can close an open list like this:
close_list([]) :- !.
close_list([_ | T]) :-
close_list(T).
i.e. you have to walk through all the elements to reach the variable tail, and then bind it to the empty list.
Usage:
?- List = [a, b, C, d, 2.2 | _], close_list(List).
List = [a, b, C, d, 2.2].
If you hold a variable that is bound to the tail then it becomes much simpler:
?- List = [a, b, C, d, 2.2 | Tail], Tail = [].
List = [a, b, C, d, 2.2],
Tail = [].