Calling facts in query - prolog

This is my code:
sentence([['o'],['m','e','n','i','n','o'],['a','l','e','g','r','e']]).
lastWord(X,[X]).
lastWord(X,[_|Z]) :- lastWord(X,Z).
If I try lastWord(X,[1,2,3]). or even lastWord(X,[['o'],['m','e','n','i','n','o'],['a','l','e','g','r','e']]). I get what I want (which is, of course, the last element of the list (in the examples, 3 and ['a','l','e','g','r','e'].
But if I try lastWord(X, sentence). or lastWord(X, sentence(Y)). I get false.
How can I "call" the defined list (in this case, 'sentence') in lastWord?

Prolog is not a functional language. Thus, in goals such as lastWord(X, sentence) or lastWord(X, sentence(Y)) is not going to replace sentence or sentence(Y) by the argument of the sentence/1 predicate. Try instead:
?- sentence(List), lastWord(Last, List).
List = [[o], [m, e, n, i, n, o], [a, l, e, g, r, e]],
Last = [a, l, e, g, r, e] ;
false.
Note there's a spurious choice point left for the query. You can eliminate it by rewriting the definition of the predicate lastWord/2. A similar predicate, usually named last/2, is often available from libraries:
last([Head| Tail], Last) :-
last(Tail, Head, Last).
last([], Last, Last).
last([Head| Tail], _, Last) :-
last(Tail, Head, Last).
Note the different argument order (Prolog coding guidelines suggest to have input arguments preceding output arguments). Using this predicate instead:
?- sentence(List), last(List, Last).
List = [[o], [m, e, n, i, n, o], [a, l, e, g, r, e]],
Last = [a, l, e, g, r, e].

Related

Split a list in two halves, reversing the first half using difference lists

I need to do an exercise similar to this:
Prolog - Split a list in two halves, reversing the first half.
I am asked to take a list of letters into two lists that are either equal in size (even sized original list I guess) or one is larger than the other by one element (odd sized list), and reverse the first one while I'm at it, but using only difference lists.
These are the required query and output
?-dividelist2([a,b,c,d,e,f | T] - T, L1-[], L2-[]).
L1 = [c,b,a]
L2 = [d,e,f]
?-dividelist2([a,b,c,d,e | T] - T, L1-[], L2-[]).
L1 = [c,b,a]
L2 = [d,e]
% OR
L1 = [b,a]
L2 = [c,d,e]
This is my code using the previous example but modified, I don't know how to properly compare the two lists
"deduct" them from the input and produce [d,e,f]?
dividelist2(In -[], L1-[], L2-[]) :-
length_dl(In - [],L), % length of the list
FL is L//2, % integer division, so half the length, Out1 will be 1 shorter than Out2 if L is odd
( \+ (FL*2 =:= L), % is odd
FLP is FL + 1 % odd case
; FLP = FL % odd and even case
),
take(In,FLP,FirstHalf),
conc([FirstHalf| L2]-l2,L2-[],In-[]),
reverse1(FirstHalf-[], L1-[]). % do the reverse
reverse1(A- Z,L - L):-
A == Z , !.
reverse1([X|Xs] - Z,L - T):-
reverse1(Xs - Z, L - [X|T]).
length_dl(L- L,0):-!.
length_dl([X|T] - L,N):-
length_dl(T- L,N1),
N is N1 + 1 .
take(Src,N,L) :- findall(E, (nth1(I,Src,E), I =< N), L).
conc(L1-T1,T1-T2,L1-T2).
This is the current trace:
Call:dividelist2([a, b, c, d, e, f|_22100]-_22100, _22116-[], _22112-[])
Call:length_dl([a, b, c, d, e, f]-[], _22514)
Call:length_dl([b, c, d, e, f]-[], _22520)
Call:length_dl([c, d, e, f]-[], _22526)
Call:length_dl([d, e, f]-[], _22532)
Call:length_dl([e, f]-[], _22538)
Call:length_dl([f]-[], _22544)
Call:length_dl([]-[], _22550)
Exit:length_dl([]-[], 0)
Call:_22554 is 0+1
Exit:1 is 0+1
Exit:length_dl([f]-[], 1)
Call:_22560 is 1+1
Exit:2 is 1+1
Exit:length_dl([e, f]-[], 2)
Call:_22566 is 2+1
Exit:3 is 2+1
Exit:length_dl([d, e, f]-[], 3)
Call:_22572 is 3+1
Exit:4 is 3+1
Exit:length_dl([c, d, e, f]-[], 4)
Call:_22578 is 4+1
Exit:5 is 4+1
Exit:length_dl([b, c, d, e, f]-[], 5)
Call:_22584 is 5+1
Exit:6 is 5+1
Exit:length_dl([a, b, c, d, e, f]-[], 6)
Call:_22590 is 6//2
Exit:3 is 6//2
Call:3*2=:=6
Exit:3*2=:=6
Call:_22590=3
Exit:3=3
Call:take([a, b, c, d, e, f], 3, _22594)
Call:'$bags' : findall(_22518, (nth1(_22514, [a, b, c, d, e, f], _22518),_22514=<3), _22614)
Exit:'$bags' : findall(_22518, '251db9a2-f596-4daa-adae-38a38a13842c' : (nth1(_22514, [a, b, c, d, e, f], _22518),_22514=<3), [a, b, c])
Exit:take([a, b, c, d, e, f], 3, [a, b, c])
Call:conc([[a, b, c]|_22112]-l2, _22112-[], [a, b, c, d, e, f]-[])
Fail:conc([[a, b, c]|_22112]-l2, _22112-[], [a, b, c, d, e, f]-[])
Fail:dividelist2([a, b, c, d, e, f|_22100]-_22100, _22116-[], _22112-[])
false
thanks
This is not an answer but testing and debugging suggestions that doesn't fit the comment length limit. The suggestions use Logtalk, which you can run with most Prolog systems.
From your question, the dividelist2/3 predicate needs to satisfy a couple of properties, one of them describing the lengths of the resulting lists. We can express this property easily using a predicate, p/1:
p(DL) :-
difflist::length(DL, N),
dividelist2(DL, DL1, DL2),
difflist::length(DL1, N1),
difflist::length(DL2, N2),
N is N1 + N2,
abs(N1 - N2) =< 1.
Here I'm using Logtalk's difflist library object to compute the length of the difference lists. Given this predicate, we can now perform some property-testing of your dividelist2/3 predicate.
Using Logtalk lgtunit tool implementation of property-testing, we get:
?- lgtunit::quick_check(p(+difference_list(integer))).
* quick check test failure (at test 1 after 0 shrinks):
* p(A-A)
false.
I.e. your code fails for the trivial case of an empty difference list. In the query, we use the difference_list(integer) type simply to simplify the generated counter-examples.
Let's try to fix the failure by adding the following clause to your code:
dividelist2(A-A, B-B, C-C).
Re-trying our test query, we now get:
?- lgtunit::quick_check(p(+difference_list(integer))).
* quick check test failure (at test 2 after 0 shrinks):
* p([0|A]-A)
false.
I.e. the dividelist2/3 predicate fails for a difference list with a single element. You can now use the difference list in the generated counter-example as a starting point for debugging:
?- dividelist2([0|A]-A, L1, L2).
A = [0|A],
L1 = _2540-_2540,
L2 = _2546-_2546 ;
false.
You can also use property-testing with your auxiliary predicates. Take the length_dl/2 predicate. We can compare it with another implementation of a predicate that computes the length of a difference list, e.g. the one in the Logtalk library, by defining another property:
q(DL) :-
difflist::length(DL, N),
length_dl(DL, N).
Testing it we get:
?- lgtunit::quick_check(q(+difference_list(integer))).
* quick check test failure (at test 3 after 0 shrinks):
* q([-113,446,892|A]-A)
false.
Effectively, using the counter.example, we get:
?- length_dl([-113,446,892|A]-A, N).
A = [-113, 446, 892|A],
N = 0.
Hope that this insight helps in fixing your code.
Ok, my idea can work, but seems somewhat inelegant. We'll begin with a handy utility that'll turn a list into a difference list:
list_dl([], W-W).
list_dl([H|T1], [H|T2]-W) :-
list_dl(T1, T2-W).
Now we want a predicate to take the first and last element from the difference list. The case where there's only one element left will need to be handled differently, so we'll make that one unique.
head_last(Head, Head, DL-Hole, one) :-
once(append([Head|_], [Last, Hole], DL)),
var(Last), !.
head_last(Head, Last, DL-Hole, New) :-
once(append([Head|Mid], [Last, Hole], DL)),
list_dl(Mid, New).
Now we can create our recursive split and reverse predicate, which has 3 base cases:
splitrev(W-W, [], []) :- var(W), !. % Empty base case.
splitrev(DL, [V|[]], []) :- head_last(V, V, DL, one).
splitrev(DL, [], [V|[]]) :- head_last(V, V, DL, one).
splitrev(DL, [Head|Front], [Last|Back]) :-
head_last(Head, Last, DL, Rest),
splitrev(Rest, Front, Back).
Unfortunately it's much easier to add an element to the back of a difference list than it is to get an element from the back, plus getting that element closed the hole in the list. Therefore I think a different strategy would be better.

Append list of lists elements in Prolog

I'm learning Prolog for about a week, so I'm a newbie.
I'm trying to do a function, that appends, the elements of a list of lists.
So the input would be: [ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ].
And the output would be : [ [a,b,c,j,k,l,s,t,u], [g,h,i,m,n,o,v,w,x] ].
Or
Input: [ [[a,b], [c,d]], [[e,f], [g,h]], [[i,j],[k,l]] ].
Output: [ [a,b,e,f,i,j], [c,d,g,h,k,l] ].
It would be important, that it has to work with a lot of elements, not only 3.
I wrote this, but it only works with 2 elements, so i can only do it, with pairs.
merge([],[],[]).
merge(L1,[],L1).
merge([H1|T1],[H2|T2],LL):-
append(H1, H2, HE),
merge(T1,T2,TE),
append([HE], TE, LL).
If I understand your question correctly...
First, if you know that your input has exactly two levels of nesting in it, and if your Prolog had higher-order predicates for mapping and for folding, and if you could compose them, you could simply write:
merge_foldl([], []).
merge_foldl([X|Xs], R) :-
reverse([X|Xs], [Y|Ys]),
foldl(maplist(append), Ys, Y, R).
This works as expected for SWI-Prolog.
Here it is with your two examples:
?- merge_foldl([ [[a,b,c],[g,h,i]], [[j,k,l],[m,n,o]], [[s,t,u],[v,w,x]] ], R).
R = [[a, b, c, j, k, l, s, t, u], [g, h, i, m, n, o, v, w, x]].
?- merge_foldl([ [[a,b], [c,d], [e,f]], [[g,h], [i,j], [k,l]] ], R).
R = [[a, b, g, h], [c, d, i, j], [e, f, k, l]].
If you don't have access to neither foldr nor foldl, you would have to hardcode the folding:
merge([], []).
merge([X|Xs], Result) :-
merge_maplist(Xs, X, Result).
merge_maplist([], Result, Result).
This is not all, but it says that if you are at the end of the list of lists, the last element is the result.
Now you have to define the step where you append to the front of each sublist. This is easier with maplist:
merge_maplist([X|Xs], Prev, Result) :-
merge_maplist(Xs, X, Result0),
maplist(append, Prev, Result0, Result).
Note that here we are "emulating" a right fold by using a non-tail-recursive definition: we are doing the appending in reverse, after the recursive step. For a tail-recursive definition (identical to hard-coded left fold), you would have to reverse the original list first!
So you keep on peeling off one list of lists from your input until you are done. Then, you use maplist to apply append/3 to each pair of lists from the previous element and the result so far, to get the final result.
If you don't have access to maplist either, you'd have to hardcode the mapping as well. For the three arguments that append/3 takes:
map_append([], [], []).
map_append([X|Xs], [Y|Ys], [Z|Zs]) :-
append(X, Y, Z),
map_append(Xs, Ys, Zs).
and your merge/2 and merge_/3 become:
merge([], []).
merge([X|Xs], Result) :-
merge_(Xs, X, Result).
merge_([], Result, Result).
merge_([X|Xs], Prev, Result) :-
merge_(Xs, X, Result0),
map_append(Prev, Result0, Result).
This is a lot of code for something that can be solved quite nicely if you have higher-order predicates.

Find all positions of a value in a list in Prolog

My assignment is this: Write a program that reads an integer x and a list of integers L; then locate the list of all positions of x into L, and return the resulting list. For example, for x=2 and L=[1,2,3,4,2,5,2,6] the program should return the list R=[2,5,7].
So far, I've been able to write an indexOf predicate:
indexOf([E|_], E, 1).
indexOf([_|T], E, I) :- indexOf(T, E, I2), I is I2 + 1.
However, this doesn't "return" a list. So:
indexOf([a,b,c,a,d], a, R).
R = 1;
R = 4
I'd like to do something like this:
findAll([a,b,c,a,d], a, R).
R = [1, 4]
But I'm not sure how to collect the values into a list.
This is a school assignment, so I'd appreciate just a nudge in the right direction.
A nudge: you find the indices, but you don't collect them.
indices(List, E, Is) :-
indices_1(List, E, Is, 1).
For an empty list, the list of indices is empty,
and the element doesn't matter
indices_1([], _, [], _).
If the element is like the head, collect the index.
indices_1([E|Xs], E, [I|Is], I) :-
I1 is I + 1,
indices_1(Xs, E, Is, I1).
This needs another clause to work properly.
EDIT:
One way to do it would be:
indices_1([X|Xs], E, Is, I) :- dif(X, E),
I1 is I + 1,
indices_1(Xs, E, Is, I1).
In the previous clause, the head of the list and the Element are unified. In this clause, they are explicitly different. This means that only one of the two clauses can be true for an element of the list in the first arguemnt.
EDIT:
Another way to do that is to use findall and nth1:
indices(List, E, Is) :-
findall(N, nth1(N, List, E), Is).

How to find a path with limited depth in graph?

link(a, b).
link(a, c).
link(b, c).
link(b, e).
link(c, f).
link(c, g).
link(c, d).
symlink(F1, F2) :-
link(F1, F2).
symlink(F1, F2) :-
link(F2, F1).
profile(a,box). %Tag it is the same as box for a.
find(Start, Tag, Rpath) :
find2(Start, Tag, 0, [], Rpath).
find2(Step, Tag, Count, Path, Rpath) :-
C is Count +1,
C < 5,
symlink(Step, A),
compat(A,Tag), % Compatible means the distance between the tag of A
% and the Tag that is given as argument should be maximum 1.
append(Path, [A|E],Rpath), %This part i want make my final path in Rpath.
not(member(Step,Path)),
find2(A, Tag, C, [Step|Path], Rpath).
You are quite close to a working predicate here. I've include a code snippet that hopefully solves a few of the small mistakes you make. Notice that find/3 is the predicate you would actually use (from the outside), a so-called wrapper clause.
find/4 works in the following way:
The first clause is only used to detect a transgression of the maximum depth.
The second clause is only used to detect a goal node, i.e. one that matches the given tag.
The third clause does the real job of finding a symmetric link in the graph.
Some small things to note:
Renamed symlink/2 to symmetric_link/2 to avoid confusion with symbolic links.
Used \+ instead of not for negation (the former is more common I believe).
Used tag/2 for tagging nodes, not profile/2 to avoid confusion with the act of profiling/analyzing code performance.
Code snippet:
link(a, b).
link(a, c).
link(b, c).
link(b, d).
link(b, e).
link(c, f).
link(c, g).
link(c, d).
tag(a, box).
symmetric_link(F1, F2) :-
link(F1, F2).
symmetric_link(F1, F2) :-
link(F2, F1).
maximum_depth(5).
find(Start, End, Path):-
find(Start, End, 0, [Start], Path).
find(_, _, Depth, _, _):-
maximum_depth(Max),
Depth > Max, !,
fail.
find(Node, Tag, _, _, [Node]):-
tag(Node, Tag), !.
find(Node1, Tag, Depth1, History, [Node1|Path]):-
symmetric_link(Node1, Node2),
\+ memberchk(Node2, History),
Depth2 is Depth1 + 1,
find(Node2, Tag, Depth2, [Node2|History], Path).
Example of usage:
?- find(g, box, Path).
Path = [g, c, d, b, a] ;
Path = [g, c, a] ;
Path = [g, c, b, a].
I have not fully tested this predicate and would advice you to write a unit test for these kinds of predicates. I use plUnit for this, which runs on SWI-Prolog and SICStus Prolog, but there may be others as well.
Hope this helps!

Prolog separating lists

Hello is there any way to separate a list in Prolog into two other lists, the first includes everything before an element and the second everything after the element. For example
A=[1,2,3,5,7,9,0] and element=5
the two lists should be
A1=[1,2,3] and A2=[7,9,0]
I don't care about finding the element just what to do next
it's easy as
?- Elem = 5, A = [1,2,3,5,7,9,0], append(A1, [Elem|A2], A).
edit to explain a bit...
append/3 it's a relation among 3 lists.
It's general enough to solve any concatenation on proper lists - when not there are circular arguments.
The comparison it's a plain unification, that take place on second argument. That must be a list beginning with Elem. Prolog list constructor syntax is [Head|Tail]. To make unification succeed, Elem must match the Head.
Here's an alternative method, illustrating how to handle it with list recursion:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
X \== E,
split(T, E, LL, LR).
Or better, if your Prolog supports dif/2:
split([E|T], E, [], T).
split([X|T], E, [X|LL], LR) :-
dif(X, E),
split(T, E, LL, LR).
Examples:
| ?- split([1,2,3,4,5], 3, L, R).
L = [1,2]
R = [4,5] ? ;
no
| ?- split([1,2,3,4,5], 5, L, R).
L = [1,2,3,4]
R = [] ? ;
(1 ms) no
| ?- split([1,2,3,4,5], 1, L, R).
L = []
R = [2,3,4,5] ? ;
no
| ?-
It is a sort of specialized twist on append/3 as CapelliC showed.

Resources