INFORMATIKA 3

Matematika BSc - BME TTK - 2026 tavaszi félév


6. gyakorlat - megoldások





1. feladat. Készítsünk programot, ami a felhasználótól kéri be síkbeli pontok koordinátáit, majd kiszámolja a ponthalmaz súlypontját. Adjunk lehetőséget a felhasználónak arra, hogy minden lépésnél eldöntse, hogy hozzáad-e újabb pontot a ponthalmazhoz, esetleg töröl-e egy már meglévő pontot, vagy pedig kiszámoltatja a súlypontot. Használjuk cin input stream-et és a switch utasítást az opciók közül való választásra (nem szükséges lekezelni azokat az eseteket, ha a felhasználó rossz inputot ad meg). Használjuk az előadáson írt bme::Point osztályt. Módosítsuk a programot úgy, hogy a pontokhoz súlyokat rendelhessünk, és az súlyozott átlagot számoljon.

Megoldás:

#include <iostream>
#include <vector>
#include "point.h"

using namespace bme;
using namespace std;

void calculateWeightedCentroid(const vector<Point>& points, const vector<double>& weights) {
    if (points.empty()) {
        cout << "Nincs elerheto pont.\n";
        return;
    }
    double sumX = 0, sumY = 0, totalWeight = 0;
    for (size_t i = 0; i < points.size(); ++i) {
        sumX += points[i].getX() * weights[i];
        sumY += points[i].getY() * weights[i];
        totalWeight += weights[i];
    }
    if (totalWeight == 0) {
        cout << "Osszsuly nem lehet nulla.\n";
        return;
    }
    cout << "Sulypont: (" << (sumX / totalWeight) << ", " << (sumY / totalWeight) << ")\n";
}

int main() {
    vector<Point> points;
    vector<double> weights;
    int choice;
    do {
        cout << "1: Uj pont hozzaadasa\n2: Pont torlese\n3: Sulypont szamitasa\n0: Kilepes\n";
        cout << "Valasztas: ";
        cin >> choice;

        switch (choice) {
            case 1: {
                double x, y, weight;
                cout << "Adja meg a pont koordinatait (x y) es sulyat: ";
                cin >> x >> y >> weight;
                points.push_back(Point(x, y));
                weights.push_back(weight);
                break;
            }
            case 2: {
                if (points.empty()) {
                    cout << "Nincs torolheto pont.\n";
                    break;
                }
                int index;
                cout << "Adja meg a torlendo pont indexet (0-tol kezdve): ";
                cin >> index;
                if (index >= 0 && index < points.size()) {
                    points.erase(points.begin() + index);
                    weights.erase(weights.begin() + index);
                } else {
                    cout << "Ervenytelen index.\n";
                }
                break;
            }
            case 3:
                calculateWeightedCentroid(points, weights);
                break;
            case 0:
                cout << "Kilepes...\n";
                break;
            default:
                cout << "Ervenytelen valasztas!\n";
        }
    } while (choice != 0);
    return 0;
}


2. feladat. Definiáljunk egy Counted nevű osztályt, amely számon tartja, hogy a program futása közben hány példánya létezik. Azaz, legyen egy static tagfüggvénye, amely visszaadja, hogy az adott pillanatban mennyi Counted objektum található a memóriában.

Megoldás:

counted.h

#ifndef COUNTED_H
#define COUNTED_H

class Counted {
private:
    static int n_objects;
public:
    Counted() { n_objects++; }
    ~Counted() { n_objects--; }
    static int count() { return n_objects; }
};

#endif


counted.cpp

#include "Counted.h"
int Counted::n_objects = 0;


Egy tesztprogram:

#include "counted.h"
#include <iostream>
using namespace std;
int main() {
    Counted X, Y;
    Counted* array;
    array = new Counted[20];
    cout << "There are " << Counted::count()
        << " Counted objects in memory" << endl;
    delete[] array;
    cout << "And now there are " << Counted::count()
        << " Counted objects in memory" << endl;
    return 0;
}


3. feladat. Csináljunk egy SmartArray osztályt, amely úgy működik, mint egy int tömb, de tetszőleges indexet megadhatunk neki. A deklaráció így nézzen ki:

SmartArray X(k);

Ez a példány viselkedjen úgy, mint egy int-ekből álló k elemű tömb, de az indexelés ne csak 0 és k-1 közt legyen lehetséges: az X[i] adja vissza az i modulo k maradékának megfelelő indexű elemet, ahol k a tömb elemszáma. Írjunk másoló konstruktort és értékadó = operátort is az osztályhoz.

Megoldás:

smart_array.h

#ifndef SMART_ARRAY_H
#define SMART_ARRAY_H

namespace bme {

    class SmartArray {
    private:
        int N;
        int* data;
        int adjust_index(int k)const;
    public:
        SmartArray(const SmartArray& other);
        SmartArray(int nels);
        ~SmartArray() { delete[] data; }

        int get_N() const { return N; }
        int& operator[](int k) { return data[adjust_index(k)]; }
        const int& operator[](int k)const { return data[adjust_index(k)]; }
        SmartArray& operator=(const SmartArray& other);
    };

}

#endif


smart_array.cpp

#include "smart_array.h"

namespace bme {

    int SmartArray::adjust_index(int k) const {
        k %= N;
        if (k < 0) k += N;
        return k;
    }

    SmartArray::SmartArray(const SmartArray& other) {
        N = other.N;
        data = new int[N];
        for (int i = 0; i < N; ++i) {
            data[i] = other.data[i];
        }
    }

    SmartArray::SmartArray(int nels) {
        N = (nels > 1) ? nels : 1;
        data = new int[N];
    }

    SmartArray& SmartArray::operator=(const SmartArray& other) {
        if (this != &other) {
            delete[] data;
            N = other.N;
            data = new int[N];
            for (int i = 0; i < N; ++i) {
                data[i] = other.data[i];
            }
        }
        return *this;
    }

}


4. feladat. Írjunk template swap függvényt, amely paraméterül kap két változó referenciát, melyek típusa (azonos) template paraméter, és megcseréli ezek értékét.

Megoldás:

#include <iostream>
using namespace std;

template<typename T>
void mySwap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 5, y = 10;
    cout << "Csere elott: x = " << x << ", y = " << y << endl;
    mySwap(x, y);
    cout << "Csere utan: x = " << x << ", y = " << y << endl;

    double a = 3.14, b = 2.71;
    cout << "Csere elott: a = " << a << ", b = " << b << endl;
    mySwap(a, b);
    cout << "Csere utan: a = " << a << ", b = " << b << endl;

    return 0;
}



5. feladat. Írjunk template függvényeket, amik visszaadják halmazok unióját, metszetét, különbségét. Használjuk a set osztályt.

Megoldás:

#include <iostream>
#include <set>

using namespace std;

template<typename T>
set<T> set_union_custom(const set<T>& a, const set<T>& b) {
    set<T> result = a;
    for (const T& elem : b) {
        result.insert(elem);
    }
    return result;
}

template<typename T>
set<T> set_intersection_custom(const set<T>& a, const set<T>& b) {
    set<T> result;
    for (const T& elem : a) {
        if (b.find(elem) != b.end()) {
            result.insert(elem);
        }
    }
    return result;
}

template<typename T>
set<T> set_difference_custom(const set<T>& a, const set<T>& b) {
    set<T> result;
    for (const T& elem : a) {
        if (b.find(elem) == b.end()) {
            result.insert(elem);
        }
    }
    return result;
}

int main() {
    set<int> A = { 1, 2, 3, 4 };
    set<int> B = { 3, 4, 5, 6 };

    auto unio = set_union_custom(A, B);
    auto metszet = set_intersection_custom(A, B);
    auto kulonbseg = set_difference_custom(A, B);

    cout << "Unió: ";
    for (int x : unio) cout << x << " ";

    cout << "\nMetszet: ";
    for (int x : metszet) cout << x << " ";

    cout << "\nKülönbség (A - B): ";
    for (int x : kulonbseg) cout << x << " ";

    cout << endl;
    return 0;
}


6. feladat. Írjunk template függvényt, amely paraméterül kap egy x változót, melynek típusa template paraméter, továbbá egy n nemnegatív egész számot, és visszaadja az x+2*x+...+n*x értéket (melynek típusa megegyezik az x típusával).

Megoldás:

template<typename T>
T sum_multiples(T x, int n) {
    T result = x;
    for (int i = 2; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            result += x;
        }
    }
    return result;
}


7. feladat. Írjunk egy VectorND osztályt, amely egy n dimenziós vektort reprezentál, ahol a koordináták típusa, valamint a vektor dimenziója is egy-egy template paraméter. Definiáljuk az összeadást, skalárral való szorzást, valamint a skaláris szorzatot is.

Megoldás:

vectornd.hpp

#ifndef VECTORND_HPP
#define VECTORND_HPP

#include <iostream>

using namespace std;

template<typename T, size_t N>
class VectorND {
private:
    T data[N];

public:
    VectorND() {
        for (size_t i = 0; i < N; ++i) {
            data[i] = T(0);
        }
    }

    // init egy REFERENCIA egy N elemű T típusú elemeket tartalmazó tömb elejére
    // pointer átadása nem biztonságos!
    VectorND(const T(&init)[N]) {
        for (size_t i = 0; i < N; ++i) {
            data[i] = init[i];
        }
    }

    T& operator[](size_t index) {
        return data[index];
    }

    const T& operator[](size_t index) const {
        return data[index];
    }

    VectorND<T, N> operator+(const VectorND<T, N>& other) const {
        VectorND<T, N> result;
        for (size_t i = 0; i < N; ++i) {
            result[i] = data[i] + other[i];
        }
        return result;
    }

    VectorND<T, N> operator*(const T& scalar) const {
        VectorND<T, N> result;
        for (size_t i = 0; i < N; ++i) {
            result[i] = data[i] * scalar;
        }
        return result;
    }

    T dot(const VectorND<T, N>& other) const {
        T result = T(0);
        for (size_t i = 0; i < N; ++i) {
            result += data[i] * other[i];
        }
        return result;
    }

};

template<typename T, size_t N>
ostream& operator<<(ostream& os, const VectorND<T, N>& vec) {
    os << "(";
    for (size_t i = 0; i < N; ++i) {
        os << vec[i];
        if (i != N - 1) os << ", ";
    }
    os << ")";
    return os;
}

#endif


8. feladat. Írjunk egy Matrix osztályt, amely mátrixokat reprezentál, és melynek elemtípusa, valamint a sor- és oszlopszáma is egy-egy template paraméter. Definiáljuk az összeadást, skalárral való szorzást és a mátrixszorzást is.

Megoldás:

matrix.hpp

#ifndef MATRIX_HPP
#define MATRIX_HPP

#include <iostream>
#include <vector>
using namespace std;

template<typename T, size_t Rows, size_t Cols>
class Matrix {
private:
    vector<vector<T>> data;

public:
    // Default konstruktor: minden elem 0
    Matrix() {
        for (size_t i = 0; i < Rows; ++i) {
            vector<T> row(Cols, T(0)); // Egy sor létrehozása 0 értékekkel
            data.push_back(row);
        }
    }

    // a paraméter referencia egy két dimenziós tömb elejére
    // pointer biztonságosan nem adható át!
    Matrix(const T(&init)[Rows][Cols]) {
        for (size_t i = 0; i < Rows; ++i) {
            vector<T> row;
            for (size_t j = 0; j < Cols; ++j) {
                row.push_back(init[i][j]);
            }
            data.push_back(row);
        }
    }

    T& operator()(size_t i, size_t j) {
        return data[i][j];
    }

    const T& operator()(size_t i, size_t j) const {
        return data[i][j];
    }

    Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols>& other) const {
        Matrix<T, Rows, Cols> result;
        for (size_t i = 0; i < Rows; ++i) {
            for (size_t j = 0; j < Cols; ++j) {
                result(i, j) = data[i][j] + other(i, j);
            }
        }
        return result;
    }

    // Skalárral szorzás
    Matrix<T, Rows, Cols> operator*(const T& scalar) const {
        Matrix<T, Rows, Cols> result;
        for (size_t i = 0; i < Rows; ++i) {
            for (size_t j = 0; j < Cols; ++j) {
                result(i, j) = data[i][j] * scalar;
            }
        }
        return result;
    }

    // Mátrixszorzás (ha a méretek passzolnak)
    template<size_t OtherCols>
    Matrix<T, Rows, Cols> operator*(const Matrix<T, Cols, OtherCols>& other) const {
        Matrix<T, Rows, OtherCols> result;
        for (size_t i = 0; i < Rows; ++i) {
            for (size_t j = 0; j < OtherCols; ++j) {
                T sum = T(0);
                for (size_t k = 0; k < Cols; ++k) {
                    sum += data[i][k] * other(k, j);
                }
                result(i, j) = sum;
            }
        }
        return result;
    }

};

template<typename T, size_t Rows, size_t Cols>
ostream& operator<<(ostream& os, const Matrix<T, Rows, Cols>& mat) {
    for (size_t i = 0; i < Rows; ++i) {
        for (size_t j = 0; j < Cols; ++j) {
            os << mat(i, j) << " ";
        }
        os << endl;
    }
    return os;
}

#endif


main.cpp

#include "matrix.hpp"
#include<iostream>

using namespace std;

int main() {
    // Mátrix inicializálása 2D tömbbel
    double initA[2][2] = { {1.0, 2.0}, {3.0, 4.0} };
    double initB[2][2] = { {5.0, 6.0}, {7.0, 8.0} };

    Matrix<double, 2, 2> A(initA);
    Matrix<double, 2, 2> B(initB);

    auto C = A + B;
    auto D = A * 2.0;
    auto E = A * B;

    cout << "A + B:\n" << C << endl;
    cout << "A * 2:\n" << D << endl;
    cout << "A * B:\n" << E << endl;

    return 0;
}