Reputation: 602
I wrote an algorithm and tried to implement it in Prolog, but what I found out is that the parenthesis do not work as expected: what is written in is not all done before exiting the parenthesis. Here is the code:
%1. If the first member of L1 is smaller than L2
% A. If the first member of L1 is not equal to Last
% Than: A.1 Add the first member of L1 to the first member of NL
% Begin recurssion on the resumption of L1, L2 resumption of NL
% and Last from L1.
% Else: A.2 begin the recursion on resumption of L1, L2 with the
% first member and L3 with the first member.
% 2. If the first member in L1 is equal to the first member of L2,
% Than: Start recursion on resumption of L1 and L2 (with its first
% member) and Last = *.
% 3. If the first member of L1 is bigger than the first membber of L2
% Than: begin recursion on L1 with the first member, resumption of
% L2 and Last = x. %(x != * only for debugging)
%
*/
make_list([X1|L1], [X2|L2], [X3|NewL], Last) :-
(
X1 < X2,
(
X1 \= Last, %A
X3=X1;
make_list(L1, [X2|L2], NewL, X1) %B
), %Why those parenthesis do not work as expected?
! %green cut
);
(
X1=X2,
make_list(L1, [X2|L2], [X3|NewL], *)
),
!
;
make_list([X1|L1], L2, [X3|NewL], *).
My question is how to make it work as expected and why does B
not work once A
is done? After all it is also in the same parenthesis, e.g.:
?- make_list([6,6,10,20],[10,25,30],L, -).
L = [6|_G849] % (should be [6,20]).
EDIT1: make_list should find all members in L1
that are not in L2
and put them in NewL, while Last
stores the last member in L1
that was parsed.
EDIT2: no -> are allowed (this is howmework). If someone could show me how to express if then else in prolog, that could be great.
Upvotes: 1
Views: 4131
Reputation: 71065
I suspect that "green cut" of yours is not green at all; you have
( A ; B ), !
so on exit from (A ; B)
the first time, if A succeeded, B
won't be tried anymore - that is what the cut !
is saying here: don't try any more.
If you want B
to be tried too, remove the cut !
.
If-then-else is:
ifte(A,B,C):- A, B.
ifte(A,B,C):- \+A, C.
We can spare us a not
by using a cut
,
ifte(A,B,C):- A, !, B.
ifte(A,B,C):- C.
About your code: we express and then
with comma: A,B
. To output the Last it's easiest to use a working predicate, with additional argument, "seen-last"; and in the base case finally the last seen and the output would be unified.
Upvotes: 1
Reputation: 7493
In short: !/0
applies at the predicate level: here you'd want it to apply to some block level where blocks would be delimited by (
and )
. This notion of cut applied to blocks does not exist in Prolog. A cut will erase all encountered choice points up until its location in a predicate.
And instead of writing your code with a lot of (;)/2
usage, consider introducing new clauses instead, for readability (precisely because we do not like parenthesis and figuring out (;)/2
and (,)/2
priorities):
c :- A; B.
can be written
c :- A.
c :- B.
It will quite often be better this way. Better to produce the code easily, better to maintain it, to read it and to expand it.
I didn't look at your predicate in depth or anything, just wanted to mention those two things.
Upvotes: 1