Commit 4e53933d authored by Christophe Rhodes's avatar Christophe Rhodes
Browse files

updates to 05

parent 33b09ebd
#+TITLE: Algorithms & Data Structures: Lab 05
#+SUBTITLE: week of 29th October 2018
#+include: ../labsheet.org
* Setup
** Saving your work from last week
As with previous weeks, you will use =git= to download a bundle of
lab code. You might have made modifications in your downloaded
copy; if you have not already done so, you need to save those
modifications. First examine the changes present in your
downloaded copy by issuing the following commands from the labs
directory:
#+begin_example
git status
git diff
#+end_example
and if you are satisfied with the changes, store them in the git
version control system by doing
#+begin_example
git commit -a
#+end_example
and writing a suitable commit message
** Downloading this week's distribution
Once you have successfully saved your changes from last week, you
can get my updates by doing
#+begin_example
git pull
#+end_example
which /should/ automatically merge in new content. After the =git
pull= command, you should have a new directory containing this
week's material (named =05/=) alongside the existing directories.
* Linked Lists (cont'd)
** Setup
You should begin from the work you did in lab 04: a singly-linked
list class implemented in terms of ~SLList~ objects, with primitive
methods:
* ~first()~
* ~rest()~
* ~setFirst(o)~
* ~setRest(r)~
and additional methods:
* ~nth(i)~
* ~nthRest(i)~
* ~length()~
Verify that your implementation compiles and runs the additional
tests provided in this week's distribution.
** Remove
Implement ~remove~, which returns a new list whose contents are the
same as the original list, but with all instances of the given
object removed. Use the second part of the [[http://www.doc.gold.ac.uk/~mas01cr/teaching/is52038b/2017-18/ListAlgorithms.html][interactive exercise]] on
list algorithms to guide you, and check your implementation against
the provided test cases.
** Reverse
Implement ~reverse~, which returns a new list whose contents are
the same as the original list but in reverse order. Check your
implementation against the provided test cases. What are the time
and space complexity of your solution?
** Other linear list algorithms
Write down the base case and recursive step for the following
algorithms:
- sum :: find the sum of the elements in a list
- max :: find the maximum value of the elements in a non-empty list
- search[o] :: return true if the object is present in a list, otherwise false
- position[o] :: return the position of the object in a list, if
present, otherwise -1
By adding to your existing ~SLList~ implementation, write methods
to perform these operations. How will you test your
implementations?
** Submission
Submit your work on the ~SLList~ data structure and related
algorithms to the [[https://learn.gold.ac.uk/mod/lti/view.php?id=611922][lab submission area]] on the [[https://learn.gold.ac.uk/course/view.php?id=11491][module learn.gold
page]]. The submission area will close at *16:00* on *9th November
2018*.
#include <cppunit/extensions/HelperMacros.h>
#include "SLList.hpp"
class LengthSLListTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(LengthSLListTest);
CPPUNIT_TEST(testLengthOfNIL);
CPPUNIT_TEST(testLength);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { };
void tearDown() { };
void testLengthOfNIL();
void testLength();
};
void LengthSLListTest::testLengthOfNIL() {
CPPUNIT_ASSERT_EQUAL_MESSAGE("What is the length of NIL?", 0U, SLList::NIL->length());
}
void LengthSLListTest::testLength() {
SLList *n = new SLList(1, SLList::NIL);
CPPUNIT_ASSERT_EQUAL_MESSAGE("What is the length of a list whose next is NIL?", 1U, n->length());
SLList *nn = new SLList(2, n);
CPPUNIT_ASSERT_EQUAL_MESSAGE("What is the length of a list whose next is a list with length 1?", 2U, nn->length());
delete n;
delete nn;
}
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(LengthSLListTest, "Length");
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("Length");
include ../../cpp.mk
SLListTest: CPPFLAGS += -I ../../04/cpp
SLListTest: ../../04/cpp/SLList.o ../../00/cpp/RunTests.o LengthSLListTest.o RemoveSLListTest.o ReverseSLListTest.o
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
test: SLListTest
./SLListTest
all: SLListTest
.PHONY: test all
#include <cppunit/extensions/HelperMacros.h>
#include "SLList.hpp"
class RemoveSLListTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RemoveSLListTest);
CPPUNIT_TEST(testRemoveOfNIL);
CPPUNIT_TEST(testRemove1);
CPPUNIT_TEST(testRemove2);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { };
void tearDown() { };
void testRemoveOfNIL();
void testRemove1();
void testRemove2();
};
void RemoveSLListTest::testRemoveOfNIL() {
SLList *n = SLList::NIL->remove(1);
CPPUNIT_ASSERT_EQUAL_MESSAGE("What can you remove from NIL?", SLList::NIL, n);
n = SLList::NIL->remove(0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("What can you remove from NIL?", SLList::NIL, n);
}
void RemoveSLListTest::testRemove1() {
SLList *n = new SLList(1, SLList::NIL);
SLList *r = n->remove(0);
CPPUNIT_ASSERT_MESSAGE("remove must return a fresh list", r != n);
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change the length", 1U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change any item", 1, r->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change the next field", SLList::NIL, r->rest());
/* we're going to ignore memory leaks from ->remove() for now */
r = n->remove(1);
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing the only item present gives a length zero list", 0U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("the only length zero list is NIL", SLList::NIL, r);
delete n;
}
void RemoveSLListTest::testRemove2() {
SLList *n = new SLList(1, SLList::NIL);
SLList *nn = new SLList(2, n);
SLList *r = nn->remove(0);
CPPUNIT_ASSERT_MESSAGE("remove must return a fresh list", r != nn);
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change the length", 2U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change any item", 2, r->first());
CPPUNIT_ASSERT_MESSAGE("remove must return a completely fresh list", r->rest() != n);
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change any item", 1, r->rest()->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("removing an object not present doesn't change the next fields", SLList::NIL, r->rest()->rest());
/* again, ignoring memory leaks from ->remove() */
r = nn->remove(1);
CPPUNIT_ASSERT_MESSAGE("remove must return a fresh list", r != nn);
CPPUNIT_ASSERT_EQUAL_MESSAGE("remove of an object present will change the length", 1U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("remove of an object present can change which item is first", 2, r->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("remove of an object present will change the list structure", SLList::NIL, r->rest());
delete n;
delete nn;
}
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(RemoveSLListTest, "Remove");
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("Remove");
#include <cppunit/extensions/HelperMacros.h>
#include "SLList.hpp"
class ReverseSLListTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ReverseSLListTest);
CPPUNIT_TEST(testReverseOfNIL);
CPPUNIT_TEST(testReverse1);
CPPUNIT_TEST(testReverse2);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { };
void tearDown() { };
void testReverseOfNIL();
void testReverse1();
void testReverse2();
};
void ReverseSLListTest::testReverseOfNIL() {
SLList *n = SLList::NIL->reverse();
CPPUNIT_ASSERT_EQUAL_MESSAGE("What should the reverse of NIL be?", SLList::NIL, n);
}
void ReverseSLListTest::testReverse1() {
SLList *n = new SLList(1, SLList::NIL);
SLList *r = n->reverse();
CPPUNIT_ASSERT_MESSAGE("reverse must return a fresh list", r != n);
CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse should not change the length of the list", 1U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("the first item of a reversed one-element list is the same as the first element of the original", 1, r->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse of a one-element list should be a one-element list", SLList::NIL, r->rest());
/* we're going to ignore memory leaks from ->reverse() for now */
delete n;
}
void ReverseSLListTest::testReverse2() {
SLList *n = new SLList(1, SLList::NIL);
SLList *nn = new SLList(2, n);
SLList *r = nn->reverse();
CPPUNIT_ASSERT_MESSAGE("reverse must return a fresh list", r != n);
CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse must not change the length of the list", 2U, r->length());
CPPUNIT_ASSERT_EQUAL_MESSAGE("the second item becomes the first", 1, r->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("the first item becomes the second", 2, r->rest()->first());
CPPUNIT_ASSERT_EQUAL_MESSAGE("reverse of a two-element list should be a two-element list", SLList::NIL, r->rest()->rest());
/* again, ignoring memory leaks from ->reverse() */
delete n;
delete nn;
}
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ReverseSLListTest, "Reverse");
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("Reverse");
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.JUnitCore;
public class LengthSLListTest {
@Test
public void testLengthOfNIL() {
assertEquals("What is the length of NIL?", 0, SLList.NIL.length());
}
@Test
public void testLength() {
SLList n = new SLList(1, SLList.NIL);
assertEquals("What is the length of a list whose next is NIL?", 1, n.length());
SLList nn = new SLList(2, n);
assertEquals("What is the length of a list whose next is a list with length 1?", 2, nn.length());
}
public static void main(String[] args) {
JUnitCore core = new JUnitCore();
core.run(LengthSLListTest.class);
}
}
include ../../java.mk
TESTCLASSFILES = LengthSLListTest.class RemoveSLListTest.class ReverseSLListTest.class
CLASSFILES = ../../04/java/SLList.class $(TESTCLASSFILES)
CLASSPATHS += ../../04/java
all: $(CLASSFILES)
test: all
(((($(JAVA) $(CP) $(CLASSPATH) org.junit.runner.JUnitCore $(subst .class,,$(TESTCLASSFILES)); echo $$? >&3) | egrep -v \(org.junit\|sun.reflect\|java.lang.reflect\) >&4) 3>&1) | (read xs; exit $$xs)) 4>&1
clean:
-rm -f $(TESTCLASSFILES) test.xml
.PHONY: test all clean
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import org.junit.Test;
import org.junit.runner.JUnitCore;
public class RemoveSLListTest {
@Test
public void testRemoveOfNIL() {
SLList n = SLList.NIL.remove(1);
assertEquals("What can you remove from NIL?", SLList.NIL, n);
n = SLList.NIL.remove(0);
assertEquals("What can you remove from NIL?", SLList.NIL, n);
}
@Test
public void testRemove1() {
SLList n = new SLList(1, SLList.NIL);
SLList r = n.remove(0);
assertNotEquals("remove must return a fresh list", n, r);
assertEquals("removing an object not present doesn't change the length", 1, r.length());
assertEquals("removing an object not present doesn't change any item", 1, r.first());
assertEquals("removing an object not present doesn't change the next field", SLList.NIL, r.rest());
r = n.remove(1);
assertEquals("removing the only item present gives a length zero list", 0, r.length());
assertEquals("the only length zero list is NIL", SLList.NIL, r);
}
@Test
public void testRemove2() {
SLList n = new SLList(1, SLList.NIL);
SLList nn = new SLList(2, n);
SLList r = nn.remove(0);
assertNotEquals("remove must return a fresh list", nn, r);
assertEquals("removing an object not present doesn't change the length", 2, r.length());
assertEquals("removing an object not present doesn't change any item", 2, r.first());
assertNotEquals("remove must return a completely fresh list", n, r.rest());
assertEquals("removing an object not present doesn't change any item", 1, r.rest().first());
assertEquals("removing an object not present doesn't change the next fields", SLList.NIL, r.rest().rest());
r = nn.remove(1);
assertNotEquals("remove must return a fresh list", nn, r);
assertEquals("remove of an object present will change the length", 1, r.length());
assertEquals("remove of an object present can change which item is first", 2, r.first());
assertEquals("remove of an object present will change the list structure", SLList.NIL, r.rest());
}
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import org.junit.Test;
import org.junit.runner.JUnitCore;
public class ReverseSLListTest {
@Test
public void testReverseOfNIL() {
SLList n = SLList.NIL.reverse();
assertEquals("What should the reverse of NIL be?", SLList.NIL, n);
}
@Test
public void testReverse1() {
SLList n = new SLList(1, SLList.NIL);
SLList r = n.reverse();
assertNotEquals("reverse must return a fresh list", n, r);
assertEquals("reverse should not change the length of the list", 1, r.length());
assertEquals("the first item of a reversed one-element list is the same as the first element of the original", 1, r.first());
assertEquals("reverse of a one-element list should be a one-element list", SLList.NIL, r.rest());
}
@Test
public void testReverse2() {
SLList n = new SLList(1, SLList.NIL);
SLList nn = new SLList(2, n);
SLList r = nn.reverse();
assertNotEquals("reverse must return a fresh list", nn, r);
assertEquals("reverse must not change the length of the list", 2, r.length());
assertEquals("the second item becomes the first", 1, r.first());
assertNotEquals("all nodes in the reversed list must be fresh", n, r.rest());
assertEquals("the first item becomes the second", 2, r.rest().first());
assertEquals("reverse of a two-element list should be a two-element list", SLList.NIL, r.rest().rest());
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment