Related
I am a new learner for prolog. Here is the question of our workshop, I have no idea where start it.
Would really appreciate any help with this.
sublist(Xs, Ys)
This holds when Xs is a list containing some of the elements of Ys, in the same order they appear in the list Ys. This should work whenever Ys is a proper list. For example:
sublist([a,c,e],[a,b,c,d,e]) should succeed.
sublist([a,e,c],[a,b,c,d,e]) should fail.
sublist([a,X,d],[a,b,c,d,e]) should have the two solutions X=b and X=c.
sublist(X,[a,b,c]) should have the eight solutions X=[]; X=[c]; X=[b]; X=[b,c]; X=[a]; X=[a,c]; X=[a,b]; and X=[a,b,c].
My implementation:
sublist([], []).
sublist([H| Rest1], [H| Rest2]) :-sublist(Rest1, Rest2).
sublist(H, [_ | Rest2]) :-sublist(H, Rest2).
Examples:
?- sublist(X,[a,b,c]).
X = [a, b, c] ;
X = [a, b] ;
X = [a, c] ;
X = [a] ;
X = [b, c] ;
X = [b] ;
X = [c] ;
X = [].
?- sublist([a,c,e],[a,b,c,d,e]) .
true ;
false.
?- sublist([a,e,c],[a,b,c,d,e]) .
false.
?- sublist([a,X,d],[a,b,c,d,e]).
X = b ;
X = c ;
false.
Please note that a sublist needs its elements to be consecutive in the original list.
With that definition it would be easier to define a sublist through defining auxiliary predicates prefix and suffix, examples are taken from Shapiro's book:
prefix([], _).
prefix([X|Xs], [X,Ys]) :-
prefix(Xs, Ys).
suffix(Xs, Xs).
suffix(Xs, [_|Ys]) :-
suffix(Xs, Ys).
– and then it is just a matter of defining a sublist as either a suffix of a prefix:
sublist(Xs, Ys) :-
prefix(Ps, Ys),
suffix(Xs, Ps).
Result:
?- sublist(X, [1,2,3]).
X = [] ;
X = [1] ;
X = [] ;
X = [1, 2] ;
X = [2] ;
X = [] ;
X = [1, 2, 3] ;
X = [2, 3] ;
X = [3] ;
X = [] ;
false.
– or as a prefix of a suffix:
sublist(Xs, Ys) :-
prefix(Xs, Ss),
suffix(Ss, Ys).
Result:
?- sublist(X, [1,2,3]).
X = [] ;
X = [] ;
X = [] ;
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1, 2] ;
X = [2, 3] ;
X = [1, 2, 3] ;
But one could also do a recursive definition:
sublist(Xs, Ys) :-
prefix(Xs, Ys).
sublist(Xs, [_|Ys]) :-
sublist(Xs, Ys).
Result:
?- sublist(X, [1,2,3]).
X = [] ;
X = [1] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [] ;
X = [2] ;
X = [2, 3] ;
X = [] ;
X = [3] ;
X = [] ;
false.
I am trying to compute arrangements of K elements in Prolog, where the sum of their elements is equal to a given S. So, I know that arrangements can be computed by finding the combinations and then permute them. I know how to compute combinations of K elements, something like:
comb([E|_], 1, [E]).
comb([_|T], K, R) :-
comb(T, K, R).
comb([H|T], K, [H|R]) :-
K > 1,
K1 is K-1,
comb(T, K1, R).
The permutations of a list, having the property that the sum of their elements is equal to a given S, I know to compute like this:
insert(E, L, [E|L]).
insert(E, [H|T], [H|R]) :-
insert(E, T, R).
perm([], []).
perm([H|T], P) :-
perm(T, R),
insert(H, R, P).
sumList([], 0).
sumList([H], H) :-
number(H).
sumList([H|Tail], R1) :-
sumList(Tail, R),
R1 is R+H.
perms(L, S, R) :-
perm(L, R),
sumList(R, S1),
S = S1.
allPerms(L, LP) :-
findall(R, perms(L,R), LP).
The problem is that I do not know how to combine them, in order to get the arrangements of K elements, having the sum of elements equal to a given S. Any help would be appreciated.
Use clpfd!
:- use_module(library(clpfd)).
Using SWI-Prolog 7.3.16 we query:
?- length(Zs,4), Zs ins 1..4, sum(Zs,#=,7), labeling([],Zs).
Zs = [1,1,1,4]
; Zs = [1,1,2,3]
; Zs = [1,1,3,2]
; Zs = [1,1,4,1]
; Zs = [1,2,1,3]
; Zs = [1,2,2,2]
; Zs = [1,2,3,1]
; Zs = [1,3,1,2]
; Zs = [1,3,2,1]
; Zs = [1,4,1,1]
; Zs = [2,1,1,3]
; Zs = [2,1,2,2]
; Zs = [2,1,3,1]
; Zs = [2,2,1,2]
; Zs = [2,2,2,1]
; Zs = [2,3,1,1]
; Zs = [3,1,1,2]
; Zs = [3,1,2,1]
; Zs = [3,2,1,1]
; Zs = [4,1,1,1].
To eliminate "redundant modulo permutation" solutions use chain/2:
?- length(Zs,4), Zs ins 1..4, chain(Zs,#=<), sum(Zs,#=,7), labeling([],Zs).
Zs = [1,1,1,4]
; Zs = [1,1,2,3]
; Zs = [1,2,2,2]
; false.
I use SWI-Prolog.
You can write that
:- use_module(library(lambda)).
arrangement(K, S, L) :-
% we have a list of K numbers
length(L, K),
% these numbers are between 1 (or 0) and S
maplist(between(1, S), L),
% the sum of these numbers is S
foldl(\X^Y^Z^(Z is X+Y), L, 0, S).
The result
?- arrangement(5, 10, L).
L = [1, 1, 1, 1, 6] ;
L = [1, 1, 1, 2, 5] ;
L = [1, 1, 1, 3, 4] ;
L = [1, 1, 1, 4, 3] .
You can use also a CLP(FD) library.
Edited after the remark of #repeat.
This response is similar to response of #repeat
predicates that below are implemented using the SICStus 4.3.2 tool
after simple modification of gen_list(+,+,?)
edit Code
gen_list(Length,Sum,List) :- length(List,Length),
domain(List,0,Sum),
sum(List,#=,Sum),
labeling([],List),
% to avoid duplicate results
ordered(List).
Test
| ?- gen_list(4,7,L).
L = [0,0,0,7] ? ;
L = [0,0,1,6] ? ;
L = [0,0,2,5] ? ;
L = [0,0,3,4] ? ;
L = [0,1,1,5] ? ;
L = [0,1,2,4] ? ;
L = [0,1,3,3] ? ;
L = [0,2,2,3] ? ;
L = [1,1,1,4] ? ;
L = [1,1,2,3] ? ;
L = [1,2,2,2] ? ;
no
I don't think that permutations could be relevant for your problem. Since the sum operation is commutative, the order of elements should be actually irrelevant. So, after this correction
sumList([], 0).
%sumList([H], H) :-
% number(H).
sumList([H|Tail], R1) :-
sumList(Tail, R),
R1 is R+H.
you can just use your predicates
'arrangements of K elements'(Elements, K, Sum, Arrangement) :-
comb(Elements, K, Arrangement),
sumList(Arrangement, Sum).
test:
'arrangements of K elements'([1,2,3,4,5,6],3,11,A).
A = [2, 4, 5] ;
A = [2, 3, 6] ;
A = [1, 4, 6] ;
false.
You already know how to use findall/3 to get all lists at once, if you need them.
With the following piece of code in Prolog I managed to extract every third item from a list:
third([_,_,Z|L], Z).
third([_,_,C|L], Y) :-
third(L, Y).
However, I still need to append every item that I am extracting to a new list, and finally create a list with only "every third" items.
I would appreciate any hint or help!
Thank you.
How about doing it like this?
list_thirds([] , []).
list_thirds([_] , []).
list_thirds([_,_] , []).
list_thirds([_,_,E|Es], [E|Xs]) :-
list_thirds(Es, Xs).
Sample queries using SICStus Prolog 4.3.2:
| ?- list_thirds([], Xs).
Xs = [] ? ;
no
| ?- list_thirds([a,b,c], Xs).
Xs = [c] ? ;
no
| ?- list_thirds([a,b,c,d,e,f], Xs).
Xs = [c,f] ? ;
no
| ?- list_thirds([a,b,c,d,e,f,g], Xs).
Xs = [c,f] ? ;
no
How about going the "other direction"?
| ?- list_thirds(List, [x,y]).
List = [_A,_B,x,_C,_D,y] ? ;
List = [_A,_B,x,_C,_D,y,_E] ? ;
List = [_A,_B,x,_C,_D,y,_E,_F] ? ;
no % terminates universally
Last, we look at the answer sequence we get from the most general query:
| ?- list_thirds(Es, Xs).
Es = [] , Xs = [] ? ;
Es = [_A] , Xs = [] ? ;
Es = [_A,_B] , Xs = [] ? ;
Es = [_A,_B,_C] , Xs = [_C] ? ;
Es = [_A,_B,_C,_D] , Xs = [_C] ? ;
Es = [_A,_B,_C,_D,_E] , Xs = [_C] ? ;
Es = [_A,_B,_C,_D,_E,_F], Xs = [_C,_F] ? ;
...
With SWI-Prolog, and module lambda.pl, you can write
:- use_module(library(lambda)).
third(In, Out) :-
foldl(\X^Y^Z^(Y=[N,L],
( N = 2
-> append(L, [X], NL),
Z = [0,NL]
; N1 is N+1,
Z = [N1, L])),
In, [0, []], [_, Out]).
With same queries :
?- third([1,2,3,4,5,6,7,8,9,10], Out).
Out = [3, 6, 9].
?- third(X, [3,6,9]).
X = [_G103, _G180, 3, _G352, _G438, 6, _G613, _G699, 9] ;
X = [_G103, _G180, 3, _G352, _G438, 6, _G613, _G699, 9|...] .
?- third(X, Y).
X = Y, Y = [] ;
X = [_G87231],
Y = [] ;
X = [_G87231, _G87317],
Y = [] ;
X = [_G87231, _G87317, _G87403],
Y = [_G87403] ;
X = [_G87231, _G87317, _G87403, _G87489],
Y = [_G87403] ;
X = [_G87231, _G87317, _G87403, _G87489, _G87575],
Y = [_G87403] ;
X = [_G87231, _G87317, _G87403, _G87489, _G87575, _G87661],
Y = [_G87403, _G87661] .
There's a DCG approach that would also work, analogous to #repeat's answer:
thirds([]) --> [].
thirds([]) --> [_].
thirds([]) --> [_,_].
thirds([X|T]) --> [_,_,X], thirds(T).
Or more concisely (thanks #repeat):
thirds([]) --> [] | [_] | [_,_].
thirds([X|T]) --> [_,_,X], thirds(T).
Called as follows:
| ?- phrase(thirds(T), [a,b,c,d,e,f,g,h]).
T = [c,f] ? a
no
| ?- phrase(thirds(T), L).
L = []
T = [] ? ;
L = [_]
T = [] ? ;
L = [_,_]
T = [] ? ;
L = [_,_,A]
T = [A] ? ;
L = [_,_,A,_]
T = [A] ? ;
...
This will work:
bagof(Third,third(List,Third),Result).
This collects all items Third such that Third is third in List; and binds the list of them to Result.
For more on bag, see http://www.swi-prolog.org/pldoc/doc_for?object=bagof/3 .
I am currently using this in my Prolog program:
sublist(X, L) :- append(_, S, L), append(X, _, S).
It will correctly list the sublists of a list if I call it like so,
?- sublist(A, [1, 2, 3]).
A = [] ;
A = [1] ;
A = [1, 2] ;
A = [1, 2, 3] ;
A = [] ;
A = [2] ;
A = [2, 3] ;
A = [] ;
A = [3] ;
A = [] ;
false.
I am looking to make a new function that will try all the shorter substrings first, so that it will come up with something more like
[1] ; [2] ; [3] ; [1, 2] ; [2, 3] ; [1, 2, 3].
Taking out the empty lists isn't vital, but would be preferred.
How about one of the following? Using SWI-Prolog we define the following rules:
Version 1
sublist_of([X|Xs], [E|Es]) :-
append(Ruler, _, [E|Es]), % ensure we get answers in ascending lengths
same_length(Ruler, [X|Xs]),
append([_,[X|Xs],_], [E|Es]).
Version 2
sublist_of__ver2([X|Xs], [E|Es]) :-
append(Ruler, _, [E|Es]), % ensure we get answers in ascending lengths
same_length(Ruler, [X|Xs]),
append([_,[X|Xs],_], [E|Es]).
Version 3a
sublist_of__ver3a([X|Xs], [E|Es]) :-
len1_len2_len12([X|Xs], _, [E|Es]),
append([_,[X|Xs],_], [E|Es]).
len1_len2_len12([], Ys, Zs) :-
same_length(Ys, Zs).
len1_len2_len12([_|Xs], Ys, [_|Zs]) :-
len1_len2_len12(Xs, Ys, Zs).
Version 3b
sublist_of__ver3b(Xs, Es) :-
Xs = [_|_],
len1_len2_len12(Xs, _, Es),
append([_,Xs,_], Es).
Sample query as given by the OP:
?- sublist_of__ver2(Xs, [1,2,3,4]).
Xs = [1 ]
; Xs = [ 2 ]
; Xs = [ 3 ]
; Xs = [ 4]
; Xs = [1,2 ]
; Xs = [ 2,3 ]
; Xs = [ 3,4]
; Xs = [1,2,3 ]
; Xs = [ 2,3,4]
; Xs = [1,2,3,4]
; false.
I swapped arguments order, for readability - please forgive me :)
sublist(L, S) :-
length(L, N),
between(1, N, M),
length(S, M),
append([_,S,_], L).
yields
?- sublist([a,b,c],S).
S = [a] ;
S = [b] ;
S = [c] ;
S = [a, b] ;
S = [b, c] ;
S = [a, b, c] ;
false.
with Sicstus-prolog it's easy with sublist(?X,+List). inside library(lists3).
code
% sublist(?Sub, +List)
% is true when all members of Sub are members of List
:- sublist(?,+) is nondet.
sublist(List, List).
sublist(Sub, [Head|Tail]) :- sublist_(Tail, Head, Sub).
:- sublist_/3 is nondet.
sublist_(Sub, _, Sub).
sublist_([Head|Tail], _, Sub) :- sublist_(Tail, Head, Sub).
sublist_([Head|Tail], X, [X|Sub]) :- sublist_(Tail, Head, Sub).
result
?- sublist(Y,[1,2,3]).
Y = [1,2,3] ? ;
Y = [2,3] ? ;
Y = [3] ? ;
Y = [] ? ;
Y = [2] ? ;
Y = [1,3] ? ;
Y = [1] ? ;
Y = [1,2] ? ;
no
I am trying to fill a list of given length N with numbers 1,2,3,...,N.
I thought this could be done this way:
create_list(N,L) :-
length(L,N),
forall(between(1,N,X), nth1(X,L,X)).
However, this does not seem to work. Can anyone say what I am doing wrong?
First things first: Use clpfd!
:- use_module(library(clpfd)).
In the following I present zs_between_and/3, which (in comparison to my previous answer) offers some more features.
For a start, let's define some auxiliary predicates first!
equidistant_stride([] ,_).
equidistant_stride([Z|Zs],D) :-
equidistant_prev_stride(Zs,Z,D).
equidistant_prev_stride([] ,_ ,_). % internal predicate
equidistant_prev_stride([Z1|Zs],Z0,D) :-
Z1 #= Z0+D,
equidistant_prev_stride(Zs,Z1,D).
Let's run a few queries to get a picture of equidistant_stride/2:
?- Zs = [_,_,_], equidistant_stride(Zs,D).
Zs = [_A,_B,_C], _A+D#=_B, _B+D#=_C.
?- Zs = [1,_,_], equidistant_stride(Zs,D).
Zs = [1,_B,_C], _B+D#=_C, 1+D#=_B.
?- Zs = [1,_,_], equidistant_stride(Zs,10).
Zs = [1,11,21].
So far, so good... moving on to the actual "fill list" predicate zs_between_and/3:
zs_between_and([Z0|Zs],Z0,Z1) :-
Step in -1..1,
Z0 #= Z1 #<==> Step #= 0,
Z0 #< Z1 #<==> Step #= 1,
Z0 #> Z1 #<==> Step #= -1,
N #= abs(Z1-Z0),
( fd_size(N,sup)
-> true
; labeling([enum,up],[N])
),
length(Zs,N),
labeling([enum,down],[Step]),
equidistant_prev_stride(Zs,Z0,Step).
A bit baroque, I must confess...
Let's see what features were gained---in comparison to my previous answer!
?- zs_between_and(Zs,1,4). % ascending consecutive integers
Zs = [1,2,3,4]. % (succeeds deterministically)
?- zs_between_and(Zs,3,1). % descending consecutive integers (NEW)
Zs = [3,2,1]. % (succeeds deterministically)
?- zs_between_and(Zs,L,10). % enumerates fairly
L = 10, Zs = [10] % both ascending and descenting (NEW)
; L = 9, Zs = [9,10]
; L = 11, Zs = [11,10]
; L = 8, Zs = [8,9,10]
; L = 12, Zs = [12,11,10]
; L = 7, Zs = [7,8,9,10]
...
?- L in 1..3, zs_between_and(Zs,L,6).
L = 3, Zs = [3,4,5,6]
; L = 2, Zs = [2,3,4,5,6]
; L = 1, Zs = [1,2,3,4,5,6].
Want some more? Here we go!
?- zs_between_and([1,2,3],From,To).
From = 1, To = 3
; false.
?- zs_between_and([A,2,C],From,To).
A = 1, From = 1, C = 3, To = 3 % ascending
; A = 3, From = 3, C = 1, To = 1. % descending
I don't have a prolog interpreter available right now, but wouldn't something like...
isListTo(N, L) :- reverse(R, L), isListFrom(N, R).
isListFrom(0, []).
isListFrom(N, [H|T]) :- M is N - 1, N is H, isListFrom(M, T).
reverse can be done by using e.g. http://www.webeks.net/prolog/prolog-reverse-list-function.html
So tracing isListTo(5, [1, 2, 3, 4, 5])...
isListTo(5, [1, 2, 3, 4, 5])
<=> isListFrom(5, [5, 4, 3, 2, 1])
<=> 5 is 5 and isListFrom(4, [4, 3, 2, 1])
<=> 4 is 4 and isListFrom(3, [3, 2, 1])
<=> 3 is 3 and isListFrom(2, [2, 1])
<=> 2 is 2 and isListFrom(1, [1])
<=> 1 is 1 and isListFrom(0, [])
QED
Since PROLOG will not only evaluate truth, but find satisfying solutions, this should work. I know this is a vastly different approach from the one you are trying, and apologize if your question is specifically about doing loops in PROLOG (if that is the case, perhaps re-tag the question?).
Here's a logically pure implementation of predicate zs_from_to/3 using clpfd:
:- use_module(library(clpfd)).
zs_from_to([],I0,I) :-
I0 #> I.
zs_from_to([I0|Is],I0,I) :-
I0 #=< I,
I1 #= I0 + 1,
zs_from_to(Is,I1,I).
Let's use it! First, some ground queries:
?- zs_from_to([1,2,3],1,3).
true.
?- zs_from_to([1,2,3],1,4).
false.
Next, some more general queries:
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]
; false.
?- zs_from_to([1,2,3],From,To).
From = 1, To = 3.
Now, let's have some even more general queries:
?- zs_from_to(Zs,From,2).
Zs = [], From in 3..sup
; Zs = [2], From = 2
; Zs = [1,2], From = 1
; Zs = [0,1,2], From = 0
; Zs = [-1,0,1,2], From = -1
; Zs = [-2,-1,0,1,2], From = -2
...
?- zs_from_to(Zs,0,To).
Zs = [], To in inf.. -1
; Zs = [0], To = 0
; Zs = [0,1], To = 1
; Zs = [0,1,2], To = 2
; Zs = [0,1,2,3], To = 3
; Zs = [0,1,2,3,4], To = 4
...
What answers do we get for the most general query?
?- zs_from_to(Xs,I,J).
Xs = [], J#=<I+ -1
; Xs = [I], I+1#=_A, J#>=I, J#=<_A+ -1
; Xs = [I,_A], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, J#=<_B+ -1
; Xs = [I,_A,_B], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, _B+1#=_C, J#>=_B, J#=<_C+ -1
...
Edit 2015-06-07
To improve on above implementation of zs_from_to/3, let's do two things:
Try to improve determinism of the implementation.
Extract a more general higher-order idiom, and implement zs_from_to/3 on top of it.
Introducing the meta-predicates init0/3 and init1/3:
:- meta_predicate init0(2,?,?).
:- meta_predicate init1(2,?,?).
init0(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,0).
init1(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,1).
:- meta_predicate init_aux(?,2,+). % internal auxiliary predicate
init_aux([] , _ ,_ ).
init_aux([Z|Zs],P_2,I0) :-
call(P_2,I0,Z),
I1 is I0+1,
init_aux(Zs,P_2,I1).
Let's see init0/3 and init1/3 in action!
?- init0(=,5,Zs). % ?- numlist(0,4,Xs),maplist(=,Xs,Zs).
Zs = [0,1,2,3,4].
?- init1(=,5,Zs). % ?- numlist(1,5,Xs),maplist(=,Xs,Zs).
Zs = [1,2,3,4,5].
Ok, where do we go from here? Consider the following query:
?- init0(plus(10),5,Zs). % ?- numlist(0,4,Xs),maplist(plus(10),Xs,Zs).
Zs = [10,11,12,13,14].
Almost done! Putting it together, we define zs_from_to/2 like this:
z_z_sum(A,B,C) :- C #= A+B.
zs_from_to(Zs,I0,I) :-
N #= I-I0+1,
init0(z_z_sum(I0),N,Zs).
At last, let's see if determinism has improved!
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]. % succeeds deterministically
If I understood correctly, the built-in predicate numlist/3 would do.
http://www.swi-prolog.org/pldoc/man?predicate=numlist/3