
1. Implementáld az alábbi 2ds matematikai vektor osztályt:

------------------------------------------------|
|  class Vector2                                |
|-----------------------------------------------|
| + x : float                                   |  -> Nincs getter, és szetter, mert azok lassítanának. (Függvényhívásnak van minimális erőforrás igénye) 
| + y : float                                   |  -> Ilyen matematikai osztályoknál, érdemes ilyeneket kioptimalizálni. PLussz leírni is sok. getx(), setx() etc.
| + abs() : Vector2                             |  -> visszaadja egy új vektorba ennek a vektornak az abszolút értékét. (x, y abszolút értékét veszi)
|                                               |      Abszolút érték képlet:  ha egy a < 0 ret -a, else ret a;
| + angle() float                               |  -> atan2(x, y)
| + angle_to(b : Vector2) : float               |  -> atan2(cross(b), dot(b));
| + cross(b : Vector2) : float                  |  -> Cross product -> x * b.y - y * b.x;
| + clamped(len : float) : Vector2              |  -> normalized() * len
| + direction_to(b : Vector2) : Vector2         |  -> Visszaad egy normalizált vektort ami ebből b be mutat. (A képlet: (b - a).normalized()) (operator-)
| + distance_to_squared(b : Vector2) : float    |  -> (x - b.x) * (x - b.x) + (y - b.y) * (y - b.y);
| + distance_to(b : Vector2) : float            |  -> sqrt((x - b.x) * (x - b.x) + (y - b.y) * (y - b.y));
| + dot(b : Vector2) : float                    |  -> dot product -> Ha a 2 vektor 90 fokosz szöget zár be, akkor 0.
|                                               |         Pozitív, ha a 2 vektor által bezárt szög kisebb mint 90 fok, negatív, ha nagyobb.
|                                               |         képlet: x * b.x + y * b.y.
| + is_equal_approx(b : Vector2) : bool         |  -> nagyjából egyenlőek-e a vektorok. A max különbség legyen 0.00001 (Epszilon).
| + length() : float                            |  -> sqrt(x * x + y * y)
| + length_squared() : float                    |  -> A hossz a gyökvonás nélkül. (A gyökvonás relatíve lassú, és ha csak össze kell 
|                                               |                         hasonlítani hosszakat, akkor elég így)
| + lerp(b : Vector2, t : float) : Vector2      |  -> Linear interpolate -> a jelenlegi vektor és b közötti átmenetvektort adja vissza t paraméter felhasználásával.
|                                               |     A t 0 és 1 közötti. Képlet: newx = x + (t * (b.x - x)); és newy = y + (t * (b.y - y));
| + normalized() : Vector2                      |  -> A vektor normalizálva. Normalizált vektor = a hossza 1. 
|                                               |     float l = length_squared(); ha nem 0, gyököt kell vonni belőle, és le kell osztani x, y-t is vele
| + normalize()                                 |  -> Maga a vektor normalizálódik.
| + add(b: Vector2)                             |  -> x += b.x, y += b.y
| + sub(b: Vector2)                             |  -> x -= b.x, y -= b.y
| + operator+=(b: Vector2)                      |     etc
| + operator-=(b: Vector2)                      |
| + operator+(a: Vector2, b: Vector2) : Vector2 |
| + operator-(a: Vector2, b: Vector2) : Vector2 |
| + operator*=(b: float)                        |  -> x és y-t is megszorozzuk b-vel.
| + operator*(Vector2 a, float b) : Vector2     |  -> x és y-t is megszorozzuk b-vel.
| + operator==(b: Vector2, b: Vector2) : bool   |
| + operator!=(b: Vector2, b: Vector2) : bool   |
| + Vector2()                                   |
| + Vector2(b : Vector2)                        |
| + Vector2(x : float, y : float)               |
------------------------------------------------|

2. Implementáld az alábbi 3ds matematikai vektor osztályt.

------------------------------------------------|
|  class Vector3                                |
|-----------------------------------------------|
| + x : float                                   |  -> Nincs getter, és szetter, mert azok lassítanának. (Függvényhívásnak van minimális erőforrás igénye) 
| + y : float                                   |  -> Ilyen matematikai osztályoknál, érdemes ilyeneket kioptimalizálni. PLussz leírni is sok. getx(), setx() etc.
| + z : float                                   |
| + abs() : Vector3                             |  -> visszaadja egy új vektorba ennek a vektornak az abszolút értékét. (x, y, y abszolút értékét veszi)
|                                               |      Abszolút érték képlet:  ha egy a < 0 ret -a, else ret a;
| + angle_to(b : Vector3) : float               |  -> atan2(cross(b).length(), dot(b));
| + cross(b : Vector3) : Vector3                |  -> Cross product -> x = (y * b.z) - (z * b.y), y = (z * b.x) - (x * b.z), z = (x * b.y) - (y * b.x)
| + clamped(len : float) : Vector3              |  -> normalized() * len
| + direction_to(b : Vector3) : Vector3         |  -> Visszaad egy normalizált vektort ami ebből b be mutat. (A képlet: (b - a).normalized())
| + distance_to_squared(b : Vector3) : float    |  -> return (b - *this).length_squared();  -> *this -> dereferencia operátor -> a this alapba mutató
| + distance_to(b : Vector3) : float            |  -> return (b - *this).length(); 
| + dot(b : Vector3) : float                    |  -> dot product -> Ha a 2 vektor 90 fokosz szöget zár be, akkor 0.
|                                               |         Pozitív, ha a 2 vektor által bezárt szög kisebb mint 90 fok, negatív, ha nagyobb.
|                                               |         képlet: x * b.x + y * b.y + z * b.z.
| + is_equal_approx(b : Vector3) : bool         |  -> nagyjából egyenlőek-e a vektorok. A max különbség legyen 0.00001 (Epszilon).
| + length() : float                            |  -> sqrt(x * x + y * y + z * z)
| + length_squared() : float                    |  -> A hossz a gyökvonás nélkül. (A gyökvonás relatíve lassú, és ha csak össze kell 
|                                               |                         hasonlítani hosszakat, akkor elég így)
| + lerp(b : Vector3, t : float) : Vector3      |  -> Linear interpolate -> a jelenlegi vektor és b közötti átmenetvektort adja vissza t paraméter felhasználásával.
|                                               |     A t 0 és 1 közötti. Képlet: newx = x + (t * (b.x - x)); és newy = y + (t * (b.y - y)); 
|                                               |     newy = z + (t * (b.z - z)); 
| + normalized() : Vector3                      |  -> A vektor normalizálva. Normalizált vektor = a hossza 1.
|                                               |     float l = length_squared(); ha nem 0, gyököt kell vonni belőle, és le kell osztani x, y, z-t is vele
| + normalize()                                 |  -> A vektor normalizálódik.
| + add(b: Vector3)                             |  -> x += b.x, y += b.y, z += b.z
| + sub(b: Vector3)                             |  -> x -= b.x, y -= b.y, z -= b.z
| + operator+=(b: Vector3)                      |      etc.
| + operator-=(b: Vector3)                      |
| + operator+(a: Vector3, b: Vector3) : Vector3 |
| + operator-(a: Vector3, b: Vector3) : Vector3 |
| + operator*=(b: float)                        |  -> x,y és z-t is megszorozzuk b-vel.
| + operator*(Vector2 a, float b) : Vector2     |  -> x,y és z-t is megszorozzuk b-vel.
| + operator==(b: Vector3, b: Vector2) : bool   |
| + operator!=(b: Vector3, b: Vector2) : bool   |
| + Vector3()                                   |
| + Vector3(b : Vector3)                        |
| + Vector3(x : float, y : float, z : float)    |
------------------------------------------------|


3. Implementáld az alábbi matematikai négyzet osztályt.

------------------------------------------------------|
|  class Rect2                                        |
|-----------------------------------------------------|
| + x : float                                         |  
| + y : float                                         | 
| + w : float                                         |
| + h : float                                         |
| + get_area() : float                                |  -> Terület (w * h)
| + intersects(b : Rect2) : bool                      |  -> Lejjebb
| + intersects_include_borders(b : Rect2) : bool      |  -> Lejjebb
| + encloses(b : Rect2) : bool                        |  -> Lejjebb
| + has_no_area() : bool                              |
| + has_point(x : float, y : float) : bool            |  
| + is_equal_approx(b : Rect2) : bool                 |  
| + grow(by : float)                                  |  -> x, y, csökkent, w,h növel by-al
| + shrink(by : float)                                |  -> x, y, növel, w,h csökkent by-al
| + operator+=(b: Rect2)                              | 
| + operator-=(b: Rect2)                              |
| + operator+(a: Rect2, b: Rect2) : Rect2             |
| + operator-(a: Rect2, b: Rect2) : Rect2             |
| + operator==(b: Rect2) : bool                       |
| + operator!=(b: Rect2) : bool                       |
| + Rect2()                                           |
| + Rect2(b : Rect2)                                  |
| + Rect2(x : float, y : float)                       |
| + Rect2(x : float, y : float, w : float, h : float) |
------------------------------------------------------|

intersects:
	if (x >= (b.x + b.w))
		return false;

	if ((x + w) <= b.x)
		return false;

	if (y >= (b.y + b.h))
		return false;

	if ((y + h) <= b.y)
		return false;

    return true;

intersects_include_borders:
	if (x > (b.x + b.w))
		return false;

	if ((x + w) < b.x)
		return false;

	if (y > (b.y + b.h))
		return false;

	if ((y + h) < b.y)
		return false;

     return true;

Encloses:

return (b.x >= x) && (b.y >= y) &&
		((b.x + b.w) <= (x + w)) &&
		 ((b.y + b.h) <= (y + h));


4. Implementáld az alábbi int-eket tároló vektor osztályt:

------------------------------------------------------|
|  class IntVector                                    |
|-----------------------------------------------------|
| + push_back(element : int)                          | 
| + pop_back()                                        | -> utolsó elem törlése
| + remove(index : int)                               |  
| + erase(element : int)                              | 
| + clear()                                           |  
| + empty() : bool                                    |
| + get(index : int) : int                            |  
| + get(index : int) : const &int, (const)            | -> 5. feladatban már hasznos optimalizáció lesz, 
|                                                     |     amúgy igazából nincs értelme const referenciaként visszaadni intet
| + set(index : int, value : int)                     |  
| + size() : int                                      |  
| + capacity() : int                                  |  
| + ensure_capacity(capacity : int)                   |  
| + resize(size : int)                                |  
| + append_array(other : IntVector)                   |  
| + find(val : int) : int                             | -> Megkeresi az adott értéket, és visszaadja az indexét, illetve ha nem található -1 et
| + dataw() : int*                                    | -> Visszaadja az adatokat tároló tömböt -> ki lehet optimalizálni vele függvényhívásokat, amikor fontos.
| + data() : const int*, (const)                      | -> Visszaadja az adatokat tároló tömböt, de ez konstans verzió.
| + operator[](index: int) : const &int, (const)      | -> 5. feladatban már hasznos optimalizáció
| + operator[](index: int) : &int                     | -> Ha esetleg összeakad az eggyel fejlebb lévővel, akkor hagyjátok ki az egyiket, majd később kipróbálom én is
| + IntVector()                                       |
| + IntVector(prealloc : int)                         |
| + IntVector(prealloc : int, grow_by : int)          |
|-----------------------------------------------------|
| - _data : int*                                      | -> Maga a tároló tömb
| - _actual_size : int                                | -> ekkora a tömb
| - _size : int                                       | -> size() ezt adja vissza / ennyi elem van eltárolva a vektorban
| - _grow_by : int                                    | -> Ha növelni kell a _data tömböt, akkor ennyivel legyen megnövelve
------------------------------------------------------|

5. A 4. feladatban elékszített IntVektor osztályból csinálj egy templatekkel általánosított Vector osztályt.

Fontos! A templatelt tagfüggvényeket implementációját vector.h-ba kell rakni! Vagy bele az osztályba, vagy a vector.h aljára!
Enélkül undefined reference hibákat fog dobmi a fordító!

Eddíg pl:

class IntVector {

    int get(int index);
    set(int index, int val);

    void push_back(int val);

    //etc...

    IntVector();

private:
    int *_data;
};

int main() {
    IntVector a;

    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    a.push_back(4);

    cout << a.get(1);

    a.set(1, 4);

    cout << a.get(1);

    //etc...

    return 0;
}

Most:

template <class T>
class Vector {

    T get(int index);
    set(int index, T val);

    //etc...

    Vector();

private:
    T *_data;
};

int main() {
    Vector<int> a; //Mindenhol ahol T-van, ki lessz replacelve int-re a compiler által!

    a.push_back(1);
    a.push_back(2);
    a.push_back(3);
    a.push_back(4);

    cout << a.get(1);

    a.set(1, 4);

    cout << a.get(1);

    //etc...

    //de így már lehet:
    Vector<float> b;
    Vector<string> c;

    //...

    return 0;
}

7. Valamelyik vektor osztályból készíts egy saját String osztályt. (Vector<char> -al ekvivalens), de készítsd el
   template nélkül, illetve adj hozzá általad hasznosnak ítélt függvényeket.
   néhány ötlet: to_float(), to_double(), to_int(), trim(), replace(), find(val : String), begins_with(str : String) : bool, ends_with(), 
   sub_str(int from, int num = -1), c_str(), operator==, operator!=, operator=, operator+=, operator+, remove(str : String),
   print(), format(), etc.

Megj: Ha implementáljátok a c_str() függvényt: Ez egy c/c++ on tömböt ad vissza (char *), és nyilván már tudjátok,
hogy egy ilyen tömbnek nem lehet megmondani a méretét. A trükk az, hogy ezek a c stringek nul termináltak.
Azaz az utolsó karakterük a 0 kontroll karaktert tartalmazza! Kódban: '\0' azza a 0. ASCII karakter.

Például, hogy egy ilyen char* es konstruktort szeretnétek csinálni, az valahogy így fog kinézni:

String::String(const char *p_c_str) {
	_data = nullptr;
	_actual_size = 0;
	_size = 0;
	_grow_by = 100;

	int i = 0;
	while (p_c_str[i] != '\0') {
		push_back(p_c_str[i]);
		++i;
	}
}

8. Az előző feladatokban sok helyen meg lehet jelölni paramétereket konstansként, illetve pl. konstans referenciává lehet alakítani őket.
   Menj végig az előző osztályokon, és mindenhol, ahol van értelme, ezeket add hozzá.
   (int-eket/float okat csak konstanssá érdemes átrakni, referenciává tenni őket nincs értelme!)
   (Érdemes másolatot csinálni, vagy pl. egy git commitban eltárolni az eredetieket, és csak úgy szerkesztgetni őket!)



