Related
HI I would like to know how a method that finds out if two members of a list in Prolog are adjacent as the catch is that the first and the last elements are checked if they are adjacent something like
(b,c,[b,a,d,c])
would give yes they are adjacent. I already have this code
adjacent(X, Y, [X,Y|_]).
adjacent(X, Y, [_|Tail]) :-
adjacent(X, Y, Tail).
but I do not know how to include the head of the list and the last elments as well being compared for being adjacent. If you are really good maybe you can tell me also how it is possible to make something like this
(c,b,[a,b,c,d])
to be true I mean the elements are adjacent no matter which exactly is first.
You can make use of last/2 predicate [swi-doc] to obtain the last element of the list. But you can not use this in the recursive call, since otherwise it will each element in the list pair with the last element as well.
The trick is to make a helper predicate for the recursive part, and then make the adjacent/3 predicate to call the recursive one you wrote yourself, or one where we match with the last element:
adjacent(X, Y, L) :-
adj(X, Y, L).
adjacent(X, Y, [Y|T]) :-
last(T, X).
adj(X, Y, [X,Y|_]).
adj(X, Y, [_|T]) :-
adj(X, Y, T).
Relations about lists can often be described with a Definite Clause Grammar dcg.
A first attempt might be:
adjacent(A, B, L) :-
phrase(adjacent(A, B), L). % interface to DCG
adjacent(A,B) -->
..., ( [A,B] | [B,A] ), ... .
... --> [] | [_], ... .
Yet, this leaves out cases like adjacent(a,d,[a,b,c,d]). One possibility would be to add another rule, or maybe simply extend the list to be considered.
adjacent(A, B, L) :-
L = [E,_|_],
append(L, [E], M),
phrase(adjacent(A, B), L).
I'm trying to solve a problem in SWI-Prolog. I have a list of suitable elements (constants) obtained with.
suitables(L) :- setof(X, isSuitable(X), L).
Each element from above has a score via a functor, and I need all the subsets that have a score > 10. I know how to get the score sum:
scoreSum([], 0).
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest.
And the condition can be expressed like this:
cond(L) :- scoreSum(L, R), R > 10.
How do I get all the subsets matching the given condition? I can get the subsets based on the answer here, but how do I iterate over that result to get only the subsets matching the condition?
Provided scoreSum/2 starts with scoreSum([H|T], Tot) :- ...
seq_subseq([], []).
seq_subseq([_|Es], Fs) :-
seq_subseq(Es, Fs).
seq_subseq([E|Es], [E|Fs]) :-
seq_subseq(Es, Fs).
possiblesubset(S) :-
suitables(L),
seq_subseq(L, S),
cond(S).
?- setof(S, possiblesubset(S), Subs).
?- setof(S, (suitables(L), seq_subseq(L,S), cond(S)), Subs). % No L^ needed ; there is only one L.
However, it is rather unusual to represent such sets explicitly, simply because Prolog can generate them so efficiently.
I think I found the solution I needed, although I'm not sure if it's efficient or the recommended way. Provided the following functors:
isSuitable(X) :- ...
scoreSum([], 0).
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest.
And the condition:
cond(L) :- scoreSum(L, R), R > 10.
I can get only the sets that meet the given condition:
suitables(L) :- setof(X, isSuitable(X), S), setof(R, (powerset(S, R), cond(R)),L).
Where powerset gives me all the subsets of the given set:
powerset([], []).
powerset([_|T], P) :- powerset(T,P).
powerset([H|T], [H|P]) :- powerset(T,P).
So instead of getting all the combinations, I've based on this question to get all sets of the list.
This is a homework question, i have pretty much the rest of the code done out, and the last part that i have to do is create an insert algorithm.
insert(I,T1,T2) - is true if T2 is the binary tree resulting from I being
inserted into binary tree T1.
so far my code for this part is...
insert(I,T1,T2) :- bTTree(T1(X,L,_), bTTree(T2(X,L,I).
insert(I,T1,T2) :- bTTree(T1(nil,nil,nil),bTTree(T2(I,nil,nil).
insert(I,T1,T2) :- bTTree(T1(X,L,_),bTTree(T2(X,L,I).
I don't know if i'm going in the right direction with this or not.
Any help would be greatly appreciated.
My completed Code (if you need it):
isempty(nil) :- !.
isempty(tree(nil,nil,nil)).
bTTree(tree(_,Left,Right)) :- binaryTree(Left), binaryTree(Right).
%traversals.
%preorder -- N,Left,Right
preorder(tree(N,_,_),N).
preorder(tree(_,Left,_),N) :- preorder(Left,N).
preorder(tree(_,_,Right),N) :- preorder(Right,N).
%inorder -- Left,N,Right.
inorder(tree(_,Left,_), N) :- inorder(Left,N).
inorder(tree(N,_,_), N).
inorder(tree(_,_,Right), N) :- inorder(Right,N).
%postorder -- Left,Right,N
postorder(tree(_,Left,_),N) :- postorder(Left,N).
postorder(tree(_,_,Right),N) :- postorder(Right,N).
postorder(tree(N,_,_),N).
search(t,I) :- bTTree(t(I,_,_)).
search(t,I) :- bTTree(t(_,I,_)).
search(t,I) :- bTTree(t(_,_,I)).
search(t,I) :- bTTree(t(_,N,_)), search(N,I).
search(t,I) :- bTTree(t(_,_,N)), search(N,I).
height(t,H) :- bTTree(t(nil,nil,nil)), H is 0.
height(t,H) :- bTTree(t(N,nil,nil)), H is 1.
height(t,H) :- bTTree(t(_,Left,Right)),
height(Left, H1),
height(Right, H2),
H is max(H1,H2) + 1.
insert(I,t1,t2) :- bTTree(t1(X,L,_)),
bTTree(t2(X,L,I)).
insert(I,t1,t2) :- bTTree(t1(nil,nil,nil)),
bTTree(t2(I,nil,nil)).
insert(I,t1,t2) :- bTTree(t1(X,L,_)),
bTTree(t2(X,L,I)).
bTTree(T1(X,L,_)) is a syntax error (apart in SWI-Prolog, after enabling the extension set_prolog_flag(allow_variable_name_as_functor, true) ).
Another problem is that bTTree/1 misses the base case, it will always fail after it completed the recursion. What's its purpose ? In Prolog usually functors are assumed as formally declared symbols, there is no point in having an 'indirection' like bBBtree/1 just to introduce a term like tree/3.
And of course, you should stick to the same representation for a data structure in a program: now you use tree, or t, or t1, or t2, ...
I think that before working on insertion those problems should be solved...
Let's say there is a simple database of people in Prolog
person(john).
person(mary).
person(john).
person(susan).
I need to match the entires exactly once:
john-mary, john-john, john-susan, mary-john, mary-susan, john-susan
I tried coming up with something like this:
match:- person(X),!,person(Y), write(X),write(-), write(Y),nl.
run:- person(X), match(X), fail.
But it's matching many times, and matches a person to him/herself, which shouldn't be.
Basically, what I need is to iterate over all Xs and make Prolog to look strictly "below" for Ys.
A quick solution would be to number your people:
person(1, john).
person(2, mary).
person(3, john).
person(4, susan).
Then you could match people like this:
match(X-Y) :-
person(I, X), person(J, Y), I < J.
Since you have two john entries, I'm not sure any other solution is going to work. Normally you could fake an ordering using #>/2 but that would require your atoms to be unique, and since they aren't, it would prevent the john-john solution.
Edit: Since we're willing to use findall/3 to materialize the database of people, we can treat this as a list problem and find a functional solution. Let's get all the combinations in a list:
combinations([X|Rest], X, Y) :- member(Y, Rest).
combinations([_|Rest], X, Y) :- combinations(Rest, X, Y).
With this predicate in hand, we can find the solution:
combined_folks(People) :-
findall(P, person(P), Persons),
findall(X-Y, combinations(Persons, X, Y), People).
?- combined_folks(X).
X = [john-mary, john-john, john-susan, mary-john, mary-susan, john-susan].
That actually turned out to be pretty clean!
person(john).
person(mary).
person(john).
person(susan).
match :- findall(P,person(P),People), match_all(People).
match_all([_]) :- !.
match_all([P|People]) :- match_2(P,People), match_all(People).
match_2(_,[]) :- !.
match_2(P1,[P2|People]) :- format('~a-~a~n',[P1,P2]), match_2(P1,People).
?- match.
I'm interested in formulae made up from lots of conjunctions (part of a larger problem). I want to write a program that takes something like this:
:- get_params(conj(conj(a,b),c),X)
and returns a list of all the parameters of the conjunctions i.e. X=[a,b,c]. At the moment I can do
:- get_params(conj(a,b),X) to get X=[a,b]
using simple Prolog pattern matching but how would you go about doing things such as
:- get_params(conj(conj(a,b),c),X) to get X=[a,b,c]
It seems really simple but I've been struggling all day!
Since you are describing a list, consider using DCG notation:
params(conj(A,B)) --> !, params(A), params(B).
params(X) --> [X].
Example:
?- phrase(params(conj(conj(a,b),c)), Ps).
Ps = [a, b, c].
Assuming that all conj functors are binary:
get_params(X, Y, L) :-
get_params(X, L1),
get_params(Y, L2),
append(L1, L2, L).
get_params(conj(X, Y), L) :-
get_params(X, Y, L), !.
get_params(A, [A]).