1 / 26

# Prolog Programming - PowerPoint PPT Presentation

Prolog Programming (Volume 3). Dr W.F. Clocksin. Mapping: The Full Map. sqlist( , ) sqlist([], []). sqlist([X|T], [Y|L]) :- Y is X * X, sqlist(T, L). List of numbers. List of squares of numbers. Mapping: The Full Map (cont’d).

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Prolog Programming' - Solomon

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### Prolog Programming(Volume 3)

Dr W.F. Clocksin

sqlist( , )

sqlist([], []).

sqlist([X|T], [Y|L]) :- Y is X * X, sqlist(T, L).

List of numbers

List of squares of numbers

Here is an exercise in compound terms. Map each list element (a number) to a term s(A,B) where A is the number and B is its square.

Input: [1, 9, 15]

Output: [s(1,1), s(9, 81), s(15, 225)]

sqterm([], []).

sqterm([X|T], [s(X,Y)|L]) :-

Y is X * X,

sqterm(T, L).

/* fullmap(In, Out) */

fullmap([], []).

fullmap([X|T], [Y|L]) :-

transform(X,Y), fullmap(T, L).

Here is a typical transformation table…

transform(cat, gatto).

transform(dog, cane).

transform(hamster, criceto).

transform(X, X).

?- fullmap([cat, dog, goat], Z).

Z = [gatto, cane, goat]

A ‘catchall’ rule

Sometimes the map needs to be sensitive to the input data:

Input: [1, 3, w, 5, goat]

Output: [1, 9, w, 25, goat]

squint([], []).

squint([X|T], [Y|L]) :-

integer(X),

Y is X * X, squint(T, L).

squint([X|T], [X|L]) :- squint(T,L).

Just use a separate clause for each choice

Using the infix binary compound term *, it is easy enough to give some mathematical reality to the map:

Input: [1, 3, w, 5, goat]

Output: [1, 9, w*w, 25, goat*goat]

squint([], []).

squint([X|T], [Y|L]) :-

integer(X),

Y is X * X, squint(T, L).

squint([X|T], [X*X|L]) :- squint(T,L).

Given an input list, partially map it to an output list.

evens([], []).

evens([X|T], [X|L]) :- 0 is X mod 2, evens(T, L)

evens([X|T], L) :- 1 is X mod 2, evens(T, L).

?- evens([1, 2, 3, 4, 5, 6], Q),

Q = [2, 4, 6].

partial([], []).

partial([X|T], [X|L]) :- include(X), partial(T, L)

partial([X|T], L) :- partial(T, L).

For example,

include(X) :- X >= 0.

?- partial([-1, 0, 1, -2, 2], X),

X = [0, 1, 2].

Exercise: Write a program that ‘censors’ and input list, by making a new list in which certain prohibited words do not appear. To do this, define a predicate prohibit such that prohibit(X) succeeds if X is a censored word. For example,

prohibit(bother).

prohibit(blast).

prohibit(drat).

prohibit(fiddlesticks).

censor([], []).

censor([H|T], T1) :- prohibit(H), censor(T, T1).

censor([H|T], [H|T1]) :- censor(T, T1).

setify([], []).

setify([X|T], L) :- member(X,T), setify(T, L).

setify([X|T], [X|L]) :- setify(T, L).

Before, we saw how to prevent loops (when searching a graph) by keeping a ‘trail’ of the nodes visited so far. Here is another way to think about the problem.

Keep a list of all the visitable nodes. As each node is visited, strike it off the list and pass the reduced list to the recursive call. Backtracking restores the old list, so alternative paths can be searched.

First, a predicate to reduce the list.

Goal reduce(L,X,M) succeeds for input list L, term X and output list M, when M contains the elements of L except for the first occurrence of X. Thus, X is a parameter that controls which element will be omitted from the output list.

reduce([X|T], X, T).

reduce([H|T], X, [H|L]) :- reduce(T, X, L).

path(X, X, L).

path(X, Y, L) :-

a(X, Z),

reduce(L, Z, L1),

path(Z, Y, L1).

Using the arc relation on Worksheet 9,

?- path(a, b, [a, b, c, d, e, f, g, h]).

yes.

Maps a list into several disjoint lists.

Separating sheep from goats. Define the predicate herd, such that the goal herd(L, S, G) succeeds if S is a list of all the sheep in L and G is a list of all the goats in L.

herd([], [], []).

herd([sheep|T], [sheep|S], G) :- herd(T, S, G).

herd([goat|T], S, [goat|G]) :- herd(T, S, G).

?- herd([sheep, goat, goat, sheep, goat], X, Y).

?- herd([goat, sheep, stone, goat, tree], X, Y).

?- herd(X, [sheep, sheep], [goat, goat]).

?- herd([goat, sheep, stone, goat, tree], X, Y).

The above goal fails. Instead, we could ignore other objects by having a catchall:

herd([X|T], S, G) :- herd(T, S, G).

input sheep goats extras

herd([], [], [], []).

herd([sheep|T], [sheep|S], G, E) :- herd(T, S, G, E).

herd([goat|T], S, [goat|G], E) :- herd(T, S, G, E).

herd([X|T], S, G, [X|E]) :- herd(T, S, G, E).

Maps an input list into a pair of lists, alternating the elements.

alternate([a, b, c, d, e, f], [a, c, e], [b, d, f])

Alternating by index (which element of the input list it is):

altx([], [], []).

altx([A, B | T], [A | T1], [B| T2]) :- altx(T, T1, T2).

Maps an input list into a pair of lists, alternating the elements.

altv([1, 2, 3, 4], [2, 4], [1, 3])

altv([], [], []).

altv([A | T], [A | T1], B) :-

0 is A mod 2, altv(T, T1, B).

altv([B | T], A, [B | T2]) :-

1 is B mod 2, altv(T, A, T2).

See how this is the same as sheep and goats?

/* mapsum(list of integers, cumulative sum) */

?- mapsum([1, 3, 2, 5, 4], X).

X = [1, 4, 6, 11, 15].

0

Use an accumulator as a state variable that helps to determine the value of each element of the output list.

/* ms(input list, accumulator, output list) */

mapsum(A, B) :- ms(A, 0, B)

ms([], _, []).

ms([H|T], N, [C|L]) :- C is H + N, ms(T, C, L).

initialise accumulator

anonymous variable (don’t care about accumulator if end of list)

Example: Run length encoding is a useful data representation and compression technique.

Represent sequential ‘runs’ of N identical terms T as the term N*T, for example

[12, 2, 2, w, 3, 3, s, s, s]

maps to

[1*12, 2 * 2, 1 * w, 2 * 3, 3 * s].

[12, 2, 2, w, 3, 3, s, s, s][1*12, 2 * 2, 1 * w, 2 * 3, 3 * s]

runcode(input, current term, current count, output)

runcode([], C, N, [N*C]).

runcode([H|T], H, N, Z) :-

N1 is N+1, runcode(T, H, N1, Z).

runcode([H|T], C, N, [N*C|Z]) :-

H \== C, runcode(T, H, 1, Z).

runcode([], C, N, [N*C]).

runcode([H|T], H, N, Z) :-

N1 is N+1, runcode(T, H, N1, Z).

runcode([H|T], C, N, [N*C|Z]) :-

H \== C, runcode(T, H, 1, Z).

End of list? Deal withleftover accumulator values

Have seen this before...

Otherwise, discharge the current run...

...and start a new run