/* CS 1621 Fall 2005 Yet more demos of Prolog stuff: the cut, I/O and other cool stuff */ /* Predicate to generate unending sequence of positive integers */ getnextval(1). getnextval(N) :- getnextval(M), N is M+1. /* Predicate to write out all integers up to N */ writeval(X) :- write(X), nl. writeints(N) :- N > 0, getnextval(X), writeval(X), X >= N. sum_to(1,1). /* bad version of sum */ sum_to(N,RESULT) :- N1 is N - 1 , /* infinite backtracking */ sum_to(N1,M) , /* possible */ RESULT is N + M. nsum_to(1,1) :- !. /* better version of sum */ nsum_to(N,RESULT) :- N1 is N - 1 , /* cut stops backtracking */ nsum_to(N1,M) , RESULT is N + M. /* this predicate never terminates -- writes only first result since sum_to gets into an infinite recursive loop upon backtracking */ sums_to(N) :- getnextval(M), sum_to(M, R), write(R), nl, M >= N. /* cut in nsum_to ensures proper working for valid N */ nsums_to(N) :- getnextval(M), nsum_to(M, R), write(R), nl, M >= N. /* cut fail used to weed out incorrect input */ nnsums_to(N) :- N < 1, write('Out of range'), !, fail. nnsums_to(N) :- getnextval(M), nsum_to(M, R), write(R), nl, M >= N. /* Attempts to reenter until input is valid, but does not work because read and write succeed only in forward direction */ nrunit1 :- write('Enter a positive integer > '), read(N), N > 0, nsums_to(N). /* This one works due to the predefined predicate repeat -- if we backtrack PAST write and then go forward again, it succeeds again */ nrunit2 :- repeat, write('Enter a positive integer > '), read(N), N > 0, nsums_to(N). /* Alternative approach -- if input is invalid, say so and quit. */ nnrunit1 :- write('Enter a positive integer > '), read(N), nnsums_to(N). /* Simple demonstration of a quiz using prolog */ askquestion :- write('Who is looking for the 6-fingered man?'), nl, write(' 1) Prince Humperdink'), nl, write(' 2) Inigo Montoya'), nl, write(' 3) Fezzik'), nl, write(' 4) Vizzini'), nl. /* Note the cut in the predicate below. What would happen to the quiz predicate without the cut in this predicate? Try it! */ getanswer(N) :- repeat, nl, write('Enter a number between 1 and 4 > '), read(N), N >= 1, N =< 4, !, write(' -- Thank you -- '). /* Note that the overall predicate succeeds whether or not the answer to the question is correct. */ quiz :- askquestion, getanswer(X), X == 2, nl, write('Correct! Well done!'), !. quiz :- nl, write('Sorry, the answer is 2 -- Inigo Montoya'). /* Next programs demo how using cuts affects execution. For nextval, cut makes program incorrect. For member(X,Y), cut improves effi- ciency of program when X and Y are both instantiated, but it also eliminates use of member(X,Y) to sequence through contents of Y */ nextval1(1) :- !. nextval1(N) :- nextval1(M), N is M+1. nextval2(1). nextval2(N) :- nextval2(M), N is M+1, !. member(X,[X|_]). member(X,[_|Y]) :- member(X,Y). member2(X,[X|_]) :- !. member2(X,[_|Y]) :- member2(X,Y). /* Demos problems with simple read and write in Prolog. Note output */ test :- read(X), write(X). /* This solves the writing problem, putting each character of the list one at a time. Input is still a problem though (period and quotes are necessary). */ nwrite([]) :- !. nwrite([H|T]) :- put(H), nwrite(T). test2 :- read(X), nwrite(X). /* Now string input can be typed just as we are accustomed */ nread([H|T]) :- get0(H), H \== 10, nread(T). nread([]) :- !. test3 :- nread(X), nwrite(X).