Below code works for split_list/3:
split_list([], _, [[],[]]).
split_list(T, 0, [[],T]).
split_list([H|T], N, [[H|Y],Z]) :-
N1 is N-1,
split_list(T, N1, [Y,Z]).
For example:
?- split_list([a,s,d,f,g,h,j], 3, R).
R = [[a, s, d], [f, g, h, j]] . % observed answer
But, I want to convert split_list/3 to split/4:
?- split([a,s,d,f,g,h,j], 2, R1, R2).
R1 = [a,s], R2 = [d,f,g,h,j]. % expected answer
How can I get the answer that I want? Any suggestions? Thank you :)
Here's a straight-forward definition of split/4:
split(AsBs, N, As, Bs) :-
append(As, Bs, AsBs),
length(As, N).
Sample query as given by the OP:
?- split([a,s,d,f,g,h,j], 2, R1, R2).
R1 = [a,s], R2 = [d,f,g,h,j]
; false.
How about a generalisation of above query?
?- split([a,s,d,f,g,h,j], I, R1, R2).
I = 0, R1 = [], R2 = [a,s,d,f,g,h,j]
; I = 1, R1 = [a], R2 = [s,d,f,g,h,j]
; I = 2, R1 = [a,s], R2 = [d,f,g,h,j]
; I = 3, R1 = [a,s,d], R2 = [f,g,h,j]
; I = 4, R1 = [a,s,d,f], R2 = [g,h,j]
; I = 5, R1 = [a,s,d,f,g], R2 = [h,j]
; I = 6, R1 = [a,s,d,f,g,h], R2 = [j]
; I = 7, R1 = [a,s,d,f,g,h,j], R2 = [].
In this answer, we use clpfd constraints for expressing declarative integer arithmetic.
:- use_module(library(clpfd)).
We define split/4 by combining the code of append/3 and the code1 of fd_length/2.
Note the parallels of fd_length/2 with split/4 and of fd_length/3 with split_/5:
split(Zs, N, Xs, Ys) :- %% fd_length(Xs, N) :-
N #>= 0, %% N #>= 0,
split_(Xs, N,0, Ys, Zs). %% fd_length(Xs, N,0).
%%
split_([], N,N0, Zs, Zs) :- %% fd_length([], N,N0) :-
N #= N0. %% N #= N0.
split_([X|Xs], N,N0, Ys, [X|Zs]) :- %% fd_length([_|Xs], N,N0) :-
N1 #= N0+1, %% N1 #= N0+1,
N #>= N1, %% N #>= N1,
split_(Xs, N,N1, Ys, Zs). %% fd_length(Xs, N,N1).
Now, if look at the code of split_/5 again, then we can see the code of append/3 in it:
%% split_([], N,N0, Zs, Zs) :- %% append([], Zs, Zs).
%% N #= N0, %%
%% split_([X|Xs], N,N0, Ys, [X|Zs]) :- %% append([X|Xs], Ys, [X|Zs]) :-
%% N1 #= N0+1, %%
%% N #>= N1, %%
%% split_(Xs, N,N1, Ys, Zs). %% append(Xs, Ys, Zs).
Sample queries:
?- N = 2, split(XsYs, N, Xs, Ys).
XsYs = [_A,_B|Ys], N = 2, Xs = [_A,_B]
; false.
?- N = 2, XsYs = [a,b,c,d,e], split(XsYs, N, Xs, Ys).
XsYs = [a,b,c,d,e], N = 2, Xs = [a,b], Ys = [c,d,e]
; false.
?- XsYs = [a,s,d,f,g,h,j], split(XsYs, N, Xs, Ys).
XsYs = [a,s,d,f,g,h,j], N = 0, Xs = [] , Ys = [a,s,d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 1, Xs = [a] , Ys = [s,d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 2, Xs = [a,s] , Ys = [d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 3, Xs = [a,s,d] , Ys = [f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 4, Xs = [a,s,d,f] , Ys = [g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 5, Xs = [a,s,d,f,g] , Ys = [h,j]
; XsYs = [a,s,d,f,g,h,j], N = 6, Xs = [a,s,d,f,g,h] , Ys = [j]
; XsYs = [a,s,d,f,g,h,j], N = 7, Xs = [a,s,d,f,g,h,j], Ys = []
; false.
?- Xs = [a,b,c], Ys = [d,e,f], split(XsYs, N, Xs, Ys).
XsYs = [a,b,c,d,e,f], N = 3, Xs = [a,b,c], Ys = [d,e,f].
Footnote 1: To accentuate the parallels, the program text of fd_length/2 (optimized variant) was altered slightly:
L was replaced by Xs,
the argument pair N, N0 by N,N0, and
(is)/2 by (#=)/2.
if you are interested in preserving the semantic of your existing definition, you can reuse it in this way
split_list(L,N,R1,R2) :- split_list(L,N,[R1,R2]).
Related
I have to write a predicate: double(X,Y) to be true when Y is the list consisting of each element of X
repeated twice (e.g. double([a,b],[a,a,b,b]) is true).
I ended with sth like this:
double([],[]).
double([T],List) :- double([H|T],List).
double([H|T],List) :- count(H, List, 2).
Its working fine for lists like [a,a,b] but it shouldnt... please help.
And i need help with another predicate: repeat(X,Y,N) to be true when Y is the list consisting of each element of X
repeated N times (e.g. repeat([a,b], [a,a,a,b,b,b],3) is true).
double([],[]).
double([I|R],[I,I|RD]) :-
double(R,RD).
Here's how you could realize that "repeat" predicate you suggested in the question:
:- use_module(library(clpfd)).
Based on if_/3 and (=)/3 we define:
each_n_reps([E|Es], N) :-
aux_n_reps(Es, E, 1, N).
aux_n_reps([], _, N, N). % internal auxiliary predicate
aux_n_reps([E|Es], E0, N0, N) :-
if_(E0 = E,
( N0 #< N, N1 #= N0+1 ), % continue current run
( N0 #= N, N1 #= 1 )), % start new run
aux_n_reps(Es, E, N1, N).
Sample queries1 using SICStus Prolog 4.3.2:
?- each_n_reps(Xs, 3).
Xs = [_A,_A,_A]
; Xs = [_A,_A,_A,_B,_B,_B] , dif(_A,_B)
; Xs = [_A,_A,_A,_B,_B,_B,_C,_C,_C], dif(_A,_B), dif(_B,_C)
...
How about fair enumeration?
?- length(Xs, _), each_n_reps(Xs, N).
N = 1, Xs = [_A]
; N = 2, Xs = [_A,_A]
; N = 1, Xs = [_A,_B] , dif(_A,_B)
; N = 3, Xs = [_A,_A,_A]
; N = 1, Xs = [_A,_B,_C] , dif(_A,_B), dif(_B,_C)
; N = 4, Xs = [_A,_A,_A,_A]
; N = 2, Xs = [_A,_A,_B,_B], dif(_A,_B)
; N = 1, Xs = [_A,_B,_C,_D], dif(_A,_B), dif(_B,_C), dif(_C,_D)
...
How can [A,B,C,D,E,F] be split into runs of equal length?
?- each_n_reps([A,B,C,D,E,F], N).
N = 6, A=B , B=C , C=D , D=E , E=F
; N = 3, A=B , B=C , dif(C,D), D=E , E=F
; N = 2, A=B , dif(B,C), C=D , dif(D,E), E=F
; N = 1, dif(A,B), dif(B,C), dif(C,D), dif(D,E), dif(E,F).
Footnote 1: Answers were reformatted to improve readability.
Ok for repeat/3 i have sth like this:
repeat1([],[],0).
repeat1([A|B],[X|T],Y):- repeat1(B,T,Z), Y is 1+Z.
repeat1([A1|B],[X1|T], Z) :- A1\=A, X1\=X, repeat1(B,T,Z).
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.
I have written the following program, which calculates the longest non-decreasing sub-sequence of input array.
The sub-program to find the longest list from the list of lists is taken from stackoverflow (How do I find the longest list in a list of lists) itself.
:- dynamic lns/2.
:- retractall(lns(_, _)).
lns([], []).
lns([X|_], [X]).
lns([X|Xs], [X, Y|Ls]) :-
lns(Xs, [Y|Ls]),
X < Y,
asserta(lns([X|Xs], [X, Y|Ls])).
lns([_|Xs], [Y|Ls]) :-
lns(Xs, [Y|Ls]).
% Find the longest list from the list of lists.
lengths([], []).
lengths([H|T], [LH|LengthsT]) :-
length(H, LH),
lengths(T, LengthsT).
lengthLongest(ListOfLists, Max) :-
lengths(ListOfLists, Lengths),
max_list(Lengths, Max).
longestList(ListOfLists, Longest) :-
lengthLongest(ListOfLists, Len),
member(Longest, ListOfLists),
length(Longest, Len).
optimum_solution(List, Ans) :-
setof(A, lns(List, A), P),
longestList(P, Ans),
!.
I have used the Prolog dynamic database for memoization purpose.
Though the program with database runs slower than the program without database. Below are the comparative times between two runs.
?- time(optimum_solution([0, 8, 4, 12, 2, 10, 6, 14, 1, 9], Ans)).
% 53,397 inferences, 0.088 CPU in 0.088 seconds (100% CPU, 609577 Lips)
Ans = [0, 2, 6, 9]. %% With database
?- time(optimum_solution([0, 8, 4, 12, 2, 10, 6, 14, 1, 9], Ans)).
% 4,097 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 2322004 Lips)
Ans = [0, 2, 6, 9]. %% Without database. commented out the database usage.
I would like to know if I am using the dynamic database correctly. Thanks!
The issue is that as you are traversing the list building subsequences, you need to consider only prior subsequences whose last value is less than the value you have in-hand. The problem is that Prolog's first-argument indexing is doing an equality check, not a less-than check. So Prolog will have to traverse the entire store of lns/2, unifying the first parameter with a value so you can check to see if it's less and then backtracking to get the next.
Earlier, we presented a concise solution based on clpfd.
Now we aim at generality and efficiency!
:- use_module([library(clpfd), library(lists)]).
list_long_nondecreasing_subseq(Zs, Xs) :-
minimum(Min, Zs),
append(_, Suffix, Zs),
same_length(Suffix, Xs),
zs_subseq_taken0(Zs, Xs, Min).
zs_subseq_taken0([], [], _).
zs_subseq_taken0([E|Es], [E|Xs], E0) :-
E0 #=< E,
zs_subseq_taken0(Es, Xs, E).
zs_subseq_taken0([E|Es], Xs, E0) :-
zs_subseq_taken0_min0_max0(Es, Xs, E0, E, E).
zs_subseq_taken0_min0_max0([], [], E0, _, Max) :-
Max #< E0.
zs_subseq_taken0_min0_max0([E|Es], [E|Xs], E0, Min, Max) :-
E0 #=< E,
E0 #> Min #\/ Min #> E,
E0 #> Max #\/ Max #> E,
zs_subseq_taken0(Es, Xs, E).
zs_subseq_taken0_min0_max0([E|Es], Xs, E0, Min0, Max0) :-
Min #= min(Min0,E),
Max #= max(Max0,E),
zs_subseq_taken0_min0_max0(Es, Xs, E0, Min, Max).
Sample query using SICStus Prolog 4.3.2 (with pretty-printed answer sequence):
?- list_long_nondecreasing_subseq([0,8,4,12,2,10,6,14,1,9], Xs).
Xs = [0,8,12,14]
; Xs = [0,8,10,14]
; Xs = [0,4,12,14]
; Xs = [0,4,10,14]
; Xs = [0,4, 6,14]
; Xs = [0,4, 6, 9]
; Xs = [0,2,10,14]
; Xs = [0,2, 6,14]
; Xs = [0,2, 6, 9]
; Xs = [0,8,9]
; Xs = [0,4,9]
; Xs = [0,2,9]
; Xs = [0,1,9]
; false.
Note that the answer sequence of list_long_nondecreasing_subseq/2
may be a lot smaller than the one given by list_nondecreasing_subseq/2.
Above list [0,8,4,12,2,10,6,14,1,9] has 9 non-descending subsequences of length 4—all are "returned" by both list_nondecreasing_subseq/2 and
list_long_nondecreasing_subseq/2.
The respective answer sequence sizes, however, differ considerably: (65+9=74) vs (4+9=13).
TL;DR:
In this answer we implement a very general approach based on clpfd.
:- use_module(library(clpfd)).
list_nondecreasing_subseq(Zs, Xs) :-
append(_, Suffix, Zs),
same_length(Suffix, Xs),
chain(Xs, #=<),
list_subseq(Zs, Xs). % a.k.a. subset/2 by #gusbro
Sample query using SWI-Prolog 7.3.16:
?- list_nondecreasing_subseq([0,8,4,12,2,10,6,14,1,9], Zs).
Zs = [0,8,12,14]
; Zs = [0,8,10,14]
; Zs = [0,4,12,14]
; Zs = [0,4,10,14]
; Zs = [0,4,6,14]
; Zs = [0,4,6,9]
; Zs = [0,2,10,14]
; Zs = [0,2,6,14]
; Zs = [0,2,6,9]
; Zs = [0,8,12]
...
; Zs = [9]
; Zs = []
; false.
Note the particular order of the answer sequence!
The longest lists come first, followed by the lists a little smaller ... all the way down to singleton lists, and the empty list.
Keeps getting better!
In this answer we present list_long_nondecreasing_subseq__NEW/2, a drop-in replacement of list_long_nondecreasing_subseq/2—presented in this earlier answer.
Let's cut to the chase and define list_long_nondecreasing_subseq__NEW/2!
:- use_module([library(clpfd), library(lists), library(random), library(between)]).
list_long_nondecreasing_subseq__NEW(Zs, Xs) :-
minimum(Min, Zs),
append(Prefix, Suffix, Zs),
same_length(Suffix, Xs),
zs_skipped_subseq_taken0(Zs, Prefix, Xs, Min).
zs_skipped_subseq_taken0([], _, [], _).
zs_skipped_subseq_taken0([E|Es], Ps, [E|Xs], E0) :-
E0 #=< E,
zs_skipped_subseq_taken0(Es, Ps, Xs, E).
zs_skipped_subseq_taken0([E|Es], [_|Ps], Xs, E0) :-
zs_skipped_subseq_taken0_min0_max0(Es, Ps, Xs, E0, E, E).
zs_skipped_subseq_taken0_min0_max0([], _, [], E0, _, Max) :-
Max #< E0.
zs_skipped_subseq_taken0_min0_max0([E|Es], Ps, [E|Xs], E0, Min, Max) :-
E0 #=< E,
E0 #> Min #\/ Min #> E,
E0 #> Max #\/ Max #> E,
zs_skipped_subseq_taken0(Es, Ps, Xs, E).
zs_skipped_subseq_taken0_min0_max0([E|Es], [_|Ps], Xs, E0, Min0, Max0) :-
Min #= min(Min0,E),
Max #= max(Max0,E),
zs_skipped_subseq_taken0_min0_max0(Es, Ps, Xs, E0, Min, Max).
So ... does it still work as before? Let's run some tests and compare the answer sequences:
| ?- setrand(random(29251,13760,3736,425005073)),
between(7, 23, N),
nl,
write(n=N),
write(' '),
length(Zs, N),
between(1, 10, _),
maplist(random(1,N), Zs),
findall(Xs1, list_long_nondecreasing_subseq( Zs,Xs1), Xss1),
findall(Xs2, list_long_nondecreasing_subseq__NEW(Zs,Xs2), Xss2),
( Xss1 == Xss2 -> true ; throw(up) ),
length(Xss2,L),
write({L}),
false.
n=7 {3}{8}{3}{7}{2}{5}{4}{4}{8}{4}
n=8 {9}{9}{9}{8}{4}{4}{7}{5}{6}{9}
n=9 {9}{8}{5}{7}{10}{7}{9}{4}{5}{4}
n=10 {7}{12}{7}{14}{13}{19}{13}{17}{10}{7}
n=11 {14}{17}{7}{9}{17}{21}{14}{10}{10}{21}
n=12 {25}{18}{20}{10}{32}{35}{7}{30}{15}{11}
n=13 {37}{19}{18}{22}{20}{14}{10}{11}{8}{14}
n=14 {27}{9}{18}{10}{20}{29}{69}{28}{10}{33}
n=15 {17}{24}{13}{26}{32}{14}{22}{28}{32}{41}
n=16 {41}{55}{35}{73}{44}{22}{46}{47}{26}{23}
n=17 {54}{43}{38}{110}{50}{33}{48}{64}{33}{56}
n=18 {172}{29}{79}{36}{32}{99}{55}{48}{83}{37}
n=19 {225}{83}{119}{61}{27}{67}{48}{65}{90}{96}
n=20 {58}{121}{206}{169}{111}{66}{233}{57}{110}{146}
n=21 {44}{108}{89}{99}{149}{148}{92}{76}{53}{47}
n=22 {107}{137}{221}{79}{172}{156}{184}{78}{162}{112}
n=23 {163}{62}{76}{192}{133}{372}{101}{290}{84}{378}
no
All answer sequences were exactly identical! ... So, how about runtimes?
Let's run some more queries using SICStus Prolog 4.3.2 and pretty-print the answers!
?- member(N, [15,20,25,30,35,40,45,50]),
length(Zs, N),
_NN #= N*N,
maplist(random(1,_NN), Zs),
call_time(once(list_long_nondecreasing_subseq( Zs, Xs )), T1),
call_time(once(list_long_nondecreasing_subseq__NEW(Zs,_Xs2)), T2),
Xs == _Xs2,
length(Xs,L).
N = 15, L = 4, T1 = 20, T2 = 0, Zs = [224,150,161,104,134,43,9,111,76,125,50,68,202,178,148], Xs = [104,111,125,202] ;
N = 20, L = 6, T1 = 60, T2 = 10, Zs = [71,203,332,366,350,19,241,88,370,100,288,199,235,343,181,90,63,149,215,285], Xs = [71,88,100,199,235,343] ;
N = 25, L = 7, T1 = 210, T2 = 20, Zs = [62,411,250,222,141,292,276,94,548,322,13,317,68,488,137,33,80,167,101,475,475,429,217,25,477], Xs = [62,250,292,322,475,475,477] ;
N = 30, L = 10, T1 = 870, T2 = 30, Zs = [67,175,818,741,669,312,99,23,478,696,63,793,280,364,677,254,530,216,291,660,218,664,476,556,678,626,75,834,578,850], Xs = [67,175,312,478,530,660,664,678,834,850] ;
N = 35, L = 7, T1 = 960, T2 = 120, Zs = [675,763,1141,1070,299,650,1061,1184,512,905,139,719,844,8,1186,1006,400,690,29,791,308,1180,819,331,482,982,81,574,1220,431,416,357,1139,636,591], Xs = [299,650,719,844,1006,1180,1220] ;
N = 40, L = 9, T1 = 5400, T2 = 470, Zs = [958,1047,132,1381,22,991,701,1548,470,1281,358,32,605,1270,692,1020,350,794,1451,11,985,1196,504,1367,618,1064,961,463,736,907,1103,719,1385,1026,935,489,1053,380,637,51], Xs = [132,470,605,692,794,985,1196,1367,1385] ;
N = 45, L = 10, T1 = 16570, T2 = 1580, Zs = [1452,171,442,1751,160,1046,470,450,1245,971,1574,901,1613,1214,1849,1805,341,34,1923,698,156,1696,717,1708,1814,1548,463,421,1584,190,1195,1563,1772,1639,712,693,1848,1531,250,783,1654,1732,1333,717,1322], Xs = [171,442,1046,1245,1574,1613,1696,1708,1814,1848] ;
N = 50, L = 11, T1 = 17800, T2 = 1360, Zs = [2478,2011,2411,1127,1719,1286,1081,2042,1166,86,355,894,190,7,1973,1912,753,1411,1082,70,2142,417,1609,1649,2329,2477,1324,37,1781,1897,2415,1018,183,2422,1619,1446,1461,271,56,2399,1681,267,977,826,2145,2318,2391,137,55,1995], Xs = [86,355,894,1411,1609,1649,1781,1897,2145,2318,2391] ;
false.
Of course, the baroque approach shown in this answer simply cannot compete with "serious" suitable algorithms for determining the lis—still, getting 10X speedup always feels good:)
i m new in prolog that s why may be the question is easy for you but i couldnt find the answer. Can someone please help me.
I just want
a count function s.t
count([c,c,a,a,b,b,d,a,c,b,d,d,a], O).
it will returns the number of occurences of the list members.
O = [[a, 4], [b, 3], [c, 3], [d, 3]]
The following is based on my previous answer to "Remove duplicates in list (Prolog)" and on this previous answer to the question "Prolog union for A U B U C".
list_item_subtracted_count0_count/5 is derived from list_item_subtracted/3.
list_counts/2 is derived from list_setB/2, which were both defined here.
list_item_subtracted_count0_count([], _, [], N,N).
list_item_subtracted_count0_count([A|As], E, Bs1, N0,N) :-
if_(A = E,
( Bs1 = Bs , N1 is N0+1 ),
( Bs1 = [A|Bs], N1 = N0 )),
list_item_subtracted_count0_count(As, E, Bs, N1,N).
list_counts([], []).
list_counts([X|Xs], [X-N|Ys]) :-
list_item_subtracted_count0_count(Xs, X, Xs0, 1,N),
list_counts(Xs0, Ys).
Here's the query the OP gave:
?- list_counts([c,c,a,a,b,b,d,a,c,b,d,d,a], Xss).
Xss = [c-3,a-4,b-3,d-3]. % succeeds deterministically
Note the order of pairs X-N in Counts corresponds to the first occurrence of X in Xs:
?- list_counts([a,b,c,d], Xss).
Xss = [a-1,b-1,c-1,d-1].
?- list_counts([d,c,b,a], Xss).
Xss = [d-1,c-1,b-1,a-1].
Last, let's consider all possible lists Es—enumerated fairly with ascending lengths:
?- length(Es, N), list_counts(Es, Xss).
N = 0, Es = [], Xss = []
; N = 1, Es = [A], Xss = [A-1]
; N = 2, Es = [A,A], Xss = [A-2]
; N = 2, Es = [A,B], Xss = [A-1,B-1], dif(B,A)
; N = 3, Es = [A,A,A], Xss = [A-3]
; N = 3, Es = [A,A,B], Xss = [A-2,B-1], dif(B,A)
; N = 3, Es = [A,B,A], Xss = [A-2,B-1], dif(B,A)
; N = 3, Es = [B,A,A], Xss = [B-1,A-2], dif(A,B), dif(A,B)
; N = 3, Es = [A,B,C], Xss = [A-1,B-1,C-1], dif(C,A), dif(C,B), dif(B,A)
...
co(X,L) :- co(X,[],L).
co([],A,A).
co([X|Xs], A, L) :- p(X-Z,A,R), !, Z1 is Z+1, co(Xs, [X-Z1|R], L).
co([X|Xs], A, L) :- co(Xs, [X-1|A], L).
p(X-Y,[X-Y|R],R):- !.
p(X,[H|Y], [H|Z]) :- p(X,Y,Z).
I did not use very meaningful names on purpose. Try to understand what each one of the predicates does.
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