Relations
Membership
1 | member(X, [X | Tail]). |
Relation: member(X, L)
- Where X is an object and L is a list
Goal: member(X, L) is true if X occurs in L
- For example:
- ?- member(b, [a,b,c]).
true.- ?- member(b, [a,[b,c]]).
false.- ?- member([b,c], [a,b,c]).
true.How to approach:
The program for the membership relation can be based on the following observation:
X is a member of L if either
- X is the head of L, or
- X is a member of the tail of L.
Concatenation (or append)
1 | conc( [], L, L). |
Relation: conc(L1, L2, L3)
- here L1 and L2 are two lists, and L3 is their concatenation
Goal: conc(L1, L2, L3) is true if L3 is the concatenation of list L1 and list L2
- For example:
- ?- conc([a,b],[c,d],[a,b,c,d]).
true.- ?- conc([a,b],[c,d],[a,b,a,c,d]).
false.How to approach:
- In the definition of conc we will have two cases, depending on the first argument, L1:
- If the first argument is the empty list then the second and the third arguments must be the same list
- If the first argument of conc is a non-empty list then it has a head and a tail and must look like this: [X | L1]
Using conc, the membership relation could be programmed by the following clause:
1 | member(X, L) :- |
or
1 | member(X, L) :- |
Exercise 3.1 (a)
Write a goal, using conc, to delete the last three elements from a list L producing another list L1.
1 | conc(L1, [_,_,_], L). |
Exercise 3.1 (b)
Write a sequence of goals to delete the first three elements and the last three elements from a list L producing list L2.
1 | conc([_,_,_], L1, L), |
Exercise 3.2
Define the relation, last(Item, List), so that Item is the last element of a list List. Write two versions:
(a) using the conc relation
(b) without using the conc relation
1 | % using the conc relation |
Add
If X is the new item and the list to which X is added is L then the resulting list is simply [X | L].
If we want to define such a procedure explicitly, it can be written as the fact- add(X, L, [X| L]).
Delete
1 | del(X, [X | Tail], Tail). |
Relation: del(X, L, L1)
- Where X is an item and L and L1 are lists
Goal: del(X, L, L1) is true if L1 equal to the list L with the item X removed
- For example:
- ?- del(a, [a,b,a,a], L).
L = [b,a,a];
L = [a,b,a];
L = [a,b,a];
false.How to approach:
- The program for the del relation can be based on the following observation:
- If X is the head of the list then the result after the deletion is the tail of the list
- If X is in the tail then it is deleted from there.
Insert
1 | insert(X, List, BiggerList): |
Sublist
1 | sublist(S, L) :- |
Relation: sublist(S, L)
- where S and L are lists
Goal: sublist(S, L) is true if S is the sublist of list L
For example:
?- sublist([c,d,e], [a,b,c,d,e,f]).
true.
?- sublist([c,e], [a,b,c,d,e,f]).
false.
How to approach:
- S is a sublist of L if:
- L can be decomposed into two lists, L1 and L2, and
- L2 can be decomposed into two lists, S and some L3.
Permutation
1 | permutation([], []). |
Relation: permutation(L, P)
- Where L and P are lists
Goal:
For example:
?- permutation([a,b,c], P).
P = [a,b,c];
P = [a,c,b];
P = [b,a,c];
…
How to approach:
The program for permutation can be based on the consideration of two cases:
if the first list is empty then the second list must be empty too
if the first list is not empty then it has the form [X|L], and a permutation of such a list can be constructed as:
first permute L obtaining L1 and then insert X at any position into L1.
or using delete to generate permutation as follows:
1 | permutation2([], []). |
Permutation might get into an infinite loop. Be careful.
Exercise 3.3
Define two predicates evenlength(List) and oddlength(List) so that they are true if their argument is a list of even or odd length respectively.
1 | evenlength([]). |
Exercise 3.4
Define the relation reverse(List, ReversedList) that reverses lists.
1 | reverse([], []). |
1 | reverse(L, Res) :- |
Exercise 3.5
Define the predicate palindrome(List).
1 | Palindrome(List) :- |
Exercise 3.6
Define the relation shift(List1, List2) so that List 2 is List1 shifted rotationally’ by one element to the left.
For example,
?- shift([1,2,3,4,5], L1),
shift(L1, L2).
L1 = [2,3,4,5,1]
L2 = [3,4,5,1,2]
1 | shift([],[]). |
Exercise 3.7
Define the relation translate(List1, List2) to translate a list of numbers between 0 and 9 to a list of the corresponding words. For example:
translate([3,5,1,3], [three, five, one, three]).
Use the following as an auxiliary relation:
means(0, zero). means(1, one). means(2, two). …
1 | means(1, one). |
Exercise 3.8
Define the relation subset(Set, Subset) where Set and Subset are two lists representing two sets. We would like to be able to use this relation not only to check for the subset relation, but also to generate all possible subsets of a given set. For example:
?- subset([a,b,c], S).
S = [a,b,c];
S = [b,c];
S = [c];
S = [];
S = [a,c];
S = [a];
…
1 | subset([], []). |
Exercise 3.9
Define the relation dividelist(List, List1, List2) so that the elements of List are partitioned between List1 and List2, and List1 and List2 are of approximately the same length. For example, dividelist([a,b,c,d,e], [a,c,e], [b,d])
1 | dividelist([], [], []). % Nothing to divide |
Exercise 3.10
Rewrite the monkey and banana program of Chapter 2 as the relation canget(State, Actions) to answer not just ‘yes’ or ‘no’, but to produce a sequence of monkey’s actions that lead to success. Let Actions be such a sequence represented as a list of moves:
Actions = [walk(door, window), push(window, middle), climb, grasp]
Original algorithm:
1 | % Legal moves |
New algorithm:
1 | % Legal moves |
Exercise 3.11
Define the relation flatten(List, FlatList) where List can be a list of lists, and FlatList is List ‘flattened’ so that the elements of List’s sublists (or sub-sublists) are reorganized as one plain list. For example:
?- flatten([a,b,[c,d],[],[[[e]]],f], L).
L = [a,b,c,d,e,f]
1 | flatten([], []). |
Don’t backtrack this program.
Kth
1 | kth(N, _, 0):- |
Quicksort
1 | kth(N, _, 0):- |