You will need to implement your code in assignment4/assignment4.pl
. assignment4/assignment4.plt
is the testcase file and assignment4/plunit.pl
is for unit testing.
To run your implementation, you have two options:
Option (1): Use iLab
. Please see the document here.
Option (2): Download and install the SWI-Prolog interpreter here. After the interpreter GUI is openned, you can use it to launch your program and make queries. In the installed GUI, after the ?-
query symbol, type consult("/path/to/your/assignment4/assignment4.pl").
to load the assignment soure file. Please specify the path correctly to where you have saved assignment4/assignment4.pl
. You will see a number of warnings. Please ignore them. Type "range(1,2,0)." (see Problem 1) after the ?-
query symbol to make your first query. The result should be false
.
Unit testing:
(1) In iLab, cd
into the folder that contains assignment4.pl
, assignment4.plt
and plunit.pl
.
(2) swipl -t "use_module(plunit), load_test_files([]), run_tests." -s assignment4
(3) You will then see how many test-cases your solution passed. Unit testing on your own machine requires swipl
on the system path or where the computer can find the installed swipl
program clearly specified.
Please submit to Sakai assignment4.pl
only.
Type "halt." after the ?-
query symbol to quite the Prolog interpreter.
Warning: /../../../assignment4.pl:14: Singleton variables: [X]
This is because you introduced some variables in your program that are never used, which could be replaced with _
. You can ignore this type of warnings. In fact, you can ignore any warnings in the console.
Warning: /../../../assignment4.plt:25: PL-Unit: Test xxxx: Test succeeded with choicepoint
This is because the interpreter used backtracking and choicpoints to execute your program. You can ignore this type of warnings. In fact, you can ignore any warnings in the console.
?- member(X, [1,2,3]).
X = 1
The problem is that you expect to see X = 2 and X = 3 but it seems that the interperter gets stuck there.
?- member(X, [1,2,3]).
X = 1; <-- It is waiting for you to type ;
X = 2; <-- It is waiting for you to type ;
X = 3
Please explicitly type a semicolon there to let the interpreter resume the search.
Sometimes after the last solution, when you expect the interpreter to just stop, it instead waits for you to type ;
one more time. For example:
?- member(1, [1,2,3]).
true ; <-- It is waiting for you to type ;
false.
This is because the interpreter is not smart about knowing if it has explored all the correct solutions. Consider the following situation:
A woman walks into a hardware store and says to the owner "I’m driving in fence posts, I need a really big hammer" The owner shows her a hammer. She says "No, I need a bigger hammer than that". The owner says "hold on, I have a bigger one in back".
He comes back a couple minutes later and says "Sorry, must have sold it. That’s the biggest we have." The first solution is offered (the first hammer). She rejects it, and the storeowner tries again. This time he fails. He thought he might have another solution, but he doesn’t.
You do not need to eliminate the false
answer. It has no effect on program execution.
Some of the predicates we learn in class are actually built-in. Feel free to use them in your assignment. Examples are append
, length
, and arithmetic predicates including +
,*
, /
, <
, =<
, >
, >=
, etc. Please do not use other library functions not covered in class.
/* YOUR CODE HERE (delete the following line) */
range(S,E,M) :- false.
?- range(1,2,2).
/* expected output: true. */
?- not(range(1,2,3)).
/* expected output: true. */
/* YOUR CODE HERE (delete the following line) */
reverseL(X,RevX) :- false.
?- reverseL([],X).
/* expected output: X = [ ]. */
?- reverseL([1,2,3],X).
/* expected output: X = [ 3, 2, 1 ]. */
?- reverseL([a,b,c],X).
/* expected output: X = [ c, b, a ]. */
Implement list membership predicate memberL(X,L)
which holds if $X \in L$. Addtionally, if $L = \emptyset$, return false
.
/* YOUR CODE HERE (delete the following line) */
memberL(X,L) :- false.
?- not(memberL(1, [])).
/* expected output: true. */
?- memberL(1,[1,2,3]).
/* expected output: true. */
?- not(memberL(4,[1,2,3])).
/* expected output: true. */
?- memberL(X, [1,2,3]).
/* expected output: see below */
Implement the predicate zip(Xs, Ys, XYs)
that relates three lists, where the third list XYs
contains pairs whose elements are the elements at the same indices of the first two lists Xs
and Ys
. In Prolog, we use A-B
for a pair of elements A
and B
. For example, 1-2
is a pair (1,2)
.
The third list XYs
will always be as long as the shorter of the first two lists; additional elements in the longer list are discarded.
/* YOUR CODE HERE (delete the following line) */
zip(Xs, Ys, XYs) :- false.
?- zip([1,2],[a,b],Z).
/* expected output: Z = [1-a, 2-b]. */
?- zip([a,b,c,d], [1,X,y], Z).
/* expected output:: Z = [a-1, b-X, c-y]. */
?- zip([a,b,c],[1,X,y,z], Z).
/* expected output:: Z = [a-1, b-X, c-y]. */
?- length(A,2), length(B,2), zip(A, B, [1-a, 2-b]).
/* expected output:: A = [1,2], B = [a,b]. */
Implement the predicate insert(X, Ys, Zs)
that is a relation between an integer X
, a sorted list of integers Ys
, and a sorted list of integers Zs
. Zs
is the result of inserting X
to Ys
. It contains the first argument X
and all the elements of Ys
.
/* YOUR CODE HERE (delete the following line) */
insert(X, Ys, Zs) :- false.
?- insert(3, [2,4,5], L).
/* expected output: L = [2,3,4,5]. */
?- insert(3, [1,2,3], L).
/* expected output: L = [1,2,3,3]. */
?- not(insert(3, [1,2,4], [1,2,3])).
/* expected output: true. */
?- insert(3, L, [2,3,4,5]).
/* expected output: L = [2,4,5]. */
?- insert(9, L, [1,3,6,9]).
/* expected output: L = [1,3,6]. */
?- insert(3, L, [1,3,3,5]).
/* expected output: L = [1,3,5]. */
Write a Prolog predicate remove_duplicates(L1,L2)
that is true if L2
is equal to the result of removing all duplicate elements from L1
. In the result, the order of the elements must be the same as the order in which the (first occurences of the) elements appear in L1
.
/* YOUR CODE HERE (delete the following line) */
remove_duplicates(L1,L2) :- false.
?- remove_duplicates([1,2,3,4,2,3],X).
/* expected output: X = [1, 2, 3, 4] */
?- remove_duplicates([1,4,5,4,2,7,5,1,3],X).
/* expected output: X = [1, 4, 5, 2, 7, 3] */
?- remove_duplicates([], X).
/* expected output: x = [] */
Write a Prolog predicate intersectionL(L1,L2,L3)
that is true if L3
is equal to the list containing intersection of the elements in L1
and L2
without any duplicates. In other words, L3
should contain the elements that both in L1
and in L2
. The order of the elements in L3
should be the same as the order in which the elements appear in L1
.
/* YOUR CODE HERE (delete the following line) */
intersectionL(L1,L2,L3) :- false.
?- intersectionL([1,2,3,4],[1,3,5,6],[1,3]).
/* expected output: true. */
?- intersectionL([1,2,3,4],[1,3,5,6],X).
/* expected output: X = [1,3]. */
?- intersectionL([1,2,3],[4,3],[3]).
/* expected output: true. */
Implement partition(L,P,S)
such that
P
is the prefix of L
andS
is the suffix of L
andappend(P,S,L)
holdsL
is []
, then P
and S
are []
.L
is [H]
, then P
is [H]
and S
is []
. L
be N
. Then length of P
is div(N/2)
. Use Prolog's built-in integer division.S
is N - div(N/2)
. You may need to use the length
,prefix
,suffix
,append
predicates that we have seen in class.
prefix(P,L) :- append(P,X,L).
suffix(S,L) :- append(X,S,L).
/* YOUR CODE HERE (delete the following line) */
partition(L,P,S) :- false.
?- partition([a],[a],[]).
/* expected output: true. */
?- partition([1,2,3],[1],[2,3]).
/* expected output: true. */
?- partition([a,b,c,d],X,Y).
/* expected output: Y = [ c, d ], X = [ a, b ]. */
Implement the predicate merge(X,Y,Z)
where X
and Y
are sorted, and Z
contains the same elements as U
where append(X,Y,U)
but Z
is also additionally sorted.
/* YOUR CODE HERE (delete the following line) */
merge(X,Y,Z) :- false.
?- merge([],[1],[1]).
/* expected output: true. */
?- merge([1],[],[1]).
/* expected output: true. */
?- merge([1,3,5],[2,4,6],X).
/* expected output: X = [ 1, 2, 3, 4, 5, 6 ]. */
Implement predicate mergesort(L,SL)
where SL
is the sorted version of L
. Use the predicate partition
to partition the list L
into two segments, sort each on separately (using mergesort
) and combine the individual sorted list using merge
.
/* YOUR CODE HERE (delete the following line) */
mergesort(L,SL) :- false.
?- mergesort([3,2,1],X).
/* expected output: X = [ 1, 2, 3 ]. */
?- mergesort([1,2,3],Y).
/* expected output: Y = [ 1, 2, 3 ]. */
?- mergesort([],Z).
/* expected output: Z = [ ]. */
?- mergesort([1,3,5,2,4,6],X).
/* expected output: X = [ 1, 2, 3, 4, 5, 6 ]. */