Related
I have this predicate and this works.
last(X,[Y|X]).
last(X,[Y|Z]) :- last(X,Z).
But I also want to do it with my list_merge predicate.
list_merge([], X, X).
list_merge([X | L1], L2, [X | L3]) :-
list_merge(L1, L2, L3).
How can I combine them?
X is the last part of Y if there is something you can merge with X to get Y
:
last(X,Y) :- list_merge( _, X, Y ).
Your code is definitely not working according to the expected behavior of "last". This is what I see:
?- last(Last, [a,b,c,d]).
Last = [b, c, d] ;
Last = [c, d] ;
Last = [d] ;
Last = [] ;
false.
Is this really what you intended?
The solution in the other answer just repeats the same answers.
Here is how you could have defined "last" (... element of a list)
last(X, [X])
last(X, [_|Y]) :- last(X, Y).
This works (try it!) even if it isn't optimal.
To get the last element of a list using "append" in the other direction, you should type:
?- append(_Front, [Last], List).
You can do exactly the same with your "list_merge". However "merge" also has a different expected behavior. You'd expect:
?- merge([b,m,x], [a,n,y], Merged).
Merged = [a,b,m,n,x,y].
Note that last is already defined in swi-prolog, and here is its code.
Here is a corrected version of your last:
last_play(Last, [_|[Last]]).
last_play(Last, [_|T]) :-
last_play(Last, T).
Results:
?- last_play(E, L).
L = [_, E] ;
L = [_, _, E] ;
L = [_, _, _, E] ;
L = [_, _, _, _, E] ;
L = [_, _, _, _, _, E]
There's 2 problems with it:
It fails for a list containing a single element:
?- last_play(E, [1]).
false.
It leaves an unwanted choicepoint:
?- last_play(E, [1,2,3]).
E = 3 ;
false.
The linked code above has neither of these problems, because it uses first-argument indexing on [] vs [Head|Tail].
?- last([1], E).
E = 1.
?- last([1,2,3], E).
E = 3.
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
This is my list in Prolog:
myList([a,b,c,d,e]).
I am trying to write a predicate. That predicate should give me this result:
ab
ac
ad
ae
bc
bd
be
cd
ce
de
I found a solution that's near to my goal. But it is not exactly what I want.
?- L=[a,b,c], findall(foo(X,Y), (member(X,L),member(Y,L)), R).
L = [a, b, c],
R = [foo(a, a), foo(a, b), foo(a, c), foo(b, a), foo(b, b), foo(b, c), foo(c, a), foo(c, b), foo(..., ...)].
For example i dont want to aa or bb or cc. Also, there is already ac result. So i dont want to again ca.
Sorry for my English.
Thanks.
?- set_prolog_flag(double_quotes, chars).
true.
?- List = "abcde",
bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
List = "abcde", XYs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- List = [A,B,C,D,E],
bagof(X-Y, Pre^Ys^( append(Pre, [X|Ys], List), member(Y,Ys) ), XYs).
List = [A,B,C,D,E], XYs = [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E].
From your question it is not that evident what you want but it seems you are happy to use findall/3. Above solutions use bagof/3 which is a somewhat more civilized version of findall/3. bagof/3 takes into account variables, and thus you get the same result with concrete characters [a,b,c,d,e] or with a list of variables [A,B,C,D,E].
You have used terms foo(a,b), in such situations it is more common (and convenient) to say a-b.
Here is another solution that does not need any of the higher-order predicates.
:- set_prolog_flag(double_quotes, chars).
:- use_module(library(double_quotes)).
list_pairwise([], []).
list_pairwise([E|Es], Fs0) :-
phrase(values_key(Es, E), Fs0,Fs),
list_pairwise(Es, Fs).
values_key([], _K) --> [].
values_key([V|Vs], K) -->
[K-V],
values_key(Vs, K).
?- list_pairwise("abcde", KVs).
KVs = [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e].
?- list_pairwise(L, [a-b,a-c,a-d,a-e,b-c,b-d,b-e,c-d,c-e,d-e]).
L = "abcde"
; false.
?- list_pairwise(L, [A-B,A-C,A-D,A-E,B-C,B-D,B-E,C-D,C-E,D-E]).
L = [A,B,C,D,E]
; false.
?- KVs = [K1-_,K1-_,K2-_|_], dif(K1,K2), list_pairwise(Ks,KVs).
KVs = [K1-K2,K1-_A,K2-_A], Ks = [K1,K2,_A], dif:dif(K1,K2)
; false.
In the last query we show that a sequence starting with keys, K1, K1, K2 can only result in the sequence of three elements.
What about a couple of predicates as follows ?
printCouples(_, []).
printCouples(E1, [E2 | T]) :-
write(E1), write(E2), nl,
printCouples(E1, T).
printList([]).
printList([H | T]) :-
printCouples(H, T),
printList(T).
From
printList([a, b, c, d])
you get
ab
ac
ad
bc
bd
cd
I'm new to Prolog and trying to do this question. We have a list
List = [a,a,a,a,b,c,c,a,a,d,e,e,e,e]
I want to pack it into sub-lists of similar elements.
Pack( [a,a,a,a,b,c,c,a,a,d,e,e,e,e], Sublists)
should give
Sublists = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]
This is what I have tried so far:
pack([],[],[]).
pack([H],[H],[H]).
pack([H,H1|T],Z,X):- H==H1 , append([H],Z,Z1) , pack([H1|T],Z1,X).
pack([H,H1|T],Z,X):- H=\=H1 , append([H],Z,Z1) ,
append(Z1,X,Xs) , pack([H1|T],Z1,Xs).
Below is the error:
Arithmetic: `a/0' is not a function
In:
[4] a=\=b
[3] pack([a,b|...],[a,a],_1608) at line 13
[2] pack([a,a|...],[a],_1688) at line 13
[1] pack([a,a|...],[],_1762) at line 13
Thanks in advance. I'm trying to solve these problems:
P-99: Ninety-Nine Prolog Problems.
You can approach this kind of problem with simple list processing and using SWI Prolog's dif/2 to provide a general solution:
pack([], []). % packing empty is empty
pack([X], [[X]]). % packing a single element
pack([X,X|T], [[X|PH]|PT]):- % rule for packing when next two terms are the same
pack([X|T], [PH|PT]).
pack([X,Y|T], [[X]|PT]):- % rule for different term
dif(X, Y),
pack([Y|T], PT).
2 ?- pack([a,a,a,a,b,c,c,a,a,d,e,e], L).
L = [[a, a, a, a], [b], [c, c], [a, a], [d], [e, e]] ;
false.
3 ?- pack(L, [[a,a,a], [b,b], [c]]).
L = [a, a, a, b, b, c] ;
false.
4 ?-
Note that lurker's solution still has some performance issues. See the ; false for each solution? This is an indication that Prolog still retains some memory (called a choice point - actually there may be even several such choice points). For many cases however, no such choice point is needed. Here is a solution that overcomes that problem (The name group in place of pack is quite common in the context of Haskell)
group([], []).
group([E|Es], [[E|Gs]|Gss]) :-
igroup(Es, E, Gs, Gss).
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
( E\=F
-> Gs1=[], Gss1=[[E|Gs2]|Gss2]
; E==F
-> Gs1=[E|Gs2], Gss1=Gss2
; E=F,
Gs1=[E|Gs2], Gss1=Gss2
; dif(E, F),
Gs1=[], Gss1=[[E|Gs2]|Gss2]
),
igroup(Es, E, Gs2, Gss2).
Note how the testing for the equality of E and F is split into four cases:
First E \= F which means that both are definitely different.
Then E == F which means that both are definitely identical.
Then E = F which is the general case of equality, and
dif(E, F) which is the case of general inequality
For the last two cases there is no -> because both may be true.
Since it is quite cumbersome to maintain so many cases, there is library(reif)
for
SICStus and
SWI which permits to write the same more compactly:
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
if_(E = F
, ( Gs1 = [E|Gs2], Gss1 = Gss2 )
, ( Gs1 = [], Gss1 = [[E|Gs2]| Gss2] )),
igroup(Es, E, Gs2, Gss2).
The error you got is because =\=/2 is true if expr1 is evaluates to a number not equal to expr2 . Instead you can use \=\2 which evaluates \+term1=term2. ==/2 evaluates to term1 equivalent to term2, =:=/ is true if expr1 is a number which is equal to expr2. One more mistake I found in your code is you're not clearing the Intermediate List. You have to flush the values in it after you have added the similar elements list to your Sublists list. I have used cut ! to reduce backtracking. Instead, if you write mutually exclusive predicates, it's better.
I have edited your code:
pack1([],[],[]).
pack1([H],L,[Z]):- append([H],L,Z),!.
pack1([H,H1|T],Z,X):- H == H1 , append([H],Z,Z1) , pack1([H1|T],Z1,X),!.
pack1([H,H1|T],Z,[Z1|Zs]):- H\=H1 ,append([H],Z,Z1) ,pack1([H1|T],[],Zs),!.
Output:
?-pack1([a,a,a,a,b,c,c,a,a,d,e,e,e,e],[],Z).
Z=[[a, a, a, a], [b], [c, c], [a, a], [d], [e, e, e, e]]
?-pack1([a,a,a,a,b,c,1,c,a,a,d,e,e,e,e],[],Z).
Z= [[a, a, a, a], [b], [c], [1], [c], [a, a], [d], [e, e, e, e]]
?-pack1([],[],Z).
Z= []
Hope this helps.
without using dif/2
my_pack([],[[]]).
my_pack([X], [[X]]).
my_pack([X,X|L], [F|R]) :- my_pack([X|L], [F1|R]), append([X], F1, F).
my_pack([X|L], [F|R]) :- my_pack(L, R), append([X], [], F).
What I am trying to do is append elements from two lists into another and in the end get the value of the new list out in console.
My lists are : A = [a, b]; B(list of pairs) = [(c, cc), (a, aa), (b, bb)]
I want to add the second element of pair of list B if the first element matches the first element of pair (dictionary principle) And I want all those elements to be added in an empty list which the console would output.
What I have so far is this (X would be the empty list):
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
H == A ->
append([B], X, X2), aa([H|T], T2, X2);
aa([H|T], T2, X).
In console I'm typing: read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).
But it keeps returning the [] value of X. How can I get the value of X2 as output if I am asking for X?
Here is the trace output:
Call:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:a==c
Fail:a==c
Redo:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:aa([a, b], [(a,aa), (b,bb)], [])
Call:a==a
Exit:a==a
Call:lists:append([aa], [], _2110)
Exit:lists:append([aa], [], [aa])
Call:aa([a, b], [(b,bb)], [aa])
Call:a==b
Fail:a==b
Redo:aa([a, b], [(b,bb)], [aa])
Call:aa([a, b], [], [aa])
Exit:aa([a, b], [], [aa])
Exit:aa([a, b], [(b,bb)], [aa])
Exit:aa([a, b], [(a,aa), (b,bb)], [])
Exit:aa([a, b], [(c,cc), (a,aa), (b,bb)], [])
Call:write([])
[]
Exit:write([])
It's not a good idea to put the ; at the end of a line, it is very easy to overlook it. I prefer a different format, see below. As for your question, you have the arguments to append/3 in the wrong order. X2 is the intermediate result from the recursive call, and the result you want to "return" is the combination of this X2 with the element B:
aa(_, [], _) :-
true.
aa([H|T], [(A, B)|T2], X) :-
( H == A
-> append([B], X2, X), aa([H|T], T2, X2)
; aa([H|T], T2, X) ).
The goal append([B], X2, X) can be written more clearly as X = [B|X2].
This fixes the immediate problem, but not yet the whole predicate:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa|_G22] ;
false.
You decompose the first argument into [H|T] but don't actually do a recursion over this list, so you never look at b and its corresponding element in the list of pairs.
Here's a simple way to do the whole thing:
aa([], _Pairs, []).
aa([Key|Keys], Pairs, Values) :-
( member((Key, Value), Pairs)
-> aa(Keys, Pairs, Values0),
Values = [Value|Values0]
; aa(Keys, Pairs, Values) ).
The key insight here is that once you know a Key, you can look for a pair (Key, Value) in your list of pairs. Value is not bound to a value yet and will be instantiated by member/2 if it the list contains a pair whose first element is Key. This is the power of unification!
This seems to work:
?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X).
X = [aa, bb].
Finally, you probably don't want to have a read(X) before this, since that means that the user must predict the solution!