Exercise 9
Added Exercise 9 to repository
This commit is contained in:
parent
950098d35e
commit
e5548947e2
175
Informatik_I/Exercise_9/Task_1/README.org
Normal file
175
Informatik_I/Exercise_9/Task_1/README.org
Normal 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 🇨🇭
|
96
Informatik_I/Exercise_9/Task_2/README.org
Normal file
96
Informatik_I/Exercise_9/Task_2/README.org
Normal 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 🇨🇭
|
62
Informatik_I/Exercise_9/Task_3/README.org
Normal file
62
Informatik_I/Exercise_9/Task_3/README.org
Normal 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 🇨🇭
|
111
Informatik_I/Exercise_9/Task_4/README.org
Normal file
111
Informatik_I/Exercise_9/Task_4/README.org
Normal 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 🇨🇭
|
Loading…
x
Reference in New Issue
Block a user