EXERCISE SHEET 3

{This exercise is about tracing and lists. 
This exercise needs the file called "likes", which contains fragments 
of prolog for three different phases of the exercises.}

{Now you can load it into prolog...}

	sicstus
	[likes].

{The first part of the file deals with my personal preferences with
respect to certain animals. The predicate assess(X) succeeds if I like
or dislike X, and fails if I have no preferences. There are some
animals I dislike outright, and others I definitely like. For the
rest, I try and think of an animal they are similar to, and assess
whether I like that or not. Look at the program, and see if you get
the gist. Then try it out on these few examples, to get the idea: (for
this exercise we will use the cut operator to prevent sicstus from
giving all solutions...)}

	assess(rabbits),!.

	assess(bears),!.

	assess(camels),!.

{So far so good. See if you can work out why the next four come up with the
answers they do:}

	assess(lions),!.

	assess(tigers),!.

	assess(geese),!.

	assess(pigeons),!.

{OK, that's got the idea, the program seems to work reasonably well. Let's see
if we can crash it:}

	assess(frogs),!.

	assess(koalas),!.

{Oh dear! We'll have to find out what's wrong. You can look at the program and
work it out for yourself, if you like, or take this opportunity to see the
trace package in action. First, let's see what happens when we trace something
we know works. At each step, just creep, ie. hit a return. When it gets to
call ( 6) or so, give a g command to see what function calls are waiting for
this predicate to succeed.}

	trace.
	assess(pigeons).

{That may help you follow what goes on in this program. Let's try out the
spy command:}

	notrace.
	spy(assess).

{This time, answer each ? by l (I mean lower case L), to leap to the next 
spy-point. When you get to about call ( 22), hit a "g" to see what goals are 
pending. This may give you an idea what's happening if you haven't one 
already... Use the "a" command to abort the rest of the execution.}

	assess(koalas).

{Now to stop spying on assess, and start spying on similar:}

	nospy(assess).
	spy(similar).

{Creep through the following. See where you get a "+" in the first column.}

	assess(dingoes).

{For this next one, answer each call with s for skip.  Type return on Exit
lines}

	assess(geese).

{That's the end of the first part of the exercise sheet, now to continue
tracing with the second part, the mystery function... Answer the M = blah
type responses with a return rather than a ;.}

	f(2, M).

	f(3, M).

	f(4, M).

{For this last one, answer the M = 89 question with a ; rather than return.}

	f(10, M).

{Guess what the function does if you feel up to it... We'll use trace to look
at it in more detail.}

	trace.

{Now go through this creeping, but skipping some of the calls to f.
You'll eventually get the M = 89 from last time. Hit a ; at it, and
creep from there onwards. See what happens? If you don't, wait 'til you get to
call 460 and give a g command. If you still don't see why it goes awry, ask
someone...}

	f(10, M).

{Now we leave tracing and get onto lists. Here are some unifications for you
to try.  Before you type the following in, try to guess what the outcome
is.  Don't just type in without thinking.}

	X = .(a, .(b, .(c, []))).

	X = .(D, .(e, [f, G])).

	X = .(a, b).

{Be careful with that one!}
{Did you manage to predict what had happened?}

	.(a, .(b, .(c, [d, e, f]))) = [X|Y].

	X = [a|[1,2,3]].

	[X|Y] = [[a, b, c], [d, e, f]].

	[X|Y] = [[a, b], c, d].

	[X|X] = [[a, b], C].

	[X|X] = [[a, b], a, b].

	.(X, Y) = [do,be,do,be,do].

{Only try this next one if you really don't know what will happen...}

	X = [V, W, X, Y, Z].

{There's a definition of member in the file likes, let's see it in action.}

	member(1, [0, 1, 2, 3]).

	member(1, [0, [1], 2]).

	member(1, [2, 4, 6]).

{You don't have to instantiate both parameters in member, you can use it as
a "generator". Answer the X = blah question with a ; and see what happens:}

	member(X, [the, cat, sat, on, the, mat]).

{This can be quite useful. In the file "likes", I've defined a predicate, 
days, which contains a list of the days of the week. Answer the questions 
with ;.}

	days(X), member(M, X).

{What use is it? Here's something to print them all out. Notice that there's
a fail at the end.

	days(X), member(D, X), write(D), nl, fail.

{See what it prints out? The no at the end is because eventually member runs
out of days to pick up, and itself fails. This next one is going to make your
eyes pop out. It's on 2 lines, the first one ends in a comma, not a dot.}

	X = [mon, tue, wed, thu, fri, sat, sun|X],
	member(D, X), write(D), nl, fail.

{Using "fail" this way is quite common in Prolog.  
With your knowledge in lists, you should now be able to write a predicate
which collects all the days in one list.}

{The following is a special treat for those who would like a bit of challenge.
You don't have to finish it in the class.}

{Aliens from the planet Trd have only three swearwords, zrt, pfk and rrb. They
use these all the time, and it gets on the nerves of their president, Jrk. Jrk
orders that all text should be censored, so that swearwords are removed. Write
a function censor(I, O), where I is a list of Trdish words, and O is the list
with obsceneties removed. What would it produce for the following examples?}

	censor([plt,yrd,pfk,crl,rrb], L).

	censor([nsp,liq,krk,zrt,plb], L).

	censor([pwq,frg,prolog,rza,zrt,zrt,zrt,zrt,zrt,pfk], L).

{President Jrk decides that merely removing words from sentences isn't enough,
and decrees that all swearwords should be replaced by the word swk, which means
"beep" in Trdish. Alter your program so that it conforms to the new
requirements.}
