Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
3 views7 pages

LabTest1 FT 2025

study material

Uploaded by

njabulondlozi16
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views7 pages

LabTest1 FT 2025

study material

Uploaded by

njabulondlozi16
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

U NIVERSITY OF THE W ITWATERSRAND , J OHANNESBURG

S CHOOL OF C OMPUTER S CIENCE & A PPLIED M ATHEMATICS

COMS1017A: Intro. to Data Structures & Algorithms


Lab Test 1 Full-Time
Prof. Richard Klein
21 August 2025

• This is a closed book lab test, you may not access any notes, other devices, or the internet.
• Answer all the questions and submit your code files to Moodle. You have 150 minutes.
• There are 70 marks available. Submissions that do not compile for a given question will
receive 0 for that question.
• Be aware of how much time you spend on one question. Begin with the questions you are
able to do and revisit the challenging ones once you are done. Avoid spending too much
time on one question and aim to answer as much as possible.
• There are several test cases that will grade your code. Each test case is marked indepen-
dently and checks a different aspect of your code. Each test case succeeds or fails, no part
marks are given within individual test cases. Each question will be checked by multiple
test cases.
• You will only submit the cpp file for each question. Do not edit tests.cpp or thing.h.
Moodle discards such changes; edited helpers will cause compile errors.
• Code will be compiled on Moodle using g++ --std=c++23 your-file.cpp tests.cpp
• You may use QtCreator, which is available on the lab computers. This is strongly recom-
mended because of the debugger.
• Running the unit test cases with the -a flag will run the tests and stop at the first failed
test case. The test cases are in the recommended order, so I suggest that you do this by
following the steps in the screenshot below (Steps 1, 2, and 3).
• When using QtCreator, you should tick the “Run in terminal” box as shown below (Steps
1, 2, and 4).
• Remove -a and pass [42] to run the test/tag [42]. The tests are all tagged with specific
names. If you run the tests with the -l flag you will see the names of all the test cases.
The local test cases correspond to those on Moodle, but the Moodle tests use different
data.

1
• Throughout various questions, you will make use of the Thing class provided in thing.h.
This class has several functions in it to assist the marker, but you can ignore all of them.
The parts that are relevant to you look like this:

1 class Thing {
2 protected:
3 int value;
4
5 public:
6 Thing() : value(-1) {}
7 Thing(int v) : value(v) {}
8
9 // You can compare things with each other
10 // e.g. t1 < t2
11 std::strong_ordering operator<=>(const Thing& other) const {
12 return value <=> other.value;
13 };
14 bool operator==(const Thing& other) const {
15 return value == other.value;
16 };
17
18 friend std::ostream& operator<<(std::ostream& os, const Thing& t);
19 };
20 // You can print a thing to cout
21 // e.g. cout << t1 << endl;
22 inline std::ostream& operator<<(std::ostream& os, const Thing& t) {
23 return os << t.value;
24 }

2
• Note that you should perform all comparisons and swaps on the Thing objects themselves,
not on their value member. For example:

1 Thing t1(2);
2 Thing t2(42);
3
4 // Valid Comparison
5 if(t1 < t2){
6 cout << "t1 is less than t2" << endl;
7 }
8

9 // Compile error
10 if(t1.value < t2.value){
11 cout << "t1 is less than t2" << endl;
12 }
13
14 // Valid Swap
15 swap(t1, t2);
16 // Valid Swap
17 Thing temp = t1;
18 t1 = t2;
19 t2 = temp;
20

21 // Compile error
22 swap(t1.value, t2.value);

3
Question 1 C++ [20 Marks]
Complete the functions in question1.cpp. This code is graded using the unit test cases provided
in tests.cpp.
1. Write a function that accepts a string and returns the number of vowels (aeiouAEIOU) in
the string. Do not count the letter y as a vowel. [4]
int CountVowels(const string& myString);
2. Write a function that accepts a string and returns the 0-based index of the first vowel in
the string. If there are no vowels, then return −1. [4]
int FirstVowelIndex(const string& myString);
3. Write a function that accepts a vector of integers and returns the average of the numbers
in the vector. If the vector is empty, return 0. [4]
double Average(const vector<int>& myVector);
4. Write a function that accepts a pointer to a vector of integers and pushes the value 42 to
the end of the vector supplied vector. [4]
void PushBack(vector<int>* myVector);
5. Write a function that accepts a vector of Things and returns true if the elements in the
vector are in ascending order, otherwise false. [4]
Empty or single-element vectors are considered sorted. You may use at most n − 1 com-
parisons between Things, where n is the number of elements in the vector.
bool IsSorted(const vector<Thing>& myVector);

Question 2 Searching and Sorting [15 Marks]


The functions in this question are graded using the unit test cases provided in tests.cpp.

You may not use any of the built in std::sort algorithms. You may not access internal fields of
Thing (e.g., .value); compare and swap whole Thing objects using their provided operators.
Do not use std::sort (or any other library sorting routine) — implement the specified algo-
rithm yourself. Submissions using such functions will receive 0 for that question.
1. Write a function that accepts a reference to a vector of Thing objects and returns the index
of the last Thing object with the relevant value. Return −1 if the value does not occur. [5]
int BackwardLinearSearch(const vector<Thing>& myVector, const Thing& value);
2. Write a function that accepts a reference to a vector of Thing objects and sorts the vector
in ascending order using the selection sort algorithm. [5]
void SelectionSort(vector<Thing>& myVector);
3. Write a function that accepts a reference to a vector of Thing objects and sorts the vector
in descending order using the insertion sort algorithm. [5]
void InsertionSortDescending(vector<Thing>& myVector);

4
Question 3 MyVector [24 Marks]
Complete the class in myvector.cpp. You will implement a simplified version of a dynamic
array similar to std::vector, supporting basic functionality for use in algorithms and iteration.
Your code will be graded using the unit test cases provided in tests.cpp.
The layout of the data is as per the typical vector implementation, with the data stored in a
contiguous block of dynamically allocated memory. The data is stored in the data member,
which is a pointer to the first element in the vector. The n_items member is the number of
elements actually stored in the vector, and the n_allocated member is the total number of
elements that the vector can hold. The data is stored at the front of the allocated memory
buffer as usual in a C++ vector. When adding an item to a vector that is full, the reallocate
method should be called to first double the capacity of the vector. When an item is removed
from the vector, the memory should be reallocated to half the capacity if the number of elements
is strictly less than a quarter of the capacity.
1. Implement the default constructor. Initially the vector should be empty and should not
allocate any memory. [1]
2. Implement the functions size() and capacity(). [2]
int MyVector::size() const;
int MyVector::capacity() const;

3. Implement the reallocate method used internally by the class when the buffer needs to
change size. The function should perform all steps necessary to change the size of the
vector’s allocated memory and ensure the data is still valid. [9]
void MyVector::reallocate(size_t new_size);
4. Implement the push_back method. [4]
The push_back method should append an element at the end, reallocating the buffer with
twice the capacity when necessary. If the current capacity is 0, then allocate 1 element.
void MyVector::push_back(const Thing& value);

5. Implement the pop_front method. [6]


The pop_front method should remove the first element and shift remaining elements left.
The capacity should be halved if the number of elements is strictly less than a quarter of
the capacity.
void MyVector::pop_front();
6. Implement destructor for the MyVector class, which should free any dynamically allocated
memory. [2]
MyVector::~MyVector();

5
Question 4 Iterators [11 Marks]
An iterator is a lightweight object that lets you visit each element of a container in sequence.
Iteration uses a half-open range [begin, end):
• begin() returns an iterator that points at the first element;
• end() returns an iterator that points one past the last element.
You can then use the loop shown in

1 MyVector<Thing> container;
2
3 container.push_back(Thing(1));
4 container.push_back(Thing(2));
5 container.push_back(Thing(3));
6 container.push_back(Thing(4));
7 container.push_back(Thing(5));
8
9 for (auto it = container.begin(); it != container.end(); ++it) {
10 /* 1 2 3 4 5 */
11 }

to traverse over all the items in the collection.


Notably, we can define any access pattern by changing the way that our iterator is implemented.
For example, we can implement a reverse iterator that visits the items in the forward or reverse
order. By keeping the interface of the iterator the same, we can use the same loop pattern to
traverse the collection in reverse.

1 // Forward iterator
2 for (ForwardIterator it = container.begin(); it != container.end(); ++it) {
3 /* 1 2 3 4 5 */
4 }
5
6 // Reverse iterator
7 for (ReverseIterator it = container.rbegin(); it != container.rend(); ++it) {
8 /* 5 4 3 2 1 */
9 }

For this test you will implement two iterator types:


1. Implement a forward iterator that visits elements from first to last, exposed via begin()
and end(). [5]
2. Implement a reverse iterator that visits elements from last to first, exposed via rbegin()
and rend(). [6]
For each iterator type, implement:
• a suitable iterator constructor (so the container can create the iterator objects, as well
as the relevant begin/end or rbegin/rend on the container itself, to create and setup the
iterator objects).

6
• operator++(): Allows us to run ++it on our iterator. On the normal iterator this pro-
gresses to the following item, on the reverse iterator, this moves to the previous item in
the container.
• operator==(): Check whether two iterators are equal. Two iterators are equal if they
point to the same item, or if they are both past the end of the sequence.
• operator*(): Returns a reference to the current element.
Note that I will never dereference the end() or rend() iterators, as this would be undefined
behaviour.

You might also like