I am facing a prolog problem regarding List and Term. Then my question is how to write a predicate
transform([a,b],X)
will return X = (a,b) Or vice versa
This is weird with me because I've never faced such term before. I tried with the built in =.. but
=..((a,b,c,d),X)
returns X=[',',a,(b,c,d)] which makes me deeply disappoint.
Thank you.
Check something like this:
transform([A], A):-
A=..[_].
transform([A,B], (A,B)):-
B=..[_].
transform([A,B,C|Tail], L):-
L=..[',',A,T],
transform([B,C|Tail], T).
The first clause is only needed if you want transform([Item], Item).
?- transform([a,b], X).
X = (a, b)
?- transform([a,b,c,d,e,f], X).
X = (a, b, c, d, e, f)
?- transform(L, (a,b,c,d,e,f,g))
L = [a, b, c, d, e, f, g]
Note that the term you are building does have a functor, it is ','/2, and it is shown with the parenthesis you are seeing.
Related
I have following source-code:
split_list(List, L, [R1|RN], Condition) :-
find_first(List, R1, Condition),
append(L, [R1|RN], List),
forall(member(X, L),
not(call(Condition, X))).
find_first([H|_], H, Condition) :- call(Condition, H), !.
find_first([_|T], X, Condition) :- find_first(T, X, Condition).
This Prolog program splits a list List into two lists L and [R1|RN]. R1 is the first element of List which satisfies the predicate Condition. L contains all elements in List before R1. L does not contain any element satisfying Condition. RN contains all elements which follow R1 in List.
My aim now is to write some predicate, which separates some list [a,b,c,D,d,f,e,f,d] into two lists [a, b, c] and [D, d, f, e, f, d] without instantiating the variable D.
I just tried the call:
split_list([a,b,c,_,d,f,e,f,d], L, R, var).
but this produces much solutions by instantiating _ by a or b or c and so on. How can I solve it?
From the looks of it, this is a more useful find_first (with argument order changed to be more sensible):
% P means previous, R means remainder
find_first_succ(Cond, L, P, [H|T]) :-
find_first_succ_(L, Cond, P, [H|T]).
find_first_succ_([H|T], Cond, [], [H|T]) :-
call(Cond, H), !.
find_first_succ_([H|T], Cond, [H|P], R) :-
find_first_succ_(T, Cond, P, R).
Result in swi-prolog:
?- find_first_succ(var, [a,b,c,_,d,f,e,f,d], P, R).
P = [a, b, c],
R = [_, d, f, e, f, d].
So, you don't need that problematic append.
I found some solution:
split_list(List, L, [R1|RN], Condition) :- member(R1, List), append(L, [R1|RN], List), call(Condition, R1).
I made some predicate, which saves a very complex list into a variable P.
Let's say:
pred(P) :-
P = [[1, a, b, c, 234],d].
Now I want to put this list into another predicate, let's say
pred2(P, L) :-
nth1(2, P, L).
My problem now is, I don't want to copy [[1, a, b, c, 234], d] as parameter into P. Is their a simple way, maybe to define an atom or another shortcut, e.g. 'test' := [[1, a, b, c, 234],d]. and call ?- pred2('test', L)?
The simple way is to call the predicate which you've defined:
pred2(L) :-
pred(P), % :- P = [[1, a, b, c, 234],d].
nth1(2, P, L).
This will "set" nay instantiate the logical variable P first, then use it to "set" L.
Note P has become an internal variable here. You don't have to set it when calling pred2. pred2 will call pred for you, to set P.
So far I've done my fair amount of research and I've tried different methods, however even after reading multiple stack overflow answers and even a PDF from Addison Wesley, I can't find the way to do it. Here is the code
use_module(library(func)).
% importing library "func"
scale([c, d, e, f, g, a, b]).
scale(c, major, [c, d, e, f, g, a, b]).
scale(c, minor, [c, d, e_b, f, g, a_b, b_b]).
%1st attempt
search(note, scale):- scale(note, scale).
%2nd attempt
scaleOf(note, type_scale):- scale(note, type_scale).
on(item,[item|rest]).
on(item,[disregardHead|tail]):-
scale(tail),
on(item, tail).
%3rd attempt
fatherOf(father,type, son):- scale(father, type, sons), search(son, type, sons).
search(son, type, []):- !, fail.
search(son, type, [son|l]):- !, true.
search(son, type, [c|l]):- search(son, type, l).
What am I attempting? Simple, something that can iterate through the predicate scale(c, [c, d, e, f, g, a, b]). But I can't get it right.
Edit: I have multiple predicates because someone else suggested creating a predicate that would differentiate one scale from the other. I thought I could cram it inside any algorithm but I guess PROLOG is not that lenient :p
You can do that with member/2 [swi-doc]. This can be used to search, unify with a member, or generate a list.
So you can search with:
search(Note, Scale, Item) :-
scale(Note, Scale, Items),
member(Item, Items).
It is important that Note, Scale, Item and Items start with an Uppercase, since identifiers with a lower case are constants or functors. Identifiers with an uppercase are variables.
This will thus unify Item with the items in the list, for the given sample data we for example obtain:
?- search(c, minor, Item).
Item = c ;
Item = d ;
Item = e_b ;
Item = f ;
Item = g ;
Item = a_b ;
Item = b_b.
So I am trying to
I am defining the sets with is_a(b, a), is_a(c, a), which for simplicity would look visually something like this:
a
b c
d e f g
I want to give in the list [b, c] and as a result get the list [d, e, f, g]
At the moment when I give in a node or a variable, then it can find everything that is underneath it with this method:
find_nodes(Root, Root) :-
\+ is_a(_, Root).
find_nodes(Root, X) :-
is_a(Node, Root),
find_nodes(Node, X).
Which when run gives me the result I need :
?- find_nodes(b, X).
X = d.
X = e.
But it is not in a list, so I have tried :
?- all_nodes([b, c], X).
all_nodes([], _).
all_nodes([H|T], [R|Res]):-
findall(L, find_nodes(H, L), R),
all_nodes(T, Res).
Which gives me - X = [[d, e], [f, g]|_4040], which consists of lists within lists, but I need just 1 list, that would be X = [d, e, f, g].
What am I doing wrong here?
EDIT
Like #lurker said findall returns a list and adding list to a list will give the result I get right now.
The one thing I also tried was using:
all_nodes([], _).
all_nodes([H|T], [R|Res]):-
find_nodes(H, R),
all_nodes(T, Res).
But well that one does not work either because It only gives me 1 element, which in this case is d and then f.
You can take advantage of the de facto standard findall/4 (*) predicate to solve the problem. This predicate is a variant of the standard findall/3 predicate that allows passing a tail for the list of solutions collected by the predicate. For example:
?- findall(N, (N=1; N=2; N=3), L, [4,5]).
L = [1, 2, 3, 4, 5].
In the following solution, I have renamed predicates and variables for clarity and modified your node leaf predicate:
is_a(a, b).
is_a(a, c).
is_a(b, d).
is_a(b, e).
is_a(c, f).
is_a(c, g).
leaf(Leaf, Leaf) :-
\+ is_a(Leaf, _).
leaf(Node, Leaf) :-
is_a(Node, Child),
leaf(Child, Leaf).
all_nodes([], []).
all_nodes([Node| Nodes], Leaves):-
findall(Leaf, leaf(Node, Leaf), Leaves, Tail),
all_nodes(Nodes, Tail).
Sample calls:
?- all_nodes([b, c], X).
X = [d, e, f, g].
?- all_nodes([a], X).
X = [d, e, f, g].
?- all_nodes([b], X).
X = [d, e].
(*) It's a built-in predicate in GNU Prolog, JIProlog, Lean Prolog, O-Prolog, SICStus Prolog, SWI-Prolog, XSB, and YAP (possibly others).
suppose i have this list in prolog:
[-0.791666666666667-[]-[predicate(a,b,c,d)]-[predicate_2(p,e,q,d,g)]]
there is way to split this in:
-0.791666666666667, [], [predicate(a,b,c,d)], [predicate_2(p,e,q,d,g)] ???
Split means have different pice of the list.
Maybe:
X = -0.791666666666667 Y = [] Z = [predicate(a,b,c,d)] etc...
Or another solution can be replace - with "," so it become a list with different elements?
You can use pattern matching. Similar to the way you use it on lists ([H|T]):
split(A, R) :- split(A, R, []).
split(A-B, R, Acc) :- split(A, R, [B|Acc]), !.
split(H, [H|T], T).
I'm using accumulator, because something like a-b-c is split by A-B into a-b and c.
EDIT: If you know you have 4 terms, you can use something like
split(A-B-C-D, A, B, C, D).
Trivial:
to_list([A-B-C-D], [A,B,C,D]).
Usage:
?- to_list([-0.791666666666667-[]-[predicate(a,b,c,d)]-[predicate_2(p,e,q,d,g)]],
L).
L = [-0.791667, [], [predicate(a, b, c, d)], [predicate_2(p, e, q, d, g)]].
Or do the pattern matching inline, it's rather wasteful to write a predicate for such a task, which seems rather one-off to me.