I need to write a predicate in Prolog that given a list that return false if there are 2 consecutive '/', otherwise it returns true. This is what I've done so far, it works only in certain cases. For what I can see it works correclty only if the list has an even number of elements.
t([]) :- !.
t([X, Y | Xs]) :-
X \= '/',
Y \= '/',
!,
t(Xs).
t([X, Y | Xs]) :-
X \= Y,
t(Xs).
Could you please help me?
Thank you in advance.
CodePudding user response:
First of all it is so much easier to formulate it the other way around:
not_t(Xs) :-
append(_,[/,/|_],Xs).
But then, we would have to negate this which makes the definition quite brittle. The best is to use iwhen/2:
:- set_prolog_flag(double_quotes, chars).
t(Xs) :-
iwhen(ground(Xs), \ not_t(Xs)).
?- t("abc").
true.
?- t("abc//").
false.
?- t([X,/,Y]).
caught: error(instantiation_error,_2027607)
So this definition works nicely for lists of characters, but it produces an error for more general queries. Which is, btw, much better than to produce an incorrect answer. But can't this be improved?
t2([]).
t2([E|Es]) :-
t2(Es, E).
t2([], _).
t2([E|Es], F) :-
dif([E,F],[/,/]),
t2(Es, E).
?- t2([X,/,Y]).
dif(X,/), dif(Y,/).
All three-element lists whose first and last element is different from /
are solutions.