How to concatenate 3 lists in Prolog without using append - prolog

I know how to concatenate 2 lists without append but how would you go about concatenating 3 lists without append.

You could foldl your catenate function over a list of lists.
list_list_catenate([E], L, [E|L]). %// [4] cat [a,b,c] is [4,a,b,c]
list_list_catenate([H|T], L, Cat) :- %// [4,5] cat [a,b,c] is [4|(5 cat [a,b,c])]
list_list_catenate(T, L, TCat),
Cat = [H|TCat].
Lists = [[1,2,3], [4,5,6], [7,8,9]],
reverse(Lists, RevLists),
foldl(list_list_catenate, RevLists, [], Result).
Fold left is a loop structure common in functional programming languages, it pushes each of the list items into the helper, along with the result of the previous time, so they aggregate up.
And this needs a reverse because of the way foldl maps the arguments to the helper; without that, it goes [1,2,3], [] then [4,5,6], [1,2,3] then [7,8,9], [4,5,6,1,2,3].

Related

Merging 2 lists into a third but in pairs

I want, given 2 lists, to merge them into a third one but each element of the third list is a list of the first and second list's elements.
E.g. given the list1 [1,2,3] and list2 [1,2,3] I want the final list to be [[1,1],[2,2],[3,3]]
What I've done so far is
merge([],[],Z).
merge([H1|T1],[T2|T2],Z):-
append([H1],[H2],W),merge(T1,T2,[W,Z]).
but I get a False result. Why isn't it working?
There are some flaws in your code:
when the first two lists are empty, the result must be an empty list too;
Instead of [T2|T2] you should write [H2|T2] to represent the second list;
there is no need to use append([H1],[H2],W) to create a list with two elements, just write [H1,H2];
since the recursive call must merge the tails of the first and second lists, there is no way the result of this call to be a list starting with the element [H1,H2].
Thus, a correct definition for that predicate is as follows:
my_merge([], [], []).
my_merge([H1|T1], [H2|T2], [[H1,H2]|T3]):-
my_merge(T1, T2, T3).
Examples:
?- my_merge([a,b,c], [1,2,3], L3).
L3 = [[a, 1], [b, 2], [c, 3]].
?- my_merge(L1, L2, [[1,a],[2,b],[3,c]]).
L1 = [1, 2, 3],
L2 = [a, b, c].
Remark Consider the possibility of representing the pair [H1,H2] as H1-H2, as the latter representation is more commonly used in Prolog.

Prolog Sorting List By Rule Position

I am new to Prolog and for the following program:
place(Store,2,a).
place(Store,1,b).
place(Store,3,d).
place(Store,4,c).
placeSort(S,List):- findall(L,place(S,N,L),List).
output: List = [a, b, d, c].
By using placeSort(S,List) , I can find all the elements(a,b,c,d) that contains S (Store).
However what I want to achieve here is to sort the Position of a,b,c,d by using N, however I dont know how to do so as using sort will just sort it out by alphabetical order
placeSort(S,NewList):- findall(L,place(S,N,L),List),sort(List,NewList).
output: List = [a, b, c, d].
what I want to achieve : List = [b,a,d,c]
**I know by using placeSort(S,NewList):- findall([N,L],place(S,N,L),List),sort(List,NewList).
it will return a list of lists sorted by numbers.
output : List = [[1, b], [2, a], [3, d], [4, c]].
but im not sure how to take away the numbers and just take the alphabets instead.
Any help would be greatly appreciated.
SWI-Prolog offers the interesting builtin order_by/2, filling the gap traditional Prolog suffers when compared to SQL, with library(solutionsequences):
?- order_by([asc(X)],place(P,X,W)).
X = 1,
W = b ;
X = 2,
W = a ;
...
So you can avoid full list construction.
The easiest way to do this is to use setof/3 (which sorts by term) and pick a term form that works for you on your sort. In this case, you can collect terms of the form N-X where they satisfy, place(_, N, X):
setof(N-X, place(S,N,X), OrderedList). % Assuming `S` is bound
This will result in:
OrderedList = [1-b, 2-a, 3-d, 4-c]
Then you can use maplist/3 to get your list by defining a simple mapping:
foo(_-X, X).
maplist(foo, OrderedList, List).
This will then give you just the elements you want.
Your complete predicate would look like:
foo(_-X, X).
placeSort(S, List) :-
setof(N-X, place(S,N,X), OrderedList),
maplist(foo, OrderedList, List).
Obviously, you'd choose sensible names for your facts, predicates, and variables. My names (foo, List, OrderedList, S, N, X) are not sufficient, in my opinion, for an application but I am not familiar with your actual problem domain, so this is just for illustration purposes.
As an aside, note that in your facts Store is a variable, so that's not particularly meaningful in the facts. I kept your use of S in your predicate, but it's unclear to me how you really intend to use it.

How prolog deals with this step-by-step?

I'm trying to understand prolog but I am stuck with one example, can you explain to me how is prolog going through this call:
eli(2,[2,2,1],L).
using those facts:
eli(X,[],[]).
eli(X,[Y],[Y]).
eli(X,[X,X|L],L1) :- eli(X,L,L1).
eli(X,[Y|L],[Y|L1]) :- eli(X,L,L1).
The results are:
L = [1]
L = [1]
L = [2, 2, 1]
L = [2, 2, 1]
and I'm not really sure why.
Thanks in advance!
It looks like your predicate is mean to delete two consecutive appearance of any element.
First clause, if the target list is empty, return the empty list. In this case the X variable in the fact is not necessary. Replace X by te anonymous variable.
eli(_,[],[]).
Second clause is similar to the first, but it matches the target list if it contains only one element. Variable X is also not necessary.
eli(_,[Y],[Y]).
Third clause, if the target list contains two or more elements, and in the Head of the list both elements are equal to X, don't copy this two elements to the Result list, and make a recursive call to the eli/3 predicate in the body of the rule, to continue the search.
eli(X,[X,X|L],L1) :- eli(X,L,L1), !.
In this case we add the cut predicate, to avoid backtracking after this rule succeeded. Otherwise you may get undesired results, like L = [2, 2, 1] in your test.
And the last clause, copy the element in the Head of the Target list to the Result list, and continue the recursive call, this will stop when the Target list is empty or contains only one element (your first two clauses).
eli(X,[Y|L],[Y|L1]) :- eli(X,L,L1).
Now this is your predicate eli/3:
eli(_,[],[]).
eli(_,[Y],[Y]).
eli(X,[X,X|L],L1) :- eli(X,L,L1), !.
eli(X,[Y|L],[Y|L1]) :- eli(X,L,L1).
Test:
?- eli(2,[2,2,1],L).
L = [1]
?- eli(2,[1,2,2,3],L).
L = [1, 3]

Why prolog outputs a weird tree-like list?

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.

prolog, list with proper brackets as result

I am wondering how to get a nice proper looking list with the elements I have! I've been trying to look up stuff on this but none of the actual examples I've found seem to actually work
Here is one method I found on the web:
create_list(Item, List, [Item|List]).
if I run this query:
Hi = [1,2], Hey = [3,4], create_list(Hi, Hey, Output).
The result gets weird:
Output = [[1,2], 3,4]
The brackets are all wrong!
It should be:
[[1,2], [3,4]]
The brackets are all wrong! It should be:
[[1,2], [3,4]]
This is because your create_list uses [Item|List]. If you wanted brackets around [3,4] to remain in place, replace [Item|List] with [Item,List]. Of course List has incorrect meaning now, so I would rename it, as follows:
list_of_two(First, Last, [First, Last]).
This would not work for more than two items, however. Your original one rule would work, like this:
create_list([1,2],[],O1), create_list([3,4],O1,O2), create_list([5,6],O2,O3).
This produces
[[5, 6], [3, 4], [1, 2]]
in the O3 list.
In contrast with other languages, a list is a very basic datastructure in Prolog:
[] is/creates an empty list
[1] is/creates a list with a single element
[1,2,3,4,....,n] is/creates a list with n elements
[1|[2,3,4]] is/creates a list by inserting 1 in the list [2,3,4] (the result is [1,2,3,4])
So, you don't need a predicate to "create" a list: if you have n elements just put them in brackets; if the elements are generated recursively, use | to create a list with the new element. For example:
put_in_list(A1,A2,A3, L):- L = [A1,A2,A3].
alternatively:
put_in_list(A1,A2,A3, [A1,A2,A3]).
also:
generate(0, []).
generate(N, [ [N, NN]| Rest ]):-
NN is N-1,
NNN is N-2,
generate(NNN, Rest).
All in all, you should be careful with types; in your case, you have a list of numbers (let's call it X) and you want a list of lists of numbers (so this would be a list of Xs). The problem was created when you gave a list of Xs as an argument instead of an X to a predicate.

Resources