I have completed a haskell code to compute the delaunay triangulation of a given point set. However, now i am stuck as to how and what method needs to be completed in prolog
Haskell:
-- The type for a single point.
type Point a = (a,a)
-- The type for a pair of points.
type Pair a = (Point a, Point a)
-- The type for a triple of points.
type Triple a = (Point a, Point a, Point a)
-- Predicate for a triple of 3 points is in CCW order or not
isCCW :: Real a => Triple a -> Bool
isCCW ((x1, y1), (x2, y2), (x3, y3)) = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1) > 0
-- Convert a triple to a CCW triple
toCCW :: Real a => Triple a -> Triple a
toCCW (p1, p2, p3) = if (isCCW ((( p1, p2, p3 )))) then (p1, p2, p3)
else (p1, p3, p2)
-- Generate all pairs of points from a list of points.
-- Each pair should appear exactly once in the result.
pairsFromPoints :: Real a => [Point a] -> [Pair a]
pairsFromPoints [] = []
pairsFromPoints (x:xs) = map makePair xs ++ (pairsFromPoints xs)
where makePair y = (x,y)
-- Generate all unique CCW triples of points from a list of points
-- Each triple should appear exactly once in the result and be
-- CCW ordered.
triplesFromPoints :: Real a => [Point a] -> [Triple a]
triplesFromPoints [] = []
triplesFromPoints (x:xs) = map makeTriple (pairsFromPoints xs) ++ (triplesFromPoints xs)
where makeTriple (y,z) = toCCW(x,y,z)
And this is the Prolog code that I'm stuck on.
Prolog:
% concatenate(L1, L1, T) is true if and only if T is equal to the concatenation
% of lists L1 and L2.
%
concatenate(L1, L2, T).
% singletons(P, Q) is true if and only if Q is equivalent to the list obtained
% from P if each item in P is wrapped in "[" and "]" to create a singleton list.
%
singletons(P, Q).
% prefix_all(I, P, Q) is true if and only if P is a list of lists and Q is the
% list obtained by prepending I to each element in P.
%
prefix_all(I, P, Q).
% pairs_all(I, P, Q) is true if and only if Q is the list obtained by pairing I
% with each item in P.
%
pairs_all(I, P, Q).
% Predicate to test if three points are in counter-clockwise orientation.
%
is_ccw([[X1,Y1],[X2,Y2],[X3,Y3]]) :- (X2-X1)*(Y3-Y1)-(X3-X1)*(Y2-Y1) > 0.
% ccw(T, U) is true if and only if T and U are triples containing the same
% points and U is in counter-clockwise orientation.
%
ccw(T, U).
% ccw_triples(P, Q) is true if and only if Q is the list containing all the
% triples of points in the list P except arranged in ccw orientation.
%
ccw_triples(P, Q).
% pairs_of_points([H|T], Q) is true if and only if Q is a list containing all of
% the distinct pairs that can be made from the points in the list of points
% [H|T].
%
pairs_of_points([H|T], Q).
% triples_of_points([H|T], Q) is true if and only if Q is a list containing all
% of the distinct triples that can be made from the points in the list of points
% [H|T].
%
triples_of_points([H|T], X).
% is_delaunay_triangle(T, P) is true if and only if no point of the point set P
% is in the circle defined by the triple T (which here you may assume is in CCW
% orientation). This predicate is undefined if P is empty.
%
is_delaunay_triangle(T, P).
% delaunay_triangles(T, P, X) is true if and only if X is the subset of
% triangles from T that are Delaunay triangles for the point set P.
%
% HINT: Define this recursively on the list of triangles T.
%
delaunay_triangles(T, P, X).
% delaunay_triangulation(P, X) is true if and only if X is the list of Delaunay
% triangles for the point list P.
% HINT: Create temporary variables to describe all triples from P as well as all
% CCW triples from P. Use the predicates you've already defined above!
%
delaunay_triangulation(P, X).
I am not exactly sure what exactly the first four methods exactly mean, if someone could give me that as a start i would be content I'm not asking you to do my assignment either but any help would be greatly appreciated!
concatenate(L1, L1, T) is true if and only if T is equal to the concatenation of lists L1 and L2.
This should read concatenate(L1, L2, T) and is the standard append/3 predicate. It corresponds to Haskell's (++) function for list concatenation. For example, it should behave as follows:
?- concatenate([], [1, 2, 3], T).
T = [1, 2, 3].
?- concatenate([1, 2], [3, 4], T).
T = [1, 2, 3, 4].
singletons(P, Q) is true if and only if Q is equivalent to the list obtained from P if each item in P is wrapped in "[" and "]" to create a singleton list.
It looks like this should behave as follows:
?- singletons([foo, bar, baz, 42], Singletons).
Singletons = [[foo], [bar], [baz], [42]].
You may find this easier to do if you first define an auxiliary predicate that only wraps a single term in a list:
?- singleton(foo, Q).
Q = [foo].
?- singleton(foo, [foo]).
true.
(You do not need to use this in your definition of singletons/2, writing it might just clarify part of the problem.)
prefix_all(I, P, Q) is true if and only if P is a list of lists and Q is the list obtained by prepending I to each element in P.
The meaning of this depends on what "prepending" is supposed to mean, but the word prefix suggests that I is to be interpreted as a list that will be the prefix of any list in Q. So something like:
?- prefix_all([pre, fix], [[1, 2], [], [foo, bar, baz]], Q).
Q = [[pre, fix, 1, 2], [pre, fix], [pre, fix, foo, bar, baz]].
Once again, it may help to think about what it means to be the prefix of one list:
?- prefix_one([pre, fix], [1, 2], Xs).
Xs = [pre, fix, 1, 2].
Do not define this predicate! Think about what it means in terms of what you already know.
pairs_all(I, P, Q) is true if and only if Q is the list obtained by pairing I with each item in P.
This looks like it's meant to behave something like this:
?- pairs_all(foo, [1, 2, three, 4], Pairs).
Pairs = [ (foo, 1), (foo, 2), (foo, three), (foo, 4)].
Again, it may help to first define an auxiliary that constructs a single pair:
?- pair(foo, 5, Pair).
Pair = (foo, 5).
Related
This recursion should slice IL to IR out of the list Lin and hand result LOut...
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut].
slice(Lin,IL,IR,LOut) :-
nth0(IL,Lin,X),
append(LOut,[X],LOut2),
IK is IL + 1,
slice(Lin,IK,IR,LOut2).
Input / Output:
?- slice([1,2,3,4],2,3,X).
ERROR: source_sink `'3'' does not exist
ERROR: source_sink `'4'' does not exist
X = [] .
I m also new to Prolog, but I think this recursion must somehow work. Also I'm not really known to the error codes in Prolog, but after checking multiple times I just have to give up... I hope you guys can help me.
slice(_,IL,IR,LOut) :-
IR<IL,
[LOut]. % <-- this line causes source_sink error.
That syntax [name] tries to load the file name.pl as Prolog source code. By the time your code gets there, LOut is [3,4] so it tries to load the files 3.pl and 4.pl, and they don't exist (thankfully, or else who knows what they could do).
I think this recursion must somehow work
It won't; you are appending to a list as you go down into the recursion, which means you will never see the result.
The following might be a close version which works, at least one way:
slice(_,IL,IR,[]) :-
IR < IL.
slice(Lin,IL,IR,[X|LOut]) :-
IR >= IL,
nth0(IL,Lin,X),
IK is IL + 1,
slice(Lin,IK,IR,LOut).
?- slice([0,1,2,3,4,5,6,7,8,9], 2, 5, X).
X = [2, 3, 4, 5]
See how [X|LOut] in the second rule's header puts X in the result that you get, and append/3 is not needed, and LOut finishes down in the recursion eventually as [] the empty list from the first rule, and all the X's are prepended on the front of it to make the result on the way down into the recursion, which is tail recursion, so it doesn't need to go back up, only forward, since there's nothing left to be done after the recursive call.
Since the "cons" is done before the recursion, this is known as "tail recursion modulo cons" in other languages, but in Prolog it is just tail, and the list is being built top-down on the way forward, as opposed to being built bottom up on the way back:
Lin=[0,1,2,3,4,5,6,7,8,9], slice( Lin, 2, 5, R)
:-
nth0(2,Lin,X2), R=[X2|R2], slice( Lin, 3, 5, R2)
:-
nth0(3,Lin,X3), R2=[X3|R3], slice( Lin, 4, 5, R3)
:-
nth0(4,Lin,X4), R3=[X4|R4], slice( Lin, 5, 5, R4)
:-
nth0(5,Lin,X5), R4=[X5|R5], slice( Lin, 6, 5, R5)
:-
R5 = [].
I think findall/3 provides a readable readable solution for your problem:
slice(Lin,IL,IR,LOut) :-
findall(E,(nth0(P,Lin,E),between(IL,IR,P)),LOut).
yields
?- slice([1,2,3,4],2,3,X).
X = [3, 4].
If you expect a different outcome, use standard arithmetic comparison operators (=<,>=) instead of between/3.
I think you want:
list_elems_slice(Start, End, Lst, Slice) :-
list_elems_slice_(Lst, 1, Start, End, Slice).
list_elems_slice_([H|T], N, N, End, [H|Slice]) :-
list_elems_slice_capture_(T, N, End, Slice).
list_elems_slice_([_|T], N, Start, End, Slice) :-
N1 is N + 1,
list_elems_slice_(T, N1, Start, End, Slice).
list_elems_slice_capture_(_, N, N, []).
list_elems_slice_capture_([H|T], N, End, [H|Slice]) :-
N1 is N + 1,
list_elems_slice_capture_(T, N1, End, Slice).
Result in swi-prolog:
?- list_elems_slice(S, E, [a,b,c], Slice).
S = E, E = 1,
Slice = [a] ;
S = 1,
E = 2,
Slice = [a, b] ;
S = 1,
E = 3,
Slice = [a, b, c] ;
S = E, E = 2,
Slice = [b] ;
S = 2,
E = 3,
Slice = [b, c] ;
S = E, E = 3,
Slice = [c] ;
false.
Assuming that the point of this exercise is to teach you to think recursively, I would approach the problem as follows.
To get what you want is essentially two separate operations:
You first must discard some number of items from the beginning of the list, and then
Take some number of items from what's left over
That gives us discard/3:
discard( Xs , 0 , Xs ) .
discard( [_|Xs] , N , Ys ) :- N > 0 , N1 is N-1, discard(Xs,N1,Ys) .
and take/3, very nearly the same operation:
take( _ , 0 , [] ) .
take( [X|Xs] , N , [Y|Ys] ) :- N > 0 , N1 is N-1, take(Xs,N1,Ys) .
Once you have those two simple predicates, slice/4 itself is pretty trivial:
%
% slice( List , Left, Right, Sublist )
%
slice( Xs, L, R, Ys ) :- % to slice a list,
L =< R, % - the left offset must first be less than or equal to the right offset
N is R-L, % - compute the number of items required, and then
discard(Xs,L,X1), % - discard the first L items, and
take(X1,N,Ys). % - take the next N items
. % Easy!
Another approach would be to use append/3:
slice( Xs , L, R, Ys ) :-
length(Pfx,L), % - construct of list of the length to be discarded
append(Pfx,Sfx,Xs), % - use append to split Xs
N is R-L, % - compute the number of items required
length(Ys,N), % - ensure Ys is the required length
append(Ys,_,Sfx) % - use append to split off Ys
. % Easy!
I have to replicate each element n times like this:
?- replicate([a,b,c],2,X). -> X = [a,a,b,b,c,c]
?- replicate([a,b,c],3,X). -> X = [a,a,a,b,b,b,c,c,c]
I have tried everything with the information I have so far, the only thing I have been able to do is to determine which is the most repeating element like this:
%List of tuples, keeps track of the number of repetitions.
modify([],X,[(X,1)]).
modify([(X,Y)|Xs],X,[(X,K)|Xs]):- K is Y+1.
modify([(Z,Y)|Xs],X,[(Z,Y)|K]):- Z =\= X, modify(Xs,X,K).
highest((X1,Y1),(_,Y2),(X1,Y1)):- Y1 >= Y2.
highest((_,Y1),(X2,Y2),(X2,Y2)):- Y2 > Y1.
maxR([X],X).
maxR([X|Xs],K):- maxR(Xs,Z),highest(X,Z,K).
rep([],R,R).
rep([X|Xs],R,R1):-modify(R,X,R2),rep(Xs,R2,R1).
maxRepeated(X,R):- rep(X,[],K),maxR(K,R).
?- maxRepeated([1,3,3,4,3,2] ,X).
X = (3, 3) .
?- maxRepeated([1,2,3,4,5,6] ,X).
X = (1, 1) .
What do you want to do ?
Take each element X of the list, get a list of N X and create a new list with the process of the rest of the list !
How to get a list of N elements X ?
replicate_one(X, N, Out) :-
length(Out, N),
maplist(=(X),Out).
Now, how to work with each element of the input, it can be easily done with the pattern [Head|Tail] :
replicate([Head|Tail], N, Out) :-
% I replicate the rest of the list
replicate(Tail, N, Tmp1),
% I replicate the first element of the list
replicate_one(Head, N, Tmp2),
% I concatenate the 2 results
append(Tmp2, Tmp1, Out).
When you work with replicate, the input looses an element each time, so you must have a process for the empty list :
replicate([], _N, []).
Now :
?- replicate([a,b,c],3,X).
X = [a, a, a, b, b, b, c, c, c].
We can split the problem into two problems:
generate a list of N elements X with a predicate we implement replicate_item/3; and
do this for every element, and concatenate the result in a prdicate named replicate/3.
#joel76 already provided a nice implementation for replicate_item/3. I will only change the order of the parameters:
replicate_item(N, X, List) :-
length(List, N),
maplist(=(X), List).
Now our replicate/3 prdicate can iterate over the list, and for each element use replicate_item/3 to generate a sublist. We can then use append/2 [swi-doc] for this:
replicate(LA, N, List) :-
maplist(replicate_item(N), LA, LL),
append(LL, List).
I'm new in Prolog and trying to do some programming with Lists
I want to do this :
?- count_occurrences([a,b,c,a,b,c,d], X).
X = [[d, 1], [c, 2], [b, 2], [a, 2]].
and this is my code I know it's not complete but I'm trying:
count_occurrences([],[]).
count_occurrences([X|Y],A):-
occurrences([X|Y],X,N).
occurrences([],_,0).
occurrences([X|Y],X,N):- occurrences(Y,X,W), N is W + 1.
occurrences([X|Y],Z,N):- occurrences(Y,Z,N), X\=Z.
My code is wrong so i need some hits or help plz..
Here's my solution using bagof/3 and findall/3:
count_occurrences(List, Occ):-
findall([X,L], (bagof(true,member(X,List),Xs), length(Xs,L)), Occ).
An example
?- count_occurrences([a,b,c,b,e,d,a,b,a], Occ).
Occ = [[a, 3], [b, 3], [c, 1], [d, 1], [e, 1]].
How it works
bagof(true,member(X,List),Xs) is satisfied for each distinct element of the list X with Xs being a list with its length equal to the number of occurrences of X in List:
?- bagof(true,member(X,[a,b,c,b,e,d,a,b,a]),Xs).
X = a,
Xs = [true, true, true] ;
X = b,
Xs = [true, true, true] ;
X = c,
Xs = [true] ;
X = d,
Xs = [true] ;
X = e,
Xs = [true].
The outer findall/3 collects element X and the length of the associated list Xs in a list that represents the solution.
Edit I: the original answer was improved thanks to suggestions from CapelliC and Boris.
Edit II: setof/3 can be used instead of findall/3 if there are free variables in the given list. The problem with setof/3 is that for an empty list it will fail, hence a special clause must be introduced.
count_occurrences([],[]).
count_occurrences(List, Occ):-
setof([X,L], Xs^(bagof(a,member(X,List),Xs), length(Xs,L)), Occ).
Note that so far all proposals have difficulties with lists that contain also variables. Think of the case:
?- count_occurrences([a,X], D).
There should be two different answers.
X = a, D = [a-2]
; dif(X, a), D = [a-1,X-1].
The first answer means: the list [a,a] contains a twice, and thus D = [a-2]. The second answer covers all terms X that are different to a, for those, we have one occurrence of a and one occurrence of that other term. Note that this second answer includes an infinity of possible solutions including X = b or X = c or whatever else you wish.
And if an implementation is unable to produce these answers, an instantiation error should protect the programmer from further damage. Something along:
count_occurrences(Xs, D) :-
( ground(Xs) -> true ; throw(error(instantiation_error,_)) ),
... .
Ideally, a Prolog predicate is defined as a pure relation, like this one. But often, pure definitions are quite inefficient.
Here is a version that is pure and efficient. Efficient in the sense that it does not leave open any unnecessary choice points. I took #dasblinkenlight's definition as source of inspiration.
Ideally, such definitions use some form of if-then-else. However, the traditional (;)/2 written
( If_0 -> Then_0 ; Else_0 )
is an inherently non-monotonic construct. I will use a monotonic counterpart
if_( If_1, Then_0, Else_0)
instead. The major difference is the condition. The traditional control constructs relies upon the success or failure of If_0 which destroys all purity. If you write ( X = Y -> Then_0 ; Else_0 ) the variables X and Y are unified and at that very point in time the final decision is made whether to go for Then_0 or Else_0. What, if the variables are not sufficiently instantiated? Well, then we have bad luck and get some random result by insisting on Then_0 only.
Contrast this to if_( If_1, Then_0, Else_0). Here, the first argument must be some goal that will describe in its last argument whether Then_0 or Else_0 is the case. And should the goal be undecided, it can opt for both.
count_occurrences(Xs, D) :-
foldl(el_dict, Xs, [], D).
el_dict(K, [], [K-1]).
el_dict(K, [KV0|KVs0], [KV|KVs]) :-
KV0 = K0-V0,
if_( K = K0,
( KV = K-V1, V1 is V0+1, KVs0 = KVs ),
( KV = KV0, el_dict(K, KVs0, KVs ) ) ).
=(X, Y, R) :-
equal_truth(X, Y, R).
This definition requires the following auxiliary definitions:
if_/3, equal_truth/3, foldl/4.
If you use SWI-Prolog, you can do :
:- use_module(library(lambda)).
count_occurrences(L, R) :-
foldl(\X^Y^Z^(member([X,N], Y)
-> N1 is N+1,
select([X,N], Y, [X,N1], Z)
; Z = [[X,1] | Y]),
L, [], R).
One thing that should make solving the problem easier would be to design a helper predicate to increment the count.
Imagine a predicate that takes a list of pairs [SomeAtom,Count] and an atom whose count needs to be incremented, and produces a list that has the incremented count, or [SomeAtom,1] for the first occurrence of the atom. This predicate is easy to design:
increment([], E, [[E,1]]).
increment([[H,C]|T], H, [[H,CplusOne]|T]) :-
CplusOne is C + 1.
increment([[H,C]|T], E, [[H,C]|R]) :-
H \= E,
increment(T, E, R).
The first clause serves as the base case, when we add the first occurrence. The second clause serves as another base case when the head element matches the desired element. The last case is the recursive call for the situation when the head element does not match the desired element.
With this predicate in hand, writing count_occ becomes really easy:
count_occ([], []).
count_occ([H|T], R) :-
count_occ(T, Temp),
increment(Temp, H, R).
This is Prolog's run-of-the-mill recursive predicate, with a trivial base clause and a recursive call that processes the tail, and then uses increment to account for the head element of the list.
Demo.
You have gotten answers. Prolog is a language which often offers multiple "correct" ways to approach a problem. It is not clear from your answer if you insist on any sort of order in your answers. So, ignoring order, one way to do it would be:
Sort the list using a stable sort (one that does not drop duplicates)
Apply a run-length encoding on the sorted list
The main virtue of this approach is that it deconstructs your problem to two well-defined (and solved) sub-problems.
The first is easy: msort(List, Sorted)
The second one is a bit more involved, but still straight forward if you want the predicate to only work one way, that is, List --> Encoding. One possibility (quite explicit):
list_to_rle([], []).
list_to_rle([X|Xs], RLE) :-
list_to_rle_1(Xs, [[X, 1]], RLE).
list_to_rle_1([], RLE, RLE).
list_to_rle_1([X|Xs], [[Y, N]|Rest], RLE) :-
( dif(X, Y)
-> list_to_rle_1(Xs, [[X, 1],[Y, N]|Rest], RLE)
; succ(N, N1),
list_to_rle_1(Xs, [[X, N1]|Rest], RLE)
).
So now, from the top level:
?- msort([a,b,c,a,b,c,d], Sorted), list_to_rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [[d, 1], [c, 2], [b, 2], [a, 2]].
On a side note, it is almost always better to prefer "pairs", as in X-N, instead of lists with two elements exactly, as in [X, N]. Furthermore, you should keep the original order of the elements in the list, if you want to be correct. From this answer:
rle([], []).
rle([First|Rest],Encoded):-
rle_1(Rest, First, 1, Encoded).
rle_1([], Last, N, [Last-N]).
rle_1([H|T], Prev, N, Encoded) :-
( dif(H, Prev)
-> Encoded = [Prev-N|Rest],
rle_1(T, H, 1, Rest)
; succ(N, N1),
rle_1(T, H, N1, Encoded)
).
Why is it better?
we got rid of 4 pairs of unnecessary brackets in the code
we got rid of clutter in the reported solution
we got rid of a whole lot of unnecessary nested terms: compare .(a, .(1, [])) to -(a, 1)
we made the intention of the program clearer to the reader (this is the conventional way to represent pairs in Prolog)
From the top level:
?- msort([a,b,c,a,b,c,d], Sorted), rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [a-2, b-2, c-2, d-1].
The presented run-length encoder is very explicit in its definition, which has of course its pros and cons. See this answer for a much more succinct way of doing it.
refining joel76 answer:
count_occurrences(L, R) :-
foldl(\X^Y^Z^(select([X,N], Y, [X,N1], Z)
-> N1 is N+1
; Z = [[X,1] | Y]),
L, [], R).
I am trying to generate a big list (2^N elements) from a small given list (N elements). For example,
there is a list [X,Y,Z], in which X, Y or Z could only be 0.1 or 0.9. I will pick 0.1 or 0.9 from X, pick 0.1 or 0.9 from Y and pick 0.1 or 0.9 from Z sequentially, then see XYZ as an element of the new list. So there should be 2^N elements in the new list [0.001,0.009,0.009,...,0.729] ([0.1*0.1*0.1, 0.1*0.1*0.9, 0.1*0.9*0.1, ..., 0.9*0.9*0.9]). How can I get this new list from the given list? N is a parameter acquired from the given list,
trn(List_given,Outlist):-
length(List_given,N),
...
I just want to implement like this,
?- trn([X,Y],Out).
Out=[0.01,0.09,0.09,0.81].
Thanks in advance!
To generate the possible combinations of your values:
mem(L, E) :- member(E, L).
gen_values(N, Choices, Values) :-
length(Values, N),
maplist(mem(Choices), Values).
So:
| ?- gen_values(3, [0.1, 0.9], L).
L = [0.10000000000000001,0.10000000000000001,0.10000000000000001] ? a
L = [0.10000000000000001,0.10000000000000001,0.90000000000000002]
L = [0.10000000000000001,0.90000000000000002,0.10000000000000001]
L = [0.10000000000000001,0.90000000000000002,0.90000000000000002]
L = [0.90000000000000002,0.10000000000000001,0.10000000000000001]
L = [0.90000000000000002,0.10000000000000001,0.90000000000000002]
L = [0.90000000000000002,0.90000000000000002,0.10000000000000001]
L = [0.90000000000000002,0.90000000000000002,0.90000000000000002]
(1 ms) yes
Then you need a list multiplier:
prodlist(L, P) :-
prodlist(L, 1, P).
prodlist([X], A, P) :- P is X * A.
prodlist([X,Y|T], A, P) :-
A1 is X * A,
prodlist([Y|T], A1, P).
Then you can get all of the results with findall/3:
trn(List_given, Outlist):-
length(List_given, N),
findall(X, (gen_values(N, [0.1, 0.9], Values), prodlist(Values, X)), Outlist).
Resulting in:
| ?- trn([_,_,_], Out).
Out = [0.0010000000000000002,0.0090000000000000028,0.0090000000000000011,0.081000000000000016,0.0090000000000000011,0.081000000000000016,0.081000000000000016,0.72900000000000009]
yes
| ?-
You can use trn([X,Y,Z], Out) here, but there's really no point. You could just as well define the predicate with the length: trn(3, Out).
Note, there's some slight floating point precision inaccuracy happening, which yields the long decimals. Also, this method doesn't take advantage of the redundancy in calculations, so it's probably not the most efficient approach. And finally, if N (the length of the input list) is large, this will explode.
In this Prolog code I intend to list the first N primes,
(...)
biggerPrime(N,P) :-
isPrime(N),
P is N,
!.
biggerPrime(N,P) :-
N1 = N+1,
biggerPrime(N1,P).
primeListAcc(0,A,R,R) :- !.
primeList(N,L) :-
primeListAcc(N,1,[],L).
primeListAcc(N,A,L,R) :-
N1 is N-1,
biggerPrime(A,P),
A1 is P+1,
primeListAcc(N1,A1,[P|L],R).
And it works fine if I want the list ordered backwards:
?- primeList(5,L).
L = [11, 7, 5, 3, 2].
But if I change the last line of the code from [P|L] to [L|P] like this:
primeListAcc(N,A,L,R) :-
N1 is N-1,
biggerPrime(A,P),
A1 is P+1,
primeListAcc(N1,A1,[L|P],R).
I get:
?- primeList(5,L).
L = [[[[[[]|2]|3]|5]|7]|11].
What am I missing? This is driving me mad!
Recall that a list is either the empty list [] or a term with functor '.' and two arguments, whose second argument is a list. The syntax [P|Ps] is shorthand notation for the term '.'(P, Ps), which is a list if Ps is a list (as is the case in your example). The term '.'(Ps, P), on the other hand, which can also be written as [Ps|P] (as you are doing), is not a list if P is not a list. You can obtain a reverse list with reverse/2.
Great, so you've discovered the problem of adding elements to the end of a list. In Prolog, we can do it with
add(X,L,Z):- L=[X|Z].
wait, what? How to read this? We must know the calling convention here. We expect L and Z to come in as uninstantiated variables, and we arrange for L from now on to point to a newly created cons node with X at its head, and Z its tail. Z to be instantiated, possibly, in some future call.
IOW what we create here is an open-ended list, L = [X|Z] = [X, ...]:
primeList(N,L) :-
primeListAcc(N,1,[],L).
primeListAcc(N,A,Z,L) :- N > 0, % make it explicitly mutually-exclusive,
N1 is N-1, % do not rely on red cuts which are easily
biggerPrime(A,P), % invalidated if clauses are re-arranged!
A1 is P+1,
L = [P|R], % make L be a new, open-ended node, holding P
primeListAcc(N1,A1,Z,R). % R, the tail of L, to be instantiated further
primeListAcc(0,A,R,R). % keep the predicate's clauses together
We can see now that Z is not really needed here, as it carries the [] down the chain of recursive calls, unchanged. So we can re-write primeListAcc without the Z argument, so that its final clause will be
primeListAcc(0,A,R):- R=[].
Keeping Z around as uninstantiated variable allows for it to be later instantiated possibly with a non-empty list as well (of course, only once (unless backtracking occurs)). This forms the basis of "difference list" technique.
To answer your literal question - here, consider this interaction transcript:
1 ?- X=[a|b].
X = [a|b]
2 ?- X=[a|b], Y=[X|c].
X = [a|b]
Y = [[a|b]|c]
the [a|b] output is just how a cons node gets printed, when its tail (here, b) is not a list. Atoms, as numbers, are not lists.