#include <sstream>
#include <cmath>
#include <memory>
#include <list>
#include <string>
#include <map>
#include <functional>
#include <iostream>

using namespace std;

class PDF {
  public:
    virtual double getMean() const = 0;
    virtual ~PDF() = default;
};

class NormV : public PDF {
  public:
    double mean, stddev;
    NormV (double mean_ = 0, double stddev_ = 1)
      : mean(mean_), stddev(stddev_) {}
    virtual double operator()(double x) const {
      return M_2_SQRTPI / (2 * M_SQRT2 * stddev) * exp(-((x - mean) * (x - mean)) / (2*stddev*stddev));
    }
    double getMean() const {
      return mean;
    }
};
class GleichV : public PDF {
  private:
    double from, to;

  public:
    GleichV(double from_, double to_): from(from_), to(to_) {
      if (to <= from) {
        ostringstream sstr;
        sstr << "NormV(" << from << ", " << to << ")";
        throw invalid_argument(sstr.str());
      }
    }
    virtual double operator()(double x) const {
      if (x < from || x > to)
        return 0;
      return 1 / (to - from);
    }
    double getMean() const {
      return from + (to - from) / 2;
    }
};
class ExpV : public PDF {
  public:
    double rate;
    ExpV(double rate_): rate(rate_) {}
    virtual double operator()(double x) const {
      if (x < 0)
        return 0;
      return rate * exp(- rate * x);
    }
    double getMean() const {
      return 1 / rate;
    }
};

class SumV : public PDF {
  private:
    list<unique_ptr<PDF>> pdfs;

  public:
    explicit SumV(PDF* pdf) { *this += pdf; }
    SumV(const SumV&) = delete;

    SumV& operator+=(PDF* pdf) {
      pdfs.push_back(unique_ptr<PDF>{pdf});
      return *this;
    }

    double getMean() const {
      double sum = 0;
      for (const unique_ptr<PDF>& pdf: pdfs)
        sum += pdf->getMean();
      return sum;
    }
};

const map<string, function<PDF*()>> pdfs{
  {"norm", []() -> PDF* {
      double mean, stddev;
      cout << "mean, stddev = ";
      cin >> mean >> stddev;
      return new NormV{mean, stddev};
    }
  },
  {"gleich", []() -> PDF* {
      double from, to;
      cout << "from, to = ";
      cin >> from >> to;
      return new GleichV{from, to};
    }
  },
  {"exp", []() -> PDF* {
      double rate;
      cout << "rate = ";
      cin >> rate;
      return new ExpV{rate};
    }
  }
};

int main() {
  unique_ptr<SumV> sum;
  while (true) {
    string fun;
    cout << "sum += ";
    if (!(cin >> fun)) {
      cout << endl;
      break;
    }

    try {
      PDF* pdf = (pdfs.at(fun))();
      if (sum)
        *sum += pdf;
      else
        sum = unique_ptr<SumV>{new SumV{pdf}};
    } catch (const out_of_range&) {
      cout << "Unknown distribution: " << fun << endl;
    }
  }

  cout << "sum.getMean() = " << sum->getMean() << endl;
}
