#include<bits/stdc++.h>
using namespace std;

int main() {
    string filename = "data.txt";
    ifstream infile(filename);
    if (!infile) {
        cerr << "Error opening file: " << filename << endl;
        return 1;
    }

    int numFeatures = 0;
    vector<vector<double>> X;
    vector<double> T;

    string line;
    while (getline(infile, line)) {
        stringstream ss(line);
        vector<double> features;
        double val;
        while (ss >> val) {
            features.push_back(val);
        }
        // Last element is target
        double target = features.back();
        features.pop_back();
        X.push_back(features);
        T.push_back(target);

        numFeatures = features.size();
    }

    int nSamples = X.size();
    double learningRate = 0.01;
    int epochs = 100;

    // Initialize weights and bias
    vector<double> weights(numFeatures, 0.0);
    double bias = 0.0;

    // Training
    for (int epoch = 0; epoch < epochs; epoch++) {
        double totalError = 0;
        for (int i = 0; i < nSamples; i++) {
            double net = bias;
            for (int j = 0; j < numFeatures; j++) {
                net += weights[j] * X[i][j];
            }
            double output = net; // Adaline uses linear output
            double error = T[i] - output;
            totalError += error * error;

            for (int j = 0; j < numFeatures; j++) {
                weights[j] += learningRate * error * X[i][j];
            }
            bias += learningRate * error;
        }
        cout << "Epoch " << epoch + 1 << " - MSE: " << totalError / nSamples << endl;
    }

    cout << "\nFinal weights: ";
    for (auto w : weights) cout << w << " ";
    cout << "\nFinal bias: " << bias << endl;

    // Prediction
    cout << "\nPredictions:\n";
    for (int i = 0; i < nSamples; i++) {
        double net = bias;
        for (int j = 0; j < numFeatures; j++) {
            net += weights[j] * X[i][j];
        }
        cout << "Sample " << i + 1 << ": " << net << " (target: " << T[i] << ")" << endl;
    }

    return 0;
}

