
/* Example showing how backtrack works */

a :- write('a1 '), b, b.
a :- write('a2 '), b.
b :- write('b1 '), c.
b :- write('b2 '), c.
b :- write('b3 '), fail.
c :- write('c ').


/* Example with CUT showing how backtrack works */

aa :- write('a1 '), bb, bb.
aa :- write('a2 '), bb.
bb :- !,write('b1 '), cc.
bb :- write('b2 '), cc.
bb :- write('b3 '), fail.
cc :- write('c ').


/* Cut - confirming the choice of a rule: */

sum_to(N,1) :- N=<1, !.
sum_to(N,R) :-
        N1 is N-1,
        sum_to(N1,R1),
	R is R1 + N.

sum_toWrong(N,1) :- N=<1.
sum_toWrong(N,R) :-
        N1 is N-1,
        sum_toWrong(N1,R1),
	R is R1 + N.

/* Better to use \+ than CUT if possible, where \+ is built-in
   "negation by failure": */

sum_to2(N,1) :- N=<1.
sum_to2(N,R) :-
        \+(N=<1),
        N1 is N-1,
        sum_to2(N1,R1),
	R is R1 + N.


/* Cut - forced failure: */

income(peter,400000).
foreigner(peter).

average_taxpayerWrong(X) :- foreigner(X), fail.
average_taxpayerWrong(X) :- income(X,I), I < 500000.

average_taxpayer(X) :- foreigner(X), !, fail.
average_taxpayer(X) :- income(X,I), I < 500000.

average_taxpayer_built-in(X) :- \+foreigner(X), income(X,I), I < 500000.


/* Negation as failure (built-in in gprolog as prefix operator \+),
   but one could make it directly: */

not(X) :- call(X), !, fail.
not(X).


/* Cut - terminating generate-and-test code after first solution found: */

/* Divide N1 by N2 */
divide_wrong(N1, N2, Result) :-
        is_integer(Result),
	div_test(N1, N2, Result).

/* Generate all integers */
is_integer(1).
is_integer(X) :- is_integer(Y), X is Y+1.

/* Test for N1/N2 = D */
div_test(N1,N2,D) :-
      P1 is N2*D,
      P2 is N2*(D+1),
      P1 =< N1,
      P2 > N1.

/* Divide N1 by N2 */
divide(N1, N2, Result) :-
        is_integer(Result),
	div_test(N1, N2, Result),
	!.


/* CUTs are often problematic if a predicate is later used in other ways
   than assumed when designing it. Try number_of_parents(eve, 2): */

number_of_parents(adam, 0) :- !.
number_of_parents(eve, 0) :- !.
number_of_parents(X, 2).


