Related
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
I'm looking for a predicate that works as this:
?- subset([1,2,3], X).
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [2, 3] ;
...
I've seen some subset implementations, but they all work when you want to check if one list is a subset of the another, not when you want to generate the subsets. Any ideas?
Here goes an implementation:
subset([], []).
subset([E|Tail], [E|NTail]):-
subset(Tail, NTail).
subset([_|Tail], NTail):-
subset(Tail, NTail).
It will generate all the subsets, though not in the order shown on your example.
As per commenter request here goes an explanation:
The first clause is the base case. It states that the empty list is a subset of the empty list.
The second and third clauses deal with recursion. The second clause states that if two lists have the same Head and the tail of the right list is a subset of the tail of the left list, then the right list is a subset of the left list.
The third clause states that if we skip the head of the left list, and the right list is a subset of the tail of the left list, then the right list is a subset of the left list.
The procedure shown above generates ordered sets. For unordered sets you might use permutation/3:
unordered_subset(Set, SubSet):-
length(Set, LSet),
between(0,LSet, LSubSet),
length(NSubSet, LSubSet),
permutation(SubSet, NSubSet),
subset(Set, NSubSet).
On http://www.probp.com/publib/listut.html you will find an implementation of a predicate called subseq0 that does what you want to:
subseq0(List, List).
subseq0(List, Rest) :-
subseq1(List, Rest).
subseq1([_|Tail], Rest) :-
subseq0(Tail, Rest).
subseq1([Head|Tail], [Head|Rest]) :-
subseq1(Tail, Rest).
A short explanation: subseq0(X, Y) checks whether Y is a subset subsequence of X, while subseq1(X, Y) checks whether Y is a proper subset subsequence of X.
Since the default representation of a set is a list with unique elements, you can use it to get all subsets as in the following example:
?- subseq0([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 3] ;
X = [3] ;
X = [] ;
X = [2] ;
X = [1, 3] ;
X = [1] ;
X = [1, 2] ;
false.
Set is a collection of distinct objects by definition. A subset procedure shouldn't care about the order of elements in the set(in the arguments). A proper solution(swi prolog) may look like:
subset(_, []).
subset([X|L], [A|NTail]):-
member(A,[X|L]),
subset(L, NTail),
not(member(A, NTail)).
For the question ?- subset([1,2,3], E) it will generate:
E = [] ;
E = [1] ;
E = [1, 2] ;
E = [1, 2, 3] ;
E = [1, 3] ;
E = [2] ;
E = [2, 3] ;
E = [3] ;
E = [3, 2] ;
false.
Hope it will help!
we can also test by deleting subset's item from the super set.
% to delete : an item can be deleted it its in the head or in the tail of a list
delete(I,[I|L],L).
delete(I,[H|L],[H|NL]) :- delete(I,L,NL).
% an [] is an item of an set.A set is a subset of we can recursively delete its head item from the super set.
subset(_,[]).
subset(S,[I|SS]) :- delete(I,S,S1), subset(S1,SS).
example:
subset([a,b,c],S).
S = []
S = [a]
S = [a, b]
S = [a, b, c]
S = [a, c]
S = [a, c, b]
S = [b]
S = [b, a]
S = [b, a, c]
S = [b, c]
S = [b, c, a]
S = [c]
S = [c, a]
S = [c, a, b]
S = [c, b]
S = [c, b, a]
subset([a,b,a,d,e],[a,e]).
1true
append([],L,L).
append([H|T],L,[H|L1]):-append(T,L,L1).
subset([X|T],[X|L]) :-subset(T,L).
subset([X|T],[G|L]) :-subset([X],L),append(L2,[X|L3],[G|L]),append(L2,L3,L4),subset(T,L4).
subset([],_).
----------------------------------------------
?- subset([1,2],[1,2]).
yes
?- subset([1,2],[2,1]).
yes
?- subset([1,1],[1,2]).
no
?- subset(D,[1,2]).
D = [1,2] ;
D = [1] ;
D = [2,1] ;
D = [2] ;
D = '[]' ;
no