Commit 86eea5c9 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Remove exercises from index

parent 4cacfbbc
# Exercise sheet 10
## Exercise 1 (Standard Containers)
The C++ standard library provides implementations of several common data-structures: vector, list, deques, queues,...
We want to compare some of them for performance of insertion and sorting algorithms:
1. Create an empty Container of type `std::list, std::vector, std::deque, ...` with value type one of {`char, double, A`},
where `A` is a class
```c++
struct A {
short s; int i; char c;
A(short s, int i, char c) : s(s), i(i), c(c) {}
};
```
and fill the container with `1,000,000` elements (or more) of random values using the function `push_back`, or `push_front`
and `emplace_back` or `emplace_front`, respectively.
2. Add a comparison operator for objects of type `A`, i.e.,
```c++
// lexicographical comparison
inline bool operator<(A const& lhs, A const& rhs)
{
return std::tie(lhs.s, lhs.i, lhs.c) < std::tie(rhs.s, rhs.i, rhs.c);
}
```
and sort the containers using a function like `std::sort` (from `<algorithm>`) or a member function `container.sort()`.
3. Measure the time needed for each of the above steps. Therefore use the class `Timer` provided in the lecture material folder.
### Hints
- Use the functions `std::rand()` or functions / classes from `<random>` (e.g. `uniform_int_distribution`) to produce the
random numbers. See [cppreference:rand](https://en.cppreference.com/w/cpp/numeric/random/rand),
[cppreference:random](https://en.cppreference.com/w/cpp/numeric/random).
- In case the data-structure provides such a function, use `reserve()` or `resize()` before inserting or filling with the values.
Compare to the time without previous reservation of space.
## Exercise 2 (Inheritance and Composition)
Write a class `NumVector`, which represents a numerical vector. The size of the vector (passed as constructor argument)
has to be fixed. Read and write access to the individual entries of the vector should be granted by means of the
brackets operator. In addition, the class should have the method `double norm()` that calculates
the Euclidean norm of the vector. Other methods should not be visible. In particular, a `NumVector`
should not be a `std::vector<double>`!
Design two implementations of this class, both of which store the values in a `std::vector<double>`.
The first implementation has to be derived from `std::vector<double>` and the second one should
not use inheritance. Use two different header files for this (e.g. `NumVector[1/2].hh`), and only include
one of them at a time when testing with the programs below.
Test your implementation as follows:
1. The classes should work correctly with the following main program.
```c++
#include <iostream>
#include "NumVector[1/2].hh"
int main()
{
NumVector v(3);
v[0] = 1; v[1] = 3, v[2] = 4;
NumVector const& w = v;
std::cout << "norm is " << w.norm() << std::endl;
std::cout << "vector is [" << w[0] << ", " << w[1] << ", " <<w [2] << "]" << std::endl;
}
```
2. The following program must not compile though!
```c++
#include <vector>
#include "NumVector[1/2].hh"
void vectorTest(std::vector<double>& v) {}
int main()
{
NumVector v(3);
v.resize(2); // must be hidden, just like other methods of std::vector!
vectorTest(v); // this should also lead to a compiler error!
}
```
## Exercise 3 (Inheritance and Functions)
Find the errors in the following program. What is the output after the incorrect lines are removed,
and why?
```c++
#include <iostream>
class SuperClass
{
public:
void foo() const
{
std::cout << "SuperClass::foo" << std::endl;
}
};
class DerivedClass : public SuperClass
{
public:
void foo()
{
std::cout << "DerivedClass::foo" << std::endl;
}
};
class LeafClass : private DerivedClass
{
public:
void bar()
{
foo();
}
};
void test(SuperClass const& super)
{
super.foo();
}
int main()
{
SuperClass super;
DerivedClass derived;
LeafClass leaf;
super.foo();
derived.foo();
test(derived);
leaf.bar();
test(leaf);
}
```
## Exercise 4 (External Libraries)
We have implemented our own matrix and vector classes in the last exercises. For most of the
data-structures there is an efficient implementation already available. Especially for linear
algebra containers and algorithms there exist a large variety of libraries, all with a different focus
or intention, often with a similar syntax.
We want to explore some of the external libraries in this exercise. The task is as follows:
- Choose one of the libraries below
- Download and install (compile) the library (if necessary)
- Create a source file `main.cc` that performs the following steps:
* Create a dense matrix `A` of size 100 x 100 and a vector `b` of size 100.
* Fill the matrix with the 1d finite-difference 3-point laplace stencil, i.e. on the diagonal the value `+2` and on
the first lower and upper off-diagonal the value `-1`.
* Fill the vector with all entries `1`.
* Solve the linear system `A*x = b` for the unknown vector `x`
- Provide a `Makefile` or a compile script that links or includes the external library
### Possible external libraries
- [MTL4](http://www.simunova.com/de/mtl4)
- [Eigen3](http://eigen.tuxfamily.org)
- [Blaze](https://bitbucket.org/blaze-lib/blaze)
- [Armadillo](http://arma.sourceforge.net)
# Exercise sheet 11
## Exercise 1 (Function templates)
1. Write a function template `minmax(a,b)` to calculate minimum and maximum of two values `a` and
`b` of the same type given as arguments to the function. The return type should be a pair of values, i.e.
`std::pair<T,T>`, where `T` is the type of the arguments. The first entry in the pair corresponds to the minimal
value, the second entry to the maximal value.
What are the requirements on the types that must be fulfilled in order to call the function properly?
**Guru Question:** Could this be implemented using C-Macros? If yes, how? Why are function templates the
better choice?
2. Consider the generic function
```c++
template <typename T1, typename T2>
T1 min(T1 a, T2 b)
{
return a < b ? a : b;
}
```
Which design decision are inappropriate? Why? Construct a function call that results in a wrong result!
3. Templates can be used to specify the functionality in a function, e.g.
```c++
#include <functional> // -> std::less
template <typename T, typename Compare = std::less<T> >
T min(T a, T b, Compare less = Compare{})
{
return less(a, b) ? a : b;
}
```
How to call that function for values of type `int`, `double`, and for a user-defined type, like `Rational`?
What do you need to implement in order to make the call work?
## Exercise 2
We have a header file `ex11.h` that declares a class and three methods:
```c++
template<typename T> struct A { void foo(); };
template<typename T> void bar1();
template<typename T> void bar2();
void bar3();
```
In another header file `ex11.hh` we provide the definition of the member-function of the class-template:
```c++
template<typename T>
void A<T>::foo() { std::cout << "foo-T\n"; }
```
In a third file `ex11_impl.cc` we provide the implementation of two methods:
```c++
template<typename T> void bar1() { std::cout << "bar1\n"; }
void bar3() { bar1<double>(); }
```
and finally in the main `ex11.cc` file we have
```c++
template<> void A<double>::foo() { std::cout << "foo-double\n"; }
template<typename T> void bar2() { std::cout << "bar2\n"; }
int main() {...}
```
1. Try to find the links between these file. Which files needs to include which else. Finally we want to compile
both `.cc` files via
```
> g++-7 ex11_impl.cc ex11.cc -o ex11
```
2. Consider the following implementation of the main() function:
```c++
int main()
{
A<float> a;
a.foo();
bar1<float>();
bar1<double>();
bar2<double>();
bar3();
}
```
Try to compile the code. What error do you get and why? Try to remove the corrupted line and compile
again! What is the output of the program and why? Use the tools `nm` or `objdump` in order to find the provided
and expected symbols in the files.
## Exercise 3 (Class Templates)
Choose one of the three classes from the last exercises (`Rational`, `Matrix`, or `Polynomial`) and transform it into a
class template, i.e.
```c++
template <class C, class V>
class Polynomial {
using coeff_type = C; // type used for the coefficients
using value_type = V; // type used for the evaluation argument
...
};
template <class T>
class Matrix {
using value_type = T; // type used for the matrix entries
...
};
template <class T>
class Rational
{
using value_type = T; // type used for numerator and denominator
...
};
```
1. Try it out with the template types filled with the explicitly specified types before and run the tests.
2. What are the requirements on the template parameters, i.e. what are the operations you need to perform with
objects of that types?
3. Try to instantiate your class with one of the other classes, i.e. `Rational<Polynomial>` to form a rational function,
`Matrix<Rational>` a matrix with rational coefficients, or `Polynomial<double,Matrix>` a matrix polynomial. What
functionality is missing in the template types and can you easily correct/extend it? Run the test suite on those types!
#### Note
- The full correction/extension in step 3 might be a complicated task. This is optional!
Just identity the missing functions, maybe implement it with a placeholder function or an error message so that at least the code
compiles.
- Please, only implement one of the class templates.
#### Resources
- [Polynomial greatest common devisor](https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor),
[Polynomial division](https://en.wikipedia.org/wiki/Polynomial_long_division),
[Rational function](https://en.wikipedia.org/wiki/Rational_function)
- [Matrix polynomial](https://en.wikipedia.org/wiki/Matrix_polynomial)
- [Class Templates](https://en.cppreference.com/w/cpp/language/class_template)
## Exercise 4 (Guru Exercise)
Write a class `SmartPointer<T>` representing a smart pointer:
- `SmartPointer` has a destructor, taking a pointer of type `T*` and store it in a member variable
- `SmartPointer` has a destructor, releasing the memory of the stored pointer .
- A dereferencing operator `*` and a member access operator `->` should be added.
- What is a reasonable default constructor?
- Does it make sense to define copy or move constructor/assignment operator?
- What other methods should be added to make it a pointer-like type?
Try out your smart pointer with the following example code:
```c++
SmartPointer<double> f() {
return SmartPointer<double>{ new double };
}
int main() {
auto p = f();
*p = 1.0;
auto q = p; // Does this make sense for your pointer type?
*q = 2.0;
// What is the effect on p?
}
```
Use `valgrind` to test for memory errors.
# Exercise sheet 12
## Exercise 1 (Functors)
Write a functor `Scale` that multiplies an assigned value with a constant factor. This constant factor
is stored as member variable in the functor and is initialized in the constructor. The `operator()` receives a
reference to the value and scales this argument (using pass-by-reference).
Use the STL algorithm `std::for_each` to scale the values of a `std::array`, or `std::vector`.
### Note
- The semantics of `std::for_each` is slightly different from the for-each implementation shown in the lecture. The functor
should not return the result, but change its argument that is passed-by-reference!
- In order to use `std::for_each` you need to include the header `<algorithm>`.
### Resources
- [cppreference:for_each](https://en.cppreference.com/w/cpp/algorithm/for_each)
## Exercise 2 (Iterators)
1. Write an iterator `integer_range_iterator` that always returns an integer on dereferencing and increments this
integer when incrementing the iterator. Thus, when you loop over all values of the iterator you get an
increasing sequence of numbers, without storing this sequence explicitly. Provide a constructor, that takes the
initial value of the integer that is incremented. Example of usage:
```c++
for (auto it = integer_range_iterator(0); it != integer_range_iterator(10); ++it)
std::cout << *it << " ";
```
This should print
```
0 1 2 3 4 5 6 7 8 9
```
Implement the dereferencing operator, increment operator and comparison operators.
2. Write a *pseudo-container* `integer_range`, that has just two member functions `begin()` and `end()` returning
the `integer_range_iterator` of the begin and end of the container. The values begin and end should
be given in the constructor of the container.
### Note
- A word *pseudo-container* here in this exercise refers to a container that does not store all its elements
directly, but provides a way to iterate over all its values.
- (optional) In addition to the `begin()` and `end()` member-function, you could easily implement element-access functions
`operator[]` and size functions for the `integer_range` container. What about mutable access functions? Can you implement
the whole interface of a `std::vector`?
## Exercise 3 (Functor composition)
1 If you have functors that represent some mathematical functions like `sqr`, `sqrt`, `exp`, `tanh`,
... how could you combine these functors in order to build more complex operations. Mathematically spoken:
let $`f : A \to B`$ and $`g : B \to C`$ be two unary functors with `argument_types` $`A`$ and $`B`$, and `return_types` $`B`$
and $`C`$ respectively. Build a functor `Composer` that implements the composition $`f \circ g : A \to C, x \mapsto g(f(x))`$.
In order to do so, write a class `Composer` first that takes two constructor arguments representing the functors
for $`f`$ and $`g`$ and provide a free function that instantiates this class:
```c++
template <class F, class G>
class Composer
{
public:
Composer(F const& f, G const& g) : (...) { ... }
result_type operator()(argument_type const& x) const { ... }
private:
// ...
};
template <class F, class G>
Composer<F,G> compose(F const& f, G const& g) {
return Composer<F,G>(f,g);
}
```
Fill in the missing parts and specify `argument_type` and `result_type`.
3. (optinal) Write the composer class, using C++-Lambda expressions instead. See also
[CppTruths](http://cpptruths.blogspot.de/2014/03/fun-with-lambdas-c14-style-part-1.html) for possible
solutions.
### Note
- Instead of providing a *generator*-function to instantiate the class, you could rely on class-template-argument deduction of c++17.
### Resources
- [cccreference:class_template_argument_deduction](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)
## Exercise 4 (Algorithms)
What does the following algorithm implement?
```c++
template <class InputIt1, class InputIt2>
bool ALGORITHM1(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
for (; first1 != last1; ++first1, ++first2) {
if (!(*first1 == *first2)) {
return false;
}
}
return true;
}
```
# Exercise sheet 13
## Exercise 1 (Iterators)
Given the following for statement:
```c++
for (int i = 0; i < max_length; ++i)
if (line[i] == ' ')
space_count++;
```
Assume that line is a `std::vector`. Rewrite the `for` statement so it instead steps through `line` using a
vector iterator.
## Exercise 2 (Iterators)
Do the following on a container, e.g. a `std::vector`, with `int`s, using standard function objects, function
adapters, algorithms, and maybe also some own function objects:
1. Find all values which are larger than a certain value.
2. Find all values which are not equal to certain value.
3. Multiply all values with a certain factor.
## Exercise 3 (Iterators)
In *python* operations on ranges are a fundamental concept and make the language very nice to use. An
example is the `map` operation, that takes a range and applies a functor to each element, when traversing the
range:
```python
for x in map(lambda x: 2*x, range(0,10)):
print(x)
```
Here, an integer range `[0, 10)` is created and the entries are scaled by a factor 2, but only during iteration in
the loop. We want to implement something similar in C++:
- take a functor and a range,
- provide iterators over the range and
- return on dereferencing the mapped value
Therefore, write a class `MappedRange<Functor,Range>` with a constructor that stores a functor, gets a range
and stores iterators to begin and end of the range:
```c++
MappedRange(Functor f, Range const& range)
: f_(f)
, it_(range.begin())
, end_(range.end())
{}
```
What are the types of the stored iterators? Then, implement a class `MappedIterator` that contains `operator++`,
`operator==`, and `operator!=` implemented in terms of the original range iterators! Finally, implement a new
dereferencing operation `operator*`, by returning the mapped dereferenced range iterator.
```c++
auto operator*() const {
return f_(*it_);
}
```
This `MappedIterator` needs the functor and a range iterator to work with. Write member-functions `begin()`
and `end()` in the class `MappedRange` that return a `MappedIterator`.
To create an instance of the class `MappedRange` write a generator function, i.e., a function template that just instantiates
the class:
```c++
template <class Functor, class Range>
MappedRange<Functor, Range> map(Functor f, Range const& range)
{
/* implementation here */
}
```
Try out your implementation with a vector and a list filled with some values, or with the integer-range
from exercise sheet 12.
## Exercise 4 (Iterators)
Provide an iterator for the class `Vector` of sheet 9. Therefore Implement a new class for the vector iterators
that is instantiated and returned in the two member function `begin()` and `end()` in the class `Vector`. This iterator
class needs a constructor with the address of the data, a dereferencing operator, increment and decrement operator and
comparison operators. See also http://www.cplusplus.com/reference/iterator/iterator as a reference implementation of a
user defined iterator.
Test your iterator with some algorithms from the standard library
## Exercise 5 (Algorithms)
What does the following algorithm implement?
```c++
template <class ForwardIt>
ForwardIt ALGORITHM2(ForwardIt first, ForwardIt last)
{
if (first == last)
return last;
ForwardIt result = first;
while (++first != last) {
if (!(*result == *first) && ++result != first) {
*result = *first; // or: ... = std::move(*first)
}
}
return ++result;
}
```
# Exercise sheet 14
There is no new exercise sheet. Please discuss and solve unfinished exercises from the older sheets.
Supports Markdown
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