Commit fb1954ae authored by Christophe Rhodes's avatar Christophe Rhodes
Browse files

updates to 01 02 03

parent 82316ee8
#+TITLE: Algorithms & Data Structures: Lab 03
#+SUBTITLE: week of 15th 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 =03/=) alongside the existing directories.
* Dynamic Arrays
** Implement the data structure
Implement a dynamic array data structure, supporting the operations
detailed in the lecture. You are provided with skeleton files and
test files, as usual; running =make test= in the =cpp/= or =java/=
directory should provide you with a test failure report, and once
you have successfully implemented a dynamic array data structure,
you should be able to rerun the tests I provide with success.
Your implementation will be a little different from the one
presented in the lecture, which used a pair to be the container; in
real implementations, we want to name fields and methods
appropriately, rather than simply re-purposing a generic data
structure.
** Investigating extension
In implementing your version of a dynamic array, you will have had
to choose:
1. how big the initial storage vector is when a dynamic array is
constructed;
2. how to extend the storage vector when it is full and a new
element needs to be added.
Copy the following table into a spreadsheet (or similar document),
and use the ~OpCounter~ class (found in directory ~00/~ of the lab
bundle) to count the number of /writes/ to memory. In this
investigation:
1. make the initial size of the storage vector be 5;
2. start with the dynamic array being empty;
3. push the number of elements indicated into the dynamic array;
4. try each of the possibilities in the table as the
\textsc{newLength} function.
| length | x + 5 | 2 × x | x² |
|--------+-------+-------+----|
| 1 | 1 | 1 | 1 |
| 5 | 5 | 5 | 5 |
| 10 | | | |
| 50 | | | |
| 100 | | | |
| 500 | | | |
| 1000 | | | |
| 5000 | | | |
| 10000 | | | |
You can use ~make count~ in the lab directory to help you; you may
want to adapt your implementation of the ~DynamicArray~ class, or
extend ~DynamicArrayCounter~, in order to be able to choose how to
compute \textsc{newLength}.
*** Asymptotic complexity
Make a hypothesis for how the number of memory writes grows as a
function of the number of elements pushed, for each of the
possibilities for \textsc{newLength}. How is your answer affected
by the initial size of the storage vector?
*** Storage overhead
For each of the above possibilities for the \textsc{newLength}
function, compute the storage overhead of the dynamic array at
length 1000. You can ignore the overhead coming from the
~DynamicArray~ class itself, and the length field of the storage
vector; calculate the overhead from how much unused space there is
in the storage vector, for each of the three cases.
** Submission
There will be a submission related to this lab at the end of next week
(deadline *16:00 26th October 2018*); you will be asked to submit
work based on your implementation of the ~DynamicArray~ class *and*
of your investigation into the scaling properties. Make sure you
save your work, and that you understand what is going on.
#include "DynamicArray.hpp"
DynamicArray::DynamicArray(size_t size) {
}
size_t DynamicArray::length() {
return (size_t) -1;
}
int DynamicArray::select(size_t k) {
return 0;
}
void DynamicArray::store(int o, size_t k) {
}
void DynamicArray::push(int o) {
}
int DynamicArray::pop() {
return 0;
}
void DynamicArray::extend() {
}
#ifndef DYNAMICARRAY_HPP
#define DYNAMICARRAY_HPP
#include <cstddef>
#include "OpCounter.hpp"
class DynamicArray {
public:
OpCounter counter = OpCounter();
public:
DynamicArray(size_t);
size_t length();
int select(size_t);
void store(int, size_t);
void push(int);
int pop();
private:
void extend();
};
#endif
#include <vector>
#include <iostream>
#include "DynamicArray.hpp"
#include "OpCounter.hpp"
int main(int argc, char *argv[]) {
std::vector<int> l = {1, 5, 10, 50, 100, 500, 1000};
for (int i = 0; i < l.size(); i++) {
DynamicArray *a = new DynamicArray(5);
for(int n = 0; n < l[i]; n++) {
a->push(n);
}
std::cout << l[i] << "," << a->counter.report() << std::endl;
delete a;
}
}
#include <cmath>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include "DynamicArray.hpp"
class DynamicArrayTest : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(DynamicArrayTest);
CPPUNIT_TEST(testConstructor);
CPPUNIT_TEST(testSmall);
CPPUNIT_TEST(testLargePush);
CPPUNIT_TEST(testLargePop);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() { };
void tearDown() { };
void testConstructor();
void testSmall();
void testLargePush();
void testLargePop();
};
void DynamicArrayTest::testConstructor() {
DynamicArray *a = new DynamicArray(10);
CPPUNIT_ASSERT_EQUAL_MESSAGE("A fresh dynamic array should have zero length", ((size_t) 0UL), a->length());
delete a;
}
void DynamicArrayTest::testSmall() {
DynamicArray *a = new DynamicArray(10);
a->push(1);
CPPUNIT_ASSERT_EQUAL(((size_t) 1UL), a->length());
CPPUNIT_ASSERT_EQUAL(1, a->select(0));
a->push(3);
CPPUNIT_ASSERT_EQUAL(((size_t) 2UL), a->length());
CPPUNIT_ASSERT_EQUAL(1, a->select(0));
CPPUNIT_ASSERT_EQUAL(3, a->select(1));
a->store(2, 0UL);
CPPUNIT_ASSERT_EQUAL(((size_t) 2UL), a->length());
CPPUNIT_ASSERT_EQUAL(2, a->select(0));
CPPUNIT_ASSERT_EQUAL(3, a->select(1));
delete a;
}
void DynamicArrayTest::testLargePush() {
DynamicArray *a = new DynamicArray(10);
for (int i = 0; i < 100; i++) {
a->push(i);
}
CPPUNIT_ASSERT_EQUAL(((size_t) 100UL), a->length());
CPPUNIT_ASSERT_EQUAL(99, a->select(99));
CPPUNIT_ASSERT_EQUAL(3, a->select(3));
delete a;
}
void DynamicArrayTest::testLargePop() {
DynamicArray *a = new DynamicArray(10);
for (int i = 1; i <= 100; i++) {
a->push(i);
}
for (int i = 100; i >= 1; i--) {
CPPUNIT_ASSERT_EQUAL((size_t) i, a->length());
CPPUNIT_ASSERT_EQUAL(i, a->pop());
CPPUNIT_ASSERT_EQUAL_MESSAGE("pop should reduce the length of a dynamic array by 1", (size_t) (i-1), a->length());
}
delete a;
}
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DynamicArrayTest, "DynamicArray");
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("DynamicArray");
/* FIXME: more boilerplate */
int main(int argc, char *argv[]) {
if (argc > 2) {
std::cerr << "Usage: " << argv[0] << " [suitename]" << std::endl;
return 1;
}
CppUnit::Test *test;
CppUnit::TextUi::TestRunner runner;
if (argc == 2)
test = CppUnit::TestFactoryRegistry::getRegistry(argv[1]).makeTest();
else
test = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
runner.addTest(test);
runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr));
bool wasSuccessful = runner.run();
return wasSuccessful ? 0 : 1;
}
include ../../cpp.mk
LDLIBS += -lm
DynamicArrayTest: DynamicArray.o DynamicArrayTest.o ../../00/cpp/OpCounter.o
DynamicArrayCounter: DynamicArray.o DynamicArrayCounter.o ../../00/cpp/OpCounter.o
test: DynamicArrayTest
./DynamicArrayTest
count: DynamicArrayCounter
./DynamicArrayCounter
.PHONY: test count
class DynamicArray {
public OpCounter counter = new OpCounter();
public DynamicArray(int size) {
}
public int length() {
return -1;
}
public int select(int k) {
return -1;
}
public void store(int o, int k) {
}
public void push(int o) {
}
public int pop() {
return -1;
}
private void extend() {
}
}
class DynamicArrayCounter {
public static void main(String args[]) {
int[] l = {1, 5, 10, 50, 100, 500, 1000};
for (int i = 0; i < l.length; i++) {
DynamicArray a = new DynamicArray(5);
for(int n = 0; n < l[i]; n++) {
a.push(n);
}
System.out.println("" + l[i] + "," + a.counter.report());
}
}
}
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.Before;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
public class DynamicArrayTest {
@Test
public void testConstructor() {
DynamicArray a = new DynamicArray(10);
assertEquals("A fresh dynamic array should have zero length", 0, a.length());
}
@Test
public void testSmall() {
DynamicArray a = new DynamicArray(10);
a.push(1);
assertEquals(1, a.length());
assertEquals(1, a.select(0));
a.push(3);
assertEquals(2, a.length());
assertEquals(1, a.select(0));
assertEquals(3, a.select(1));
a.store(2, 0);
assertEquals(2, a.length());
assertEquals(2, a.select(0));
assertEquals(3, a.select(1));
}
@Test
public void testLargePush() {
DynamicArray a = new DynamicArray(10);
for (int i = 0; i < 100; i++) {
a.push(i);
}
assertEquals(100, a.length());
assertEquals(99, a.select(99));
assertEquals(3, a.select(3));
}
@Test
public void testLargePop() {
DynamicArray a = new DynamicArray(10);
for (int i = 1; i <= 100; i++) {
a.push(i);
}
for (int i = 100; i >= 1; i--) {
assertEquals(i, a.length());
assertEquals(i, a.pop());
assertEquals("pop should reduce the length of a dynamic array by 1", i-1, a.length());
}
}
public static void main(String args[]) {
JUnitCore core = new JUnitCore();
core.run(DynamicArrayTest.class);
}
}
include ../../java.mk
TESTCLASSFILES = DynamicArrayTest.class
CLASSFILES = DynamicArray.class ../../00/java/OpCounter.class DynamicArrayCounter.class $(TESTCLASSFILES)
all: $(CLASSFILES)
test: all
(((($(JAVA) -Xss10m $(CP) $(CLASSPATH) org.junit.runner.JUnitCore $(subst .class,,$(notdir $(TESTCLASSFILES))); echo $$? >&3) | egrep -v \(org.junit\|sun.reflect\|java.lang.reflect\) >&4) 3>&1) | (read xs; exit $$xs)) 4>&1
count: all
$(JAVA) $(CP) $(CLASSPATH) DynamicArrayCounter
clean:
-rm *.class
.PHONY: test all clean
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