Exercise 9

Added Exercise 9 to repository
This commit is contained in:
JirR02 2025-04-21 23:47:45 +02:00
parent 950098d35e
commit e5548947e2
4 changed files with 444 additions and 0 deletions

View File

@ -0,0 +1,175 @@
#+title: Task 1: Complex Numbers
#+author: JirR02
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
Create your own data type for complex numbers that can be used as a
drop-in replacement for double. The definition of the data type and the
forward declarations of operators must be in file =complex.h=, while the
implementation of operators must be in file =complex.cpp=.
1. Define a struct named =Complex= that represents a complex number in
the cartesian form. As data type use floating point numbers with
=double= precision.
2. Implement input and output =(>>, <<)= operators for reading and
writing of complex numbers.
A complex number \((x pm yi)\) is represented in the format =[x,y]=,
where =x= and =y= follows the format of floating point numbers with
=double= precision.
E.g., =[-2,5]= represents \((-2 + 5i)\) . *Important: No spaces*.
*Note*: You can assume that your input value is a well-formatted complex
number.
3. [@3] Implement arithmetic operators for addition, subtraction,
multiplication, and division \((+,-,*,/)\) of complex numbers. For
the division, you may assume that the squared modulus of the divisor
is not zero, even after rounding it to a floating point number.
Finally, you do not need to treat the case of division by zero.
4. Implement the negation operator \((-)\) of complex numbers.
5. Implement comparison operators for equality and inequality
\((==,!=)\) of complex numbers.
*Hint*: recall from Exercise 5 how to correctly compare floating point
numbers.
* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
** =complex.h=
:PROPERTIES:
:CUSTOM_ID: complex.h
:END:
#+begin_src cpp
#pragma once
#include <cmath>
#include <iostream>
struct Complex {
double a;
double b;
};
// arithmetic operators
Complex operator+(const Complex &cn1, const Complex &cn2);
Complex operator-(const Complex &cn1, const Complex &cn2);
Complex operator*(const Complex &cn1, const Complex &cn2);
Complex operator/(const Complex &cn1, const Complex &cn2);
// negation operator
Complex operator-(const Complex &cn1);
// equality and inequality operators
bool operator==(const Complex &cn1, const Complex &cn2);
bool operator!=(const Complex &cn1, const Complex &cn2);
// reads a complex number from input
std::istream &operator>>(std::istream &in, Complex &a);
std::ostream &operator<<(std::ostream &out, const Complex &a);
#+end_src
** =complex.cpp=
:PROPERTIES:
:CUSTOM_ID: complex.cpp
:END:
#+begin_src cpp
#include "complex.h"
#include <cstdlib>
std::istream &operator>>(std::istream &in, Complex &a) {
char open;
char comma;
char close;
double aa;
double ab;
in >> open;
if (open == '[') {
in >> aa >> comma >> ab >> close;
if (comma == ',' && close == ']') {
a.a = aa;
a.b = ab;
} else {
std::cerr << "Invalid Input!";
}
} else {
std::cerr << "Invalid Input!";
}
return in;
}
std::ostream &operator<<(std::ostream &out, const Complex &a) {
return out << "[" << a.a << "," << a.b << "]";
}
Complex operator+(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = cn1.a + cn2.a;
double b = cn1.b + cn2.b;
res.a = a;
res.b = b;
return res;
}
Complex operator-(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = cn1.a - cn2.a;
double b = cn1.b - cn2.b;
res.a = a;
res.b = b;
return res;
}
Complex operator*(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = (cn1.a * cn2.a) - (cn1.b * cn2.b);
double b = (cn1.a * cn2.b) + (cn1.b * cn2.a);
res.a = a;
res.b = b;
return res;
}
Complex operator/(const Complex &cn1, const Complex &cn2) {
Complex res;
double a = (cn1.a * cn2.a + cn1.b * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
double b = (cn1.b * cn2.a - cn1.a * cn2.b) / (cn2.a * cn2.a + cn2.b * cn2.b);
res.a = a;
res.b = b;
return res;
}
Complex operator-(const Complex &cn1) {
Complex res;
double a = -cn1.a;
double b = -cn1.b;
res.a = a;
res.b = b;
return res;
}
bool operator==(const Complex &cn1, const Complex &cn2) {
double epsilon = 0.1;
return (std::abs(cn1.a - cn2.a) < epsilon) &&
(std::abs(cn1.b - cn2.b) < epsilon);
}
bool operator!=(const Complex &cn1, const Complex &cn2) {
double epsilon = 0.1;
return (std::abs(cn1.a - cn2.a) > epsilon) ||
(std::abs(cn1.b - cn2.b) > epsilon);
}
#+end_src
--------------
Made by JirR02 in Switzerland 🇨🇭

View File

@ -0,0 +1,96 @@
#+title: Task 2: Understanding struct & classes
#+author: JirR02
/This task is a text based task. You do not need to write any
program/C++ file: the answer should be written in main.md (and might
include code fragments if questions ask for them)./
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
Consider the following definitions:
1.
#+begin_src cpp
struct A {
int a;
double b;
int c;
};
A str = {1, 1.5, 2};
std::vector<int> vec = {1, 1, 3};
int& a = vec[0];
#+end_src
For each of the provided expressions state their /C++ type/ and /value/:
1. =str.a * str.b=
2. =str.b == vec[1]=
3. =str.a * str.b / str.c=
4. =vec[str.a] / str.c=
5. =a / 2 - str.b=
2. [@2]
#+begin_src cpp
class B {
public:
B(): vec(128) {
for (int i = 0; i < 128; ++i) {
vec[i] = 0;
}
}
// PRE: ...
// POST: ...
void add(const char c) {
++vec[c];
}
// PRE: ...
// POST: ...
int get(const char c) const {
return vec[c];
}
private:
std::vector<int> vec;
};
#+end_src
Determine PRE- and POST-conditions for the methods add and get. As these
methods are members functions of class B, PRE- and POST-conditions
should be derived taking the public interface of the class into account.
* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
#+begin_src markdown
1. `plain|`
1. Type: `cpp|double` / Value: `cpp|1.5`
2. Type: `cpp|bool` / Value: `cpp|true`
3. Type: `cpp|double` / Value: `cpp|0.75`
4. Type: `cpp|int` / Value: `cpp|0`
5. Type: `cpp|double` / Value: `cpp|-1.5`
2. ```c++
// PRE: 0 <= c < 128
// POST: Increments the value of the vector at position c
void add(const char c);
// PRE: 0 <= c < 128
// POST: Gets the value of the vector at position c
int get(const char c) const;
#+end_src
```
--------------
Made by JirR02 in Switzerland 🇨🇭

View File

@ -0,0 +1,62 @@
#+title: Task 3: Averager
#+author: JirR02
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
Write a class =Averager= that computes averages of given values of type
=double=.
Initially, an instance of class =Averager= does not contain any value.
The class =Averager= must provide the following functionality:
#+begin_src cpp
// POST: Adds a value to the current average calculation.
void add_value(double value);
// POST: Returns the average of all added values,
// or zero, if no value has been added.
double get_average();
// POST: Removes all values from the current average calculation.
void reset();
#+end_src
The declaration and implementation of class Averager must be split
between header file (=averager.h=, containing declaration) and
implementation file (=averager.cpp=, containing implementation).
/Note: The above functions have already been declared in averager.h for
you. You only need to provide function definitions in/ =averager.cpp=.
* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
#+begin_src cpp
#include "averager.h"
void Averager::add_value(double value) {
sum += value;
++count;
}
double Averager::get_average() {
double res;
if (count == 0)
res = 0;
else
res = sum / count;
return res;
}
void Averager::reset() {
sum = 0;
count = 0;
}
#+end_src
--------------
Made by JirR02 in Switzerland 🇨🇭

View File

@ -0,0 +1,111 @@
#+title: Task 4: [Hidden tests][Exam 2019.02 RW] Number Pairs with Sum
#+author: JirR02
* Number of pairs with given sum
:PROPERTIES:
:CUSTOM_ID: number-of-pairs-with-given-sum
:END:
In this exercise, you are going to use iterators to count the number of
pairs in a vector which sum up to a given value.
More formally, given a vector \(v\) of length \(n\) and a value \(s\),
we are interested in the number of pairs \(i\),\(j\) for which the
following conditions hold:
1. \(0 leq i < j < n\)
2. \(v\[i\] + v\[j\] = s\)
* Task
:PROPERTIES:
:CUSTOM_ID: task
:END:
The function =pairs_with_sum= declared in =pair_sum.h= computes the
number of pairs which sum up to a given value. Your task is implementing
this function in =pair_sum.cpp=.
* Input & Output
:PROPERTIES:
:CUSTOM_ID: input-output
:END:
The program first reads a list of integers (separated by spaces) from
=std::cin=. The first integer specifies the value \(s\). The other
integers specify the vector \(s\).
The program then calls the function
=pairs_with_sum(s, v.begin(), v.end())= to compute the number of pairs
that sum up to \(s\).
Finally, the result is printed to the console.
*** Example:
:PROPERTIES:
:CUSTOM_ID: example
:END:
- sum = 8, vector = 1 7 2 6 6
- pairs with sum(1,7), (2,6), (2,6)
- \(Rightarrow\) number pairs = 3.
#+begin_src shell
8 1 7 2 6 6
number of pairs with sum 8: 3
#+end_src
*Note*: This was a task in the 2019.02 RW exam but has since been
adapted slightly: better input handling (no need to press CTRL+D/CTRL+Z
to end vector), description, file structure, and master solution.
*Note*: You can safely assume that the sum of two values in the vector
does not cause an overflow.
* Hidden test cases
:PROPERTIES:
:CUSTOM_ID: hidden-test-cases
:END:
This exercise has some hidden test cases. You will see whether these
tests passed or failed, but you will not see the test input or the
expected output.
** Persistent input
:PROPERTIES:
:CUSTOM_ID: persistent-input
:END:
To help you in testing your code, you can enter your custom test input
in input.txt. When running the program, you can let CodeExpert read the
input from the file.
Write some program input in input.txt. Run the program as usual. Type f
(no spaces) in the terminal window and press Enter. The program will use
the contents of input.txt as input. Using this feature is entirely
optional and does not affect your score.
* Solution
:PROPERTIES:
:CUSTOM_ID: solution
:END:
#+begin_src cpp
#include "pair_sum.h"
#include <climits>
// PRE: for any two indices i and j, v[i] + v[j] ≤ INT_MAX
// POST: returns the number of indices (i,j), i<j of a vector v
// that corresponds to the given iterator range such that
// v[i] + v[j] == sum.
int pairs_with_sum(int sum, iterator begin, iterator end) {
int count = 0;
int size = end - begin;
for (int i = 0; i < size; ++i) {
for (int j = i + 1; j < size; ++j) {
iterator cur_begin = begin + i;
iterator cur_end = begin + j;
if (*cur_begin + *cur_end == sum)
++count;
}
}
return count;
#+end_src
--------------
Made by JirR02 in Switzerland 🇨🇭