Prolog Convert a list in a list of lists - list

I need to convert a list of elements into a list of lists.
For example, if i have the list [1,2,3,4] the output must be [[1],[2],[3],[4]], one element per list.
create([],_, _, _).
create([H|T], Aux, X, Result) :-
append([H], Aux, X),
Result = [X],
create(T, X, _, Result).
I always get false... is this even possible to do?

Another possibility to define this relation is by using DCGs. They yield easily readable code when describing lists. Let's stick with the name singletons as suggested by #false in the comments:
singletons([]) --> % the empty list
[]. % is empty
singletons([H|T]) --> % the head of a nonempty list
[[H]], % is a list on its own
singletons(T). % and so is the tail
You can query this directly with phrase/2:
?- phrase(singletons([1,2,3,4]),X).
X = [[1],[2],[3],[4]]
Or write a wrapper-predicate with phrase/2 as the single goal:
singletons(L,Ls) :-
phrase(singletons(L),Ls).
And query that:
?- singletons([1,2,3,4],Ls).
Ls = [[1],[2],[3],[4]]
The predicate also works the other way around:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4] ? ;
no
As well as the most general query:
?- singletons(L,Ls).
L = Ls = [] ? ;
L = [_A],
Ls = [[_A]] ? ;
L = [_A,_B],
Ls = [[_A],[_B]] ?
...
Alternatively you can also define a simple predicate that describes a relation between an arbitrary element and itself in brackets and then use maplist/3 from library(apply) to apply it on every element of a list:
:- use_module(library(apply)).
embraced(X,[X]).
singletons(L,Ls) :-
maplist(embraced,L,Ls).
This version yields the same results for the above queries. However, it is more efficient. To see that consider the following query from above:
?- singletons(L,[[1],[2],[3],[4]]).
L = [1,2,3,4]
Above you had to enter ; to make Prolog search for further solutions and subsequently fail (indicated by no). With this version there are no unnecessary choice points left and Prolog is succeeding deterministically for the query.

Try this
create([],[]).
create([H|T],[[H]|T2]):- create(T,T2).
I tried
?- create([1,2,3,4],X).
and the result was
X = [[1], [2], [3], [4]].

Related

Prolog: How do you iterate between two lists (nest for-loop)?

I just started learning Prolog this week so I am not sure if for-loops are possible in Prolog.
I have two lists in Prolog
stringList([hi,hello],[bye,later],X).
How do I create a new solution list with one element per list?
So the output should be:
X = [hi,bye]
X = [hi,later]
X = [hello,bye]
X = [hello,later]
A major advantage when using Prolog is that you can delegate such loops to the Prolog engine. You do not have to write them explicitly.
For example, in your case, think about the problem in this way: What holds (or should hold) about X?
We can say:
X is a list with two elements, say [A,B].
A is a member of the list that is denoted by the first argument.
B is a member of the list that is denoted by the second argument.
So, in Prolog:
one_from_each(As, Bs, [A,B]) :-
member(A, As),
member(B, Bs).
Sample query:
?- one_from_each([hi,hello],[bye,later], X).
X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].
And it works in other directions too:
?- one_from_each(As, Bs, [hi,bye]).
As = [hi|_4656],
Bs = [bye|_4662] ;
As = [hi|_4656],
Bs = [_4660, bye|_4668] ;
As = [hi|_4656],
Bs = [_4660, _4666, bye|_4674] .
Hence, the whole question is somewhat misguided. When coding in Prolog, always ask: How can I formulate what ought to hold? Once you have such a formulation, you can leave the search for solutions to the Prolog engine!
If you want, you can be more explicit. For example:
one_from_each([], _) --> [].
one_from_each([L|Ls], Rs) -->
one_from_each_(Rs, L),
one_from_each(Ls, Rs).
one_from_each_([], _) --> [].
one_from_each_([R|Rs], L) -->
[[L,R]],
one_from_each_(Rs, L).
Example:
?- phrase(one_from_each([hi,hello],[bye,later]), Ls).
Ls = [[hi, bye], [hi, later], [hello, bye], [hello, later]].
This is sometimes called a spatial representation, because the solutions are now no longer found on backtracking (temporal representation), but represented explicitly.
From this, you see that "loops" correspond to recursive definitions.

List as variable/argument in Prolog

I've created a function in Prolog to "turn" a list, e.g. to append the head of a list to the tail like so:
?- turn([a,b,c,d,e], Tlist).
Tlist=[b,c,d,e,a]
Within the context of my program, I'd like to be able to use predefined lists for the rule, such as
alist([a,b,c,d,e,f])
but I get lots of different errors. I've tried the following as arguments:
turn(alist(L),R).
listv(X) :- alist(L), member(X, L).
turn(listv(X),R).
and I understand that each of these are different representations of the list according to Prolog, but I'm not sure which list representation is appropriate to complete the operation on a predefined list.
Thanks!
The predicate turn/2 can easily be defined based on append/3:
turn([A|As],Bs) :-
append(As,[A],Bs).
For specifying some sample lists, we define an auxiliary predicate named_list/2:
named_list(one_to_nine , [1,2,3,4,5,6,7,8,9]).
named_list(a_to_f , [a,b,c,d,e,f]).
named_list(single_digit_primes, [2,3,5,7]).
Let's query!
?- named_list(a_to_f,Xs), turn(Xs,Ys).
Xs = [a,b,c,d,e,f], Ys = [b,c,d,e,f,a]. % succeeds deterministically
?- named_list(a_to_f,Ys), turn(Xs,Ys). % "other" direction
Ys = [a,b,c,d,e,f], Xs = [f,a,b,c,d,e] % succeeds leaving behind choicepoint
; false.
So far, we have used one specific sample list a_to_f in the queries; let's use 'em all!
?- named_list(Name,Xs), turn(Xs,Ys).
Name = one_to_nine , Xs = [1,2,3,4,5,6,7,8,9], Ys = [2,3,4,5,6,7,8,9,1]
; Name = a_to_f , Xs = [a,b,c,d,e,f] , Ys = [b,c,d,e,f,a]
; Name = single_digit_primes, Xs = [2,3,5,7] , Ys = [3,5,7,2].

Searching a list for (same) two elements in Prolog

How can I search a list in Prolog for a specific element that appears more than once?
For example, if we are searching the list [1,2,3,4,1] for the element 1, Prolog should return true, but otherwise false for all other numbers.
This is what I have so far:
duplicate([], _) :-
false,
!.
duplicate([X|_], X) :-
true,
!.
duplicate([H|T], X) :-
T = [_|T1],
duplicate(T, X),
duplicate(T1, X).
My basic idea is to search the list until I find the element I am looking for, then search the tail of the list for the item again. I do not want to use the member() function provided by Prolog.
Prolog should also return the elements that appear more than once if asked by the query: duplicate([1,2,3,4,1], X), should print X = 1.
And here the obvious version using grammars. In a sense, we are describing the structure of a list containing a duplicate. That structure is as follows:
First, there is anything (...),
then there is the element ([V]),
again anything (...)
and again the element ([V])
followed by anything.
duplicate(L, V) :-
phrase(( ..., [V], ..., [V], ... ), L).
... --> [] | [_], ... .
As a downside, this version will produce redundant answers for a query like
?- duplicate([a,a,a],a).
This can be overcome by using dif/2:
duplicate(L, V) :-
phrase(( all(dif(V)), [V], all(dif(V)), [V], ... ), L).
The definition for non-terminal all//1.
What I was saying in my comment was : I want two items from the list L wich are not in the same place so
duplicate(L, V) :-
% nth0 gives the index (from 0) of an element in a list
% element V is at the place Id1 in L
nth0(Id1, L, V),
% element V is at the place Id2 in L
nth0(Id2, L, V),
% Id1 is different from Id2
% It is more usefull to say that Id1 < Id2
% Thanks **false** for the improvement
Id1 < Id2.
Another way to do this is to say : I remove the element of the list (this is done in SWI-Prolog by select/3) and I check if it's in the rest of the list :
duplicate(L, V) :-
select(V, L, L1),
member(V, L1).
Pure and simple! Use meta-predicate tcount/3 with reified term equality (=)/3 like so:
?- tcount(=(X), [1,2,3,4,1], 2).
X = 1 ; % succeeds, but leaves choicepoint
false.
?- tcount(=(1), [1,2,3,4,1], 2).
true. % succeeds deterministically
?- tcount(=(X), [b,c,d,a,b,a,c], 2).
X = b ;
X = c ;
X = a ;
false.
?- tcount(=(a), [b,c,d,a,b,a,c], 2).
true. % succeeds deterministically
Last, let's run the following quite general query:
?- tcount(=(a), Ls, 2).
Ls = [a,a] ;
Ls = [a,a,_X], dif(_X,a) ;
Ls = [a,a,_X,_Y], dif(_X,a), dif(_Y,a) ;
Ls = [a,a,_X,_Y,_Z], dif(_X,a), dif(_Y,a), dif(_Z,a) ...
The solution by #false is as clean as it will get. Here is a more verbose solution that states the problem in simpler terms. One thing to remember is that a "duplicated" element might mean that an element occurs exactly twice -- this is how this predicate interprets it -- or it might mean that an element occurs more than once -- this is what you probably mean (so the name duplicate is in fact misleading)
%% duplicate(List, Element) is true for every matching pair of _Element_ in _List_
duplicate([First|Rest], Element) :-
duplicate_1(Rest, First, Element).
% First occurrence
duplicate_1([This|Rest], X, X) :- % first occurrence
duplicate_2(Rest, This, X).
duplicate_1([This|Rest], _, X) :- % look further for first occurrence
duplicate_1(Rest, This, X).
% Second occurrence
duplicate_2(_, X, X). % second occurrence
duplicate_2([This|Rest], _, X) :- % look further for second occurrence
duplicate_2(Rest, This, X).
This can now be used in all directions:
?- duplicate([b,c,d,a,b,a,c], X).
X = b ;
X = c ;
X = a ;
false.
?- duplicate([b,c,d,a,b,a,c], a).
true ;
false.
?- duplicate(L, a).
L = [a, a|_G274] ;
L = [a, _G273, a|_G277] ;
L = [a, _G273, _G276, a|_G280] .
You will have to use cuts, or dif/2, or once/1 to get rid of the multiple answers, if they are a problem. How exactly depends on how you want to use the predicate.
for the first part of your problem I have found a simple solution:
duplicated([H|T], Item) :- H == Item, second_stage(T, Item). %first occurence found
duplicated([H|T], Item) :- duplicated(T, Item).
second_stage([H|T], Item) :- H == Item. %second occurence found -> match!
second_stage([H|T], Item) :- second_stage(T, Item).
This will give true f.e. with duplicated([1,2,3,1,5], 1).
For the second part (query with Variable) I will try to find a way...but I dont
know if this is possible in Prolog.
:)

Prolog: How "length(+,-)" delete unassigned tail of the list keeping the list?

Again a Prolog beginner :-}
I build up a list element by element using
(1)
member(NewElement,ListToBeFilled).
in a repeating call,
(2)
ListToBeFilled = [NewElement|TmpListToBeFilled].
in a recursive call like
something(...,TmpListToBeFilled).
A concrete example of (2)
catch_all_nth1(List, AllNth, Counter, Result) :-
[H|T] = List,
NewCounter is Counter + 1,
(
0 is Counter mod AllNth
->
Result = [H|Result1]
;
Result = Result1
),
catch_all_nth1(T,AllNth,NewCounter,Result1),
!.
catch_all_nth1([], _, _, _).
As result I get a list which looks like
[E1, E2, E3, ..., Elast | _G12321].
Of course, the Tail is a Variable. [btw: are there better method to fill up the
list, directly avoiding the "unassigned tail"?]
I was now looking for a simple method to eliminate the "unassigned tail".
I found:
Delete an unassigned member in list
there it is proposed to use:
exclude(var, ListWithVar, ListWithoutVar),!,
[Found this too, but did not help as I do not want a dummy element at the end
Prolog list has uninstantiated tail, need to get rid of it ]
What I noticed is that using length\2 eliminate the "unassigned tail", too, and in addtion
the same List remains.
My Question is: How does it work? I would like to use the mechanism to eliminate the unassigned tail without using a new variable... [in SWI Prolog 'till now I did not get the debugger
entering length() ?!]
The example:
Z=['a','b','c' | Y],
X = Z,
write(' X '),write(X),nl,
length(X,Tmp),
write(' X '),write(X),nl.
13 ?- test(X).
X [a,b,c|_G3453]
X [a,b,c]
X = [a, b, c] .
I thought X, once initialized can not be changed anymore and you need
a new variable like in exclude(var, ListWithVar, ListWithoutVar).
Would be happy if someone explain the trick to me...
Thanks :-)
You're right about the strange behaviour: it's due to the ability of length/2 when called with unbound arguments
The predicate is non-deterministic, producing lists of increasing length if List is a partial list and Int is unbound.
example:
?- length([a,b,c|X],N).
X = [],
N = 3 ;
X = [_G16],
N = 4 ;
X = [_G16, _G19],
N = 5 ;
...
For your 'applicative' code, this tiny correction should be sufficient. Change the base recursion clause to
catch_all_nth1([], _, _, []).
here are the results before
4 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d|_G75].
and after the correction:
5 ?- catch_all_nth1([a,b,c,d],2,1,R).
R = [b, d].
But I would suggest instead to use some of better know methods that Prolog provide us: like findall/3:
?- findall(E, (nth1(I,[a,b,c,d],E), I mod 2 =:= 0), L).
L = [b, d].
I think this should do it:
% case 1: end of list reached, replace final var with empty list
close_open_list(Uninstantiated_Var) :-
var(Uninstantiated_Var), !,
Uninstantiated_Var = '[]'.
% case 2: not the end, recurse
close_open_list([_|Tail]) :-
close_open_list(Tail).
?- X=[1,2,3|_], close_open_list(X).
X = [1, 2, 3].
Note that only variable X is used.. it simply recurses through the list until it hits the var at the end, replaces it with an empty list, which closes it. X is then available as a regular 'closed' list.
Edit: once a list element has been assigned to something specific, it cannot be changed. But the list itself can be appended to, when constructed as an open list ie. with |_ at the end. Open lists are a great way to build up list elements without needing new variables. eg.
X=[1,2,3|_], memberchk(4, X), memberchk(5,X).
X = [1, 2, 3, 4, 5|_G378304]
In the example above, memberchk tries tries to make '4', then '5' members of the list, which it succeeds in doing by inserting them into the free variable at the end in each case.
Then when you're done, just close it.

Remove pair from list, only if it exists

I'm attempting to make a predicate that takes a list of pairs and, if it finds the key in the list it will remove that item from the list and return the rest. However, it also needs to return the full list if the key given does not exist.
unmap(K, M1, M2):-
select(E, M1, MM1),
select(E, [(K, _)], K1),
unmap(MM1, K1, M2).
unmap(X, _, X).
Called with:
unmap(key1, [(key1, value1),(key2, value2),(key3, value3)], R).
Results in:
R = [(key2, value2), (key3, value3)]
Works, but theres a problem. I'm trying to make it return the identical list thats given if the key1 does not exist. Here's what it returns:
Calling:
unmap(key4, [(key1, value1),(key2, value2),(key3, value3)], R).
Returns:
R = key4
I think it's something to do with my terminating rule, but I'm not sure how to go about fixing it. Thanks very much in advance for all that can help.
Of course, you can do it with logical-purity! Here's how...
Let's call the actual relation pairs_key_unmapped/3. That's a somewhat more descriptive name. unmap/3 is just a wrapper for pairs_key_unmapped/3:
unmap(Key,Ps0,Ps) :-
pairs_key_unmapped(Ps0,Key,Ps).
The implementation of pairs_key_unmapped/3 is built on the predicates if_/3 and =/3 (a.k.a. equal_truth/3), as defined by #false in an answer to "Prolog union for A U B U C":
pairs_key_unmapped([],_,[]).
pairs_key_unmapped([P|Ps],K,Us) :-
P = (K0,_),
if_(K0=K, Ps=Us, (Us=[P|Us0],pairs_key_unmapped(Ps,K,Us0))).
Let's run some queries!
?- unmap(key1,[(key1,value1),(key2,value2),(key3,value3)],Ps).
Ps = [(key2,value2),(key3,value3)]. % succeeds deterministically
?- unmap(key4,[(key1,value1),(key2,value2),(key3,value3)],Ps).
Ps = [(key1,value1),(key2,value2),(key3,value3)]. % succeeds deterministically
Let's try something different... What if Key occurs twice in Ps0?
?- unmap(key1,[(key1,x),(key1,y)],Ps). % only the 1st occurrence is removed
Ps = [(key1,y)]. % succeeds deterministically
What if Ps0 is unknown, but Ps is known?
?- unmap(key4,Ps0,[(key1,value1),(key2,value2),(key3,value3)]).
Ps0 = [(key4,_A), (key1,value1),(key2,value2),(key3,value3)] ;
Ps0 = [(key1,value1),(key4,_A), (key2,value2),(key3,value3)] ;
Ps0 = [(key1,value1),(key2,value2),(key4,_A), (key3,value3)] ;
Ps0 = [(key1,value1),(key2,value2),(key3,value3) ] ;
Ps0 = [(key1,value1),(key2,value2),(key3,value3),(key4,_A) ] ;
false.
How about something a little more general?
?- unmap(Key,Ps0,[_,_]).
Ps0 = [(Key,_A),_B, _C ] ;
Ps0 = [(_A,_B), (Key,_C), _D ], dif(_A,Key) ;
Ps0 = [(_A,_B), (_C,_D) ], dif(_A,Key), dif(_C,Key) ;
Ps0 = [(_A,_B), (_C,_D), (Key,_E)], dif(_A,Key), dif(_C,Key) ;
false.
And what answers does the most general query give us?
?- unmap(Key,Ps0,Ps).
Ps0 = [], Ps = [] ;
Ps0 = [(Key,_A)|Ps] ;
Ps0 = [(_A,_B)], Ps = [(_A,_B)], dif(_A,Key) ;
Ps0 = [(_A,_B),(Key,_C)|_Z], Ps = [(_A,_B)|_Z], dif(_A,Key) ;
Ps0 = [(_A,_B),(_C,_D)], Ps = [(_A,_B),(_C,_D)], dif(_A,Key), dif(_C,Key) ...
The issue is with your base case:
unmap(X, _, X).
If your main predicate clause fails (the key isn't found), it reverts to the base case, which will instantiate your result (third argument) with only the key (first argument). Your base case should be:
unmap(_, X, X).
Which will instantiate the result (third argument) with the original list (second argument).
Note that the main clause could be simpler (this will work in GNU or SWI prolog):
unmap(K, M, R):-
select((K, _), M, M1),
unmap(K, M1, R), !.
The cut prevents backtracking to the base case if the first clause succeeds.
In SWI Prolog, the delete/3 predicate will work in your favor:
unmap(K, M, R) :-
delete(M, (K,_), R), !.
delete/3 is more strict in GNU Prolog and will not work in this case.
This isn't so much an answer to the question, but a simpler way of attacking it, without using the 'select' (or any other built-in predicates), and only using recursion.
Considering that the output list is just a list of items that didn't match the key, you need 2 main clauses, and iterate around the list. One where the key matches the head of the list, and one that doesn't.
unmap(_, [], []).
% head of the list matches key, do not add K/H to unmatched list (ie remove it)
unmap(K, [(H, _)|Tail], Unmatched) :-
H == K,
unmap(K, Tail, Unmatched).
% above rule fails, add H to unmatched list
unmap(K, [H|Tail], [H|Unmatched]) :-
unmap(K, Tail, Unmatched).
?- unmap(key1, [(key1, value1),(key2, value2),(key3, value3)], R).
R = [ (key2, value2), (key3, value3)] .
?- unmap(key4, [(key1, value1),(key2, value2),(key3, value3)], R).
R = [ (key1, value1), (key2, value2), (key3, value3)] .
So if the key doesn't exist, it just iterates around adding all list items, and so the input and output lists are identical.