Merging two lists into a list of lists - list

I have two lists:
X = [a,b,c]
Y = [d,e,f]
I want the outcome to be:
Z = [[a,b,c], [d,e,f]]
However, when I use append I get:
Z=[a,b,c,d,e,f].
Any suggestions on how I should do this?

You may just create a list with both lists:
add_lists(X, Y, [X, Y]).
then add_lists([a,b,c], [d,e,f], Z) would yield Z = [[a,b,c], [d,e,f]].
You can also just inline this, Z=[X, Y]

gusbro's answer is what you should do using plain unification, but just commenting on what you said:
when I use append:
You can use append differently, and get the answer you want:
?- X=[a,b,c],
Y=[d,e,f],
append([X], [Y], Z).
X = [a, b, c],
Y = [d, e, f],
Z = [[a, b, c], [d, e, f]].

Related

Convert complex term to List of lists and then back to term with modified functor

you can use =.. to convert simple terms.
?- x(a,b,c) =.. A.
A = [x, a, b, c].
what about complex terms :
x(a,b(c,d)) ==> [x,a,[b,c,d]]
x(a,b(c,q(d))) ==> [x,a,[b,c,[q,d]]]
then as separate task i want to re-generate the terms with changed functor :
x(a,b(c,d)) ==> [x,a,[b,c,d]] ==> y(a,f(c,d))
deep_univ(X, Y) :-
X =.. [H|Rest],
(
Rest = []
-> Y = X
; maplist(deep_univ, Rest, ExpRest),
Y=[H|ExpRest]
).
rev_univ([H|Rest], Y) :-
maplist(rev_univ, Rest, RestT),
Y =.. [H|RestT].
rev_univ(H, H) :- \+ is_list(H).
?- T=x(a,b,c(d,e(f)), j), deep_univ(T, X), rev_univ(X, Y).
T = Y, Y = x(a, b, c(d, e(f)), j),
X = [x, a, b, [c, d, [e, f]], j]

prolog list insert at any position

New to Prolog, trying to write a predicate to give all the options that an element could be inserted in to a list at any position.
Ex:
ins(a, [b,c], R). should give:
R = [a,b,c]
R = [b,a,c]
R = [b,c,a]
which it does, but then gives an error 'Out of Global stack'. Is there a way to make this more deterministic, give the results and be done? When it is run in reverse ie. ins(X, Y, [a,b,c]). It gives the expected results then says false indicating it has completed.
Code:
app([],L,L).
app([H|T],L2,[H|L]) :-
app(T,L2,L).
ins(E, List, R) :-
R = R1,
app(R2, R3, R1),
app([E], R4, R3),
app(R2, R4, List).
Here is a link to run the code in an online compiler, SWISH (This also has an example of how I hope to use ins, but ins is the problem right now)
Any Help would be appreciated!
Did you notice how this went bad? First, Prolog was very nice and dandy and showed you how smart it is, and only later on it struck you: Buy. More. RAM. Now!
Wouldn't it be better if Prolog would be up front? Before showing any answer?
Well, you can force Prolog to do exactly this. Add a false at the end of your query like so:
?- ins(a, [b,c], R), false.
resource_error(_). % ERROR: Out of global stack
And the same you can do with your remaining program: Simply add false such that the remaining program still loops or runs out of space. I came up with the following minimal failure-slice
app([],L,L) :- false.
app([H|T],L2,[H|L]) :-
app(T,L2,L), false.
ins(E, List, R) :-
R = R1,
app(R2, R3, R1), false,
app([E], R4, R3),
app(R2, R4, List).
?- ins(a, [b,c], R), false.
That means that we have to modify something in the remaining visible part in order to get rid of that looping. In other words: As long as the visible part remains unmodified the error will persist — guaranteed!
For more on this technique to understand reasons for non-termination see failure-slice
The immediate fix would be to put the first app/3-goal last.
But there is something else: You used all kinds of variables that are difficult to fathom. Maybe stick to a more uniform scheme. Also, there is no need for appending [A] using app/3. You actually need only two app/3 goals.
Here is a simple implementation of this predicate:
ins(X, [], [X]).
ins(X, [H|T], [X,H|T]).
ins(X, [H|T], [H|T2]) :-
ins(X, T, T2).
It works in the directions you would expect it to:
?- ins(a, [b,c], R).
R = [a, b, c] ;
R = [b, a, c] ;
R = [b, c, a] ;
false.
?- ins(a, L, [a,b,c]).
L = [b, c] ;
false.
?- ins(X, [b,c], [a,b,c]).
X = a ;
false.
?- ins(X, L, [a,b,c]).
X = a,
L = [b, c] ;
X = b,
L = [a, c] ;
X = c,
L = [a, b] ;
false.
?- ins(a, X, Y).
X = [],
Y = [a] ;
X = [_5312|_5314],
Y = [a, _5312|_5314] ;
X = [_5312],
Y = [_5312, a] ;
X = [_5312, _5324|_5326],
Y = [_5312, a, _5324|_5326] ;
…
Prolog has an interesting predicate called select :
?- select(a, Out, [b,c]).
Out = [a, b, c] ;
Out = [b, a, c] ;
Out = [b, c, a] ;
false.
You can use it with another very usefull predicate called setof :
ins(Elem, In, Lst_Out) :-
setof(Out, select(Elem, Out, In), Lst_Out).
This gives :
?- ins(a, [b,c], Out).
Out = [[a, b, c], [b, a, c], [b, c, a]].

Prefix in Prolog

I'm new in Prolog.
I have a problem about predicate prefix but a little bit different.
I want to get a prefix of a list but until an element
The list can have repeat elements.
An example:
prefix(Element, List, Prefix)
prefix(c, [a,b,c,d,e,f], [a, b])
The element is not included.
What I have so far is this
prefix(X, [X|T], []).
prefix(X, [Y|T], [Y|Z]):-
prefix(X, T, Z).
But it does not work.
L = [a,b,c] ? prefix(b, L, Prefix).
no
?-
Thanks
With dif/2 you can explicitly state that for any member X preceding Element, X \== Element:
prefix(Element, [Element|_], []).
prefix(Element, [Head|List], [Head|Prefix]) :-
dif(Element, Head),
prefix(Element, List, Prefix).
or equally, because I wanted to use append/3 in the first iteration of my answer:
prefix(Element, List, Prefix) :-
append(Prefix, [Element|_Suffix], List),
maplist(dif(Element), Prefix).
For the suffix it is basically the same:
suffix(Element, List, Suffix) :-
append(_Prefix, [Element|Suffix], List),
maplist(dif(Element), Suffix).
If you don't want to use maplist(dif(Element), List):
all_dif(_, []).
all_dif(X, [H|T]) :- dif(X, H), all_dif(X, T).
Here is a solution using Definite Clause Grammars dcg and the non-terminal all_seq//2:
prefix(X, Xs, Ys) :-
phrase( ( all_seq(dif(X), Ys), [X], ... ), Xs).
... --> [] | [_], ... .
So the grammar (within phrase/2) reads:
There is
1. an initial sequence Ys with all elements different to X, followed by 2. X, followed by 3. anything.
There is still a downside, which is often the case when using DCGs: The implementation is not as determinate as it could be and thus leaves superfluous choicepoints around.
prefix(X,[X|T],[]).
prefix(X,[Y|T],Z) :- prefix(X,T,M) , Z = [Y|M].
output:
?- L = [a,b,c,d,e,f] , prefix(d,L,G). L = [a, b, c, d, e, f], G = [a,
b, c] .
?- L = [a,b,c,d,e,f] , prefix(e,L,G). L = [a, b, c, d, e, f], G = [a,
b, c, d] .
EDIT #1
the original code is working , use (,) instead of (?) as following.
prefix(X,[X|T],[]).
prefix(X,[Y|T],[Y|Z]) :- prefix(X,T,Z).
output:
?- prefix(d , [a,b,c,d,e] , G). G = [a, b, c]
?- L = [a,b,c] , prefix(b, L, Prefix).
L = [a, b, c],
Prefix = [a] .
EDIT #2
as user false mentioned in comment, I can confirm that you are right, but in my solution, I assume that the list contains unique elements:
prefix(d,[d,d],[d]) succeeds - it should fail ,

How to predicate all pairs in a given list in Prolog?

When given a list I would like to compute all the possible combinations of pairs in the list.
e.g 2) input is a list (a,b,c) I would like to obtain pairs (a,b) (a,c) (b,c)
e.g 1) input is a list (a,b,c,d) I would like to obtain pairs (a,b) (a,c) (a,d) (b,c) (b,d) and (c,d)
Using select/3 twice (or select/3 once and member/2 once) will allow you to achieve what you want here. I'll let you work out the details and ask for help if it's still troublesome.
BTW, Prolog syntax for list isn't (a, b, c) but [a, b, c] (well, it's syntactic sugar but I'll leave it at that).
edit: as #WillNess pointed out, you're not looking for any pair (X, Y) but only for pairs where X is before Y in the list.
DCGs are a really good fit: as #false described, they can produce a graphically appealing solution:
... --> [] | [_], ... .
pair(L, X-Y) :-
phrase((..., [X], ..., [Y], ...), L).
Alternatively, if you use SWI-Prolog, a call to append/2 does the trick too, in a similar manner, but is less efficient than DCGs:
pair2(L, X-Y) :-
append([_, [X], _, [Y], _], L).
You can do it with a basic recursion, as #WillNess suggested in his comment. I'll leave this part for him to detail if needed!
OK, so to translate the Haskell definition
pairs (x:xs) = [ (x,y) | y <- xs ]
++ pairs xs
pairs [] = []
(which means, pairs in the list with head x and tail xs are all the pairs (x,y) where y is in xs, and also the pairs in xs; and there's no pairs in an empty list)
as a backtracking Prolog predicate, producing the pairs one by one on each redo, it's a straightforward one-to-one re-write of the above,
pair( [X|XS], X-Y) :- member( ... , XS) % fill in
; pair( XS, ... ). % the blanks
%% pair( [], _) :- false.
To get all the possible pairs, use findall:
pairs( L, PS) :- findall( P, pair( L, P), PS).
Consider using bagof if your lists can contain logical variables in them. Controlling bagof's backtracking could be an intricate issue though.
pairs can also be written as a (nearly) deterministic, non-backtracking, recursive definition, constructing its output list through an accumulator parameter as a functional programming language would do -- here in the top-down manner, which is what Prolog so excels in:
pairs( [X|T], PS) :- T = [_|_], pairs( X, T, T, PS, []).
pairs( [_], []).
pairs( [], []).
pairs( _, [], [], Z, Z).
pairs( _, [], [X|T], PS, Z) :- pairs( X, T, T, PS, Z).
pairs( X, [Y|T], R, [X-Y|PS], Z) :- pairs( X, T, R, PS, Z).
Here is a possible way of solving this.
The following predicate combine/3 is true
if the third argument corresponds to a list
contains pairs, where the first element of each pair
is equal to the first argument of combine/3.
The second element of each pair will correspond to an item
of the list in the second argument of the predicate combine/3.
Some examples how combine/3 should work:
?- combine(a,[b],X).
X = [pair(a,b)]
?- combine(a,[b,c,d],X).
X = [pair(a,b), pair(a,c), pair(a,d)]
Possible way of defining combine/3:
combine(A,[B],[pair(A,B)]) :- !.
combine(A,[B|T],C) :-
combine(A,T,C2), % Create pairs for remaining elements in T.
append([pair(A,B)],C2,C). % Append current pair and remaining pairs C2.
% The result of append is C.
Now combine/3 can be used to define pair/2:
pairs([],[]). % Empty list will correspond to empty list of pairs.
pairs([H|T],P) :- % In case there is at least one element.
nonvar([H|T]), % In this case it expected that [H|T] is instantiated.
pairs(H,T,P).
pairs(A,[B],[pair(A,B)]) % If remaining list contains exactly one element,
:- !. % then there will be only one pair(A,B).
pairs(A,[B|T],P) :- % In case there are at least two elements.
combine(A,[B|T],P2), % For each element in [B|T] compute pairs
% where first element of each pair will be A.
pairs(B,T,P3), % Compute all pairs without A recursively.
append(P2,P3,P). % Append results P2 and P3 together.
Sample usage:
?- pairs([a,b,c],X).
X = [pair(a, b), pair(a, c), pair(b, c)].
?- pairs([a,b,c,d],X).
X = [pair(a, b), pair(a, c), pair(a, d), pair(b, c), pair(b, d), pair(c, d)].
You can use append/ to iterate through the list:
?- append(_,[X|R],[a,b,c,d]).
X = a,
R = [b, c, d] ;
X = b,
R = [c, d] ;
X = c,
R = [d] ;
X = d,
R = [] ;
false.
Next, use member/2 to form a pair X-Y, for each Y in R:
?- append(_,[X|R],[a,b,c,d]), member(Y,R), Pair=(X-Y).
X = a,
R = [b, c, d],
Y = b,
Pair = a-b ;
X = a,
R = [b, c, d],
Y = c,
Pair = a-c ;
X = a,
R = [b, c, d],
Y = d,
Pair = a-d ;
X = b,
R = [c, d],
Y = c,
Pair = b-c ;
X = b,
R = [c, d],
Y = d,
Pair = b-d ;
X = c,
R = [d],
Y = d,
Pair = c-d ;
false.
Then, use findall/3 to collect all pairs in a list:
?- findall(X-Y, (append(_,[X|R],[a,b,c,d]), member(Y,R)), Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].
Thus, your final solution can be expressed as:
pairs(List, Pairs) :-
findall(X-Y, (append(_,[X|R],List), member(Y,R)), Pairs).
An example of use is:
?- pairs([a,b,c,d], Pairs).
Pairs = [a-b, a-c, a-d, b-c, b-d, c-d].

Prolog GNU - Having a difficult time with this, lists and recursion

So , i still don't completely understand how lists and recursion work in prolog, could be why i am having trouble with this, but i don't even know how to begin this problem.
There is a list of friends.
f(a,b).
f(a,c).
f(a,d).
f(b,c).
f(b,e).
f(b,f).
f(c,e).
f(c,g).
f(g,e).
etc..
I have to find if someone is a friend through someone else up to two friends of friends.
So example if i did
fof(a,e, List).
Then i should get
List = [a, b, e];
List = [a, c, e];
List = [a, c, g, e]; <-- anything past this point won't work
So basically you check yourself, then see if your friends is friends with person2, then see if their friends are friends with person2, if they are then add to a list.
not exactly sure how to execute this though.
Ok, so i got something similar to what i need.
fb(X,X,_).
fb(X,Y,List) :-
friend(X,Y),
X \== Y,
List = [X,Y].
fb(X,Y,List) :-
friend(X,Z),friend(Z,Y),
X \== Y, X \== Z, Z \== Y,
List = [X,Z,Y].
fb(X,Y,List) :-
friend(X,Z),friend(Z,Q),friend(Q,Y),
X \== Y,X \== Z, X \== Q, Z \== Q, Z \== Y, Q \== Y,
List = [X,Z,Q,Y].
This seems to work, but it seems i could condense this with recursion, just not sure how.
I assume you've defined friend(X,Y) to be true if either f(X,Y) or f(Y,X).
Your problem can be solved recursively by adding an argument that specifies the maximum path length allowed, and decrementing that before each recursive call.
fof(X,X,[X],_).
fof(X,Z,[X|Path],N) :-
N >= 1,
friend(X,Y),
M is N-1,
fof(Y,Z,Path,M),
\+ member(X,Path). % no duplicates
To get to a friend of a friend via max. two intermediaries, i.e. in three steps:
?- fof(a,e,L,3).
L = [a, b, c, e] ;
L = [a, b, e] ;
L = [a, c, e] ;
L = [a, c, g, e] ;
L = [a, c, b, e] ;
false.
?- fof(a,z,L,3).
false.