Reputation: 77
I have this code that return a lot of solutions, but I only need the first list, I think that I must work with some cut but I'm new to Prolog and I don't find where i must put it.
list_s(_,[],_) :-
!.
list_s(P,[P|Ps],ListS) :-
list_slope(P,Ps,ListS).
list_s(pt(X,Y),[pt(A,B)|Ps],ListS) :-
angle(pt(X,Y),pt(A,B),R),
new_s(R,pt(A,B),Ns),
append(Nls,[Ns],ListS),
!,
list_s(pt(X,Y),Ps,Nls).
I have tried to put it after the append/3
but that doesn't work.
How can I fix this?
EDIT: I think that the problem is with the append maybe i need change or improve this function.
EXAMPLE:
1 ?- list_slope(pt(2,2),[pt(1,1),pt(2,9),pt(3,8),pt(4,7)],L).
L = [slope(0.3805063771123649, pt(4, 7)), slope(0.16514867741462683, pt(3, 8)), slope(0.0, pt(2, 9)), slope(0.7853981633974483, pt(1, 1))] ;
L = [_G2260, slope(0.3805063771123649, pt(4, 7)), slope(0.16514867741462683, pt(3, 8)), slope(0.0, pt(2, 9)), slope(0.7853981633974483, pt(1, 1))] ;
L = [_G2260, _G2266, slope(0.3805063771123649, pt(4, 7)), slope(0.16514867741462683, pt(3, 8)), slope(0.0, pt(2, 9)), slope(0.7853981633974483, pt(1, 1))] ;
L = [_G2260, _G2266, _G2272, slope(0.3805063771123649, pt(4, 7)), slope(0.16514867741462683, pt(3, 8)), slope(0.0, pt(2, 9)), slope(0.7853981633974483, pt(1, 1))]
Upvotes: 0
Views: 1169
Reputation: 18663
Instead of using cuts or discarding (apparently wrong) solutions, best to rewrite the code to avoid the unwanted choice-points in the first place. For example, assuming that the predicate is called always with the first two arguments bound:
list_slope(Point, Points, Slopes) :-
% change argument order to exploit
% first-argument indexing
list_slope_(Points, Point, Slopes).
list_slope_([], _, []).
list_slope_([pt(A,B)| Points], pt(X,Y), [Slope| Slopes]) :-
angle(pt(X,Y), pt(A,B), Angle),
new_slope(Angle, pt(A,B), Slope),
list_slope_(Points, pt(X,Y), Slopes).
This will give, however, the slopes in the reverse order compared with your original code. If the reverse order is required, you can get it easily using an accumulator:
list_slope(Point, Points, Slopes) :-
% change argument order to exploit
% first-argument indexing
list_slope_(Points, Point, [], Slopes).
list_slope_([], _, Slopes, Slopes).
list_slope_([pt(A,B)| Points], pt(X,Y), Acc, Slopes) :-
angle(pt(X,Y), pt(A,B), Angle),
new_slope(Angle, pt(A,B), Slope),
list_slope_(Points, pt(X,Y), [Slope| Acc], Slopes).
Upvotes: 1
Reputation: 3407
If you want only the first result of a Prolog predicate you can simply do
once(some_predicate(Result))
Upvotes: 1