Best way to evaluate a matrix-based polynomial in C++ - c++

all. I'm trying to set up a program that evaluates a polynomial depending on the user input of X. Another part of the program I want is to then add these polynomials together. I'm using a 2D array to do this. What do you think would be the best way to write the evaluation function. Been working at this for hours and I'm still not quite sure how to do it. Thanks in advance.
polynomial.h
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
using namespace std;
#define MAX 100
class Polynomial {
friend ostream &operator<< (ostream &, const Polynomial &);
public :
Polynomial ();
void enterTerms();
int evaluate(Polynomial p, int x);
Polynomial operator +(const Polynomial & );
private :
int terms[MAX][2]; //either static size(MAX rows) or use "new" for dynamic allocation
int n; //number of terms
};
#endif
polynomial.cpp
#include "polynomial.h"
using namespace std;
ostream &operator<< (ostream & out, const Polynomial & p){
for ( int i = 0 ; i < p.n ; i++ ){
if ( i == p.n - 1 )//last term does not have + appended
out << p.terms[i][0] <<"x^"<<p.terms[i][1]<<endl;
else
out << p.terms[i][0]<<"x^"<<p.terms[i][1]<<" + ";
}
return out;
}
Polynomial :: Polynomial(){
for ( int i = 0; i < MAX; i++ ){
terms[i][0] = 0;
terms[i][1] = 0;
}
}
void Polynomial :: enterTerms(){//enterTerms() not in constructor so that no prompt for entering
//terms while doing + - etc., they also produce Poylnomial instance (i.e. invoke constructor)
int num;
cout<<"enter number of terms in polynomial\n";
cin >> num;
n = num >= 0 ? num : 1;
cout << "enter coefficient followed by exponent for each term in polynomial\n";
for ( int i = 0; i < n ; i++)
cin >> terms[i][0] >> terms[i][1] ;
}
Polynomial Polynomial :: operator + ( const Polynomial & p ){
Polynomial temp, sum;
temp.n = n + p.n;
int common = 0;
// first write sum as concatenation of p1 and p2
for ( int i = 0 ; i < n ; i++ ){
temp.terms[i][0] = terms[i][0];
temp.terms[i][1] = terms[i][1];
}
//notice j and k for traversing second half of sum, and whole p2 resp
for ( int j = n, k = 0; j < n + p.n, k < p.n ; j++, k++ ){
temp.terms[j][0] = p.terms[k][0];
temp.terms[j][1] = p.terms[k][1];
}
for ( int l = 0; l < temp.n - 1 ; l++ ){ // 0 to 1 less than length
for ( int m = l + 1 ; m < temp.n ; m++ ){ // 1 more than l to length,so that compared pairs are non redundant
if( temp.terms[l][1] == temp.terms[m][1] ){
common++; //common terms reduce no. of terms in sum (see sum.n decl)
temp.terms[l][0] += temp.terms[m][0]; //coefficients added if exponents same
temp.terms[m][0] = 0;
}
}
}
sum.n = temp.n - common; //if you place it above, common taken as 0 and sum.n is same as temp.n (logical error)
//just to debug, print temporary array
cout << endl << temp;
for ( int q = 0, r = 0; q < temp.n; q++ ){
if ( temp.terms[q][0] == 0 )
continue;
else{
sum.terms[r][0] = temp.terms[q][0];
sum.terms[r][1] = temp.terms[q][1];
r++;
}
}
cout << endl << sum;
return sum;
}
int Polynomial :: evaluate(Polynomial p, int x)
{
Polynomial terms;
return 0;
}
int main()
{
Polynomial p1 , p2;
p1.enterTerms();
p2.enterTerms();
cout << "Please enter the value of x:" << endl;
cin >> x;
//evaluate(p1);
//evaluate(p2);
p1 + p2;
system("PAUSE");
//cin.get();
return 1;
}

Please consider a simpler data structure. A common approach is to use a single array, where the index is the power of x. Just use zeros where no such term exists. Then x^3 + 2*x + 1 is written {1, 2, 0, 1}, since there's no x^2. Also note the reverse order, since p[0] represents x^0. This drastically simplifies operations like addition.
As far as evaluation, just think about the equation. If your polynomial is x^2 + 3*x + 5, and you want to evaluate for x=7, what do you do? Start with power 0, and accumulate each term into a single variable.

You can follow and complete my functions here:
float polyval_point(Eigen::VectorXf v,float x)
{
float s = 0;
for (int i=0;i<v.size();i++)
{
s += v[i] * pow(x,i);
}
return s;
}
Eigen::VectorXf polyval_vector(Eigen::VectorXf v,Eigen::VectorXf X)
{
Eigen::VectorXf S(X.size());
for (int i=0;i<X.size();i++)
{
S[i] = polyval_point(v,X[i]);
}
return S;
}

Related

What's wrong in this code , it's doing nothing other than taking inputs of n and m

Here in this question the function call is not executing also tell me abut can't I use array instead of vectors here.
if Possible to use array please provide me with code that how to pass arrays to a function in c++
Here in this question the function call is not executing also tell me abut can't I use array instead of vectors here.
if Possible to use array please provide me with code that how to pass arrays to a function in c++
#include <iostream>
#include <vector>
using namespace std;
int recursion(vector<vector<int>> &v, int n, int m)
{
if (n == 0 && m == 0)
{
return v[n][m];
}
int left = v[n][m] + recursion(v, n - 1, m);
int right = v[n][m] + recursion(v, n, m - 1);
return min(left, right);
}
int main()
{
int n, m;
cout << "enter the value of n and m" << endl;
cin >> n >> m;
cout << n << m;
//it's doing nothing after this point.
vector<vector<int>> vec(n, vector<int>(m));
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= m; j++)
{
vec[i][j] = (i)*m + (j + 1);
}
}
int result = recursion(vec, n, m);
cout << result;
return 0;
}
vec[i][j] = (i)*m + (j + 1);
is out-of-bounds for i = n and j = m. Same problem with calling recursion(vec, n, m);

How to declare arrays which are functions argument, if their size is to be determined by the user input at the start of program

For my "basics of programming" project i was ordered to make a "memory game". 2 players in their respective turns choose which cards to reveal on a "m x n" sized board. "m" and "n" are to be chosen at the start of each game. My question is, how can I create an array of structures used to display the board a the moment of user's input. So far I just used a const int to create an array of a maximum size, however more than 95% of the arrays indexes are empty using this method. Is there a way to create the array right after user's input while also having those functions defined and declared with an array of structures that's the size of the input? Here's my code so far:
const int MAX_M = 1000;
const int MAX_N = 1000;
Karta Plansza2[MAX_M][MAX_N];
void SprawdzanieParzystosci(int& m, int& n);
void RozmiaryTablicy(int& m, int& n);
void generuj(int m, int n, Karta Plansza[MAX_M][MAX_N]);
void WyswietleniePlanszy(int m, int n, Karta Plansza[MAX_M][MAX_N]);
void generuj(int m, int n, Karta Plansza[][MAX_N])
{
srand((unsigned int)time(NULL));
char A;
int B;
int C;
int D;
int k = 0;
int w1, w2, k1, k2;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
Plansza[i][j].WartoscKarty = 0;
}
while (k < (m*n))
{
A = char(rand() % 10 + 65);
B = (rand() % 10);
C = (rand() % 10);
D = ((rand() % 2000000) + 1);
do{
w1 = rand() % m;
k1 = rand() % n;
}while(Plansza[w1][k1].WartoscKarty != 0);
Plansza[w1][k1].ZnakPierwszy = A;
Plansza[w1][k1].LiczbaPierwsza = B;
Plansza[w1][k1].LiczbaDruga = C;
Plansza[w1][k1].WartoscKarty = D;
k++;
do{
w2 = rand() % m;
k2 = rand() % n;
} while (Plansza[w2][k2].WartoscKarty != 0);
Plansza[w2][k2].ZnakPierwszy = A;
Plansza[w2][k2].LiczbaPierwsza = B;
Plansza[w2][k2].LiczbaDruga = C;
Plansza[w2][k2].WartoscKarty = D;
k++;
}
}
/////////////////////////////////////////////////////
void WyswietleniePlanszy(int m, int n, Karta Plansza[MAX_M][MAX_N])
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << "***" << setw(5);
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].ZnakPierwszy << "*" << " ";
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].LiczbaPierwsza << "*" << " ";
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].LiczbaDruga << "*" << " ";
cout << "\n";
// for(int j = 0; j < 10; j++)
// cout << wzor[i][j].num4 << " ";
for (int j = 0; j < n; j++)
cout << "***" << setw(5);
cout << "\n";
cout << endl;
}
}
/////////////////////////////////////////////////////
void RozmiaryTablicy(int& m, int& n)
{
cout << "Podaj rozmiar m tablicy: ";
cin >> m;
cout << "Podaj rozmiar n tablicy: ";
cin >> n;
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
void SprawdzanieParzystosci(int& m, int& n)
{
while ((m * n) % 2 != 0 || (m <= 0) || (n <= 0)) {
RozmiaryTablicy(m, n);
if((m * n) % 2 != 0 || (m <= 0) || (n <= 0)) cout << "Zle dane. Prosze podac dane jeszcze raz" << endl;
}
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
int main()
{
int m =1;
int n =1;
SprawdzanieParzystosci(m, n);
generuj(m,n,Plansza2);
WyswietleniePlanszy(m,n,Plansza2);
cout << m << endl;
cout << n << endl;
system("pause");
return 0;
}
For example, If the user inputs m = 5 an n = 6 it would create an Plansza[5][6] array instead of a Plansza[1000][1000] array
Quick hack of a board, remark the nice board[row][column] notation and the returned reference to the field. C++17 (might work in C++14)
#include <iostream>
#include <memory>
#include <cstring>
using DaType = char;
class Board {
int rows = 0;
int cols = 0;
std::unique_ptr<DaType[]> board; // RAII
public:
class Row {
DaType *board;
public:
Row(DaType *row) : board(row) {}
DaType& operator[](int col) { return board[col]; }
};
Board(int row, int col) : rows(row), cols(col), board(std::make_unique<DaType[]>(row*col)) { memset(board.get(), '.', rows*cols); }
Row operator[](int row) { return Row(board.get()+row*cols); }
};
int main() {
const int sx = 6, sy = 10;
Board board(sx,sy);
board[3][5] = 'x';
for (int i = 0; i < sx; ++i ) {
for (int j = 0; j < sy; ++j )
std::cout << board[i][j];
std::cout << '\n';
}
}
Ps. it seemed simpler last time I did this ...
Update thanks to IlCapitano
class Board {
int rows = 0;
int cols = 0;
std::unique_ptr<DaType[]> board; // RAII
public:
Board(int row, int col) : rows(row), cols(col), board(std::make_unique<DaType[]>(row*col)) { memset(board.get(), '.', rows*cols); }
DaType *operator[](int row) { return board.get()+row*cols; }
};
The easiest way to solve this would be to just use std::vector, since the size of arrays in arguments, stackallocations, etc. has to be known at compile-time.
The easiest option without using vector would be to declare Plansza2 as a Karta* and allocate the memory dynamically after SprawdzanieParzystosci using Plansza2 = new Karta[m*n]; (Don't forget to call delete[](Plansza2); before ending your program). If you do this you can access the cells with Plansza2[y * m + x] (assuming m is width and n is height). The advantage of mapping the 2-dimensional array to a 1 dimensional array by placing all rows after one another is that you only need one allocation and one deletion, and furthermore it improves cache-friendliness.
A cleaner way to solve this (removing the possibility for a memory leak if something throws an exception or you forget to call delete) would be to create your own class for 2-dimensional arrays, that would call new[] in the constructor and delete[] in the destructor. If you do that you could define Karta& operator()(int x, int y); and const Karta& operator()(int x, int y) const; to return the appropriate cell, allowing you to access a cell with dynamicMap(x, y). operator[] can only take one argument and is therefor more complicated to use to access a 2-dimensional array (you can for example take an std::pair as the argument or return a proxy-class that also has operator[] defined). However if you write your own destructor, you need to take care of the copy-(always) and move-(c++11 onwards) constructors and assignment operators, since the default instantiations would lead to your destructor trying to delete the same pointer multiple times. An example for a move-assignment operator is:
DynamicMap& DynamicMap::operator=( DynamicMap&& map ){
if(this == &map)
return *this; //Don't do anything if both maps are the same map
dataPointer = map.dataPointer; //Copy the pointer to "this"
map.dataPointer = nullptr; //Assign nullptr to map.dataPointer because delete[] does nothing if called with null as an argument
//You can move other members in the above fashion, using std::move for types more complex than a pointer or integral, but be careful to leave map in a valid, but empty state, so that you do not try to free the same resource twice.
return *this;
}
The move constructor doesn't require the if-clause at the start, but is otherwise identical and the copy-constructor/assignment operator should probably declared as = delete; since it will probably be a bug if you copy your map. If you do need to define the copy operations, do not copy the pointer but instead create a new array and copy the contents.

How to select all possible combination of elements from a set using recursion

This is a question from hackerrank; I am trying to understand how recursion works.
The task at hand is:
Find the number of ways that a given integer, X, can be expressed
as the sum of the Nth power of unique, natural numbers.
So for example, if X = 100 and N = 2
100 = 10² = 6² + 8² = 1² + 3² + 4² + 5² + 7²
so 100 can be expressed as the square of unique natural numbers in 3
different ways, so our output is 3.
Here is my code,:
#include <cmath>
#include <iostream>
using namespace std;
int numOfSums(int x, int& n, const int k) {
int count = 0, j;
for (int i = (k + 1); (j = (int) pow(i, n)) <= x; i++) {
j = x - j;
if (j == 0)
count++;
else
count += numOfSums(j, n, i);
}
return count;
}
int main() {
int x, n;
cin >> x >> n;
cout << numOfSums(x, n, 0) << endl;
return 0;
}
But when I input x = 100 and n = 2, it's outputting 2, not 3. What's wrong with the code?
Link to the question: https://www.hackerrank.com/challenges/the-power-sum
Your example code returns 3 when I run it using this main():
#include <iostream>
int main() {
int x = 100, n = 2;
cout << numOfSums(x, n, 0) << endl;
return 0;
}
The problem is likely that you're using double std::pow(double, int), but you're not rounding the result to nearest integer ((int) casts round down). You should add ½ before truncating:
j = static_cast<int>(pow(i, n) + 0.5)
I've used the more-C++ style of cast, which I find clearer.
It would be more efficient to implement your own equivalent of std::pow() that operates on integers. That can be recursive, too, if you want:
unsigned long pow(unsigned long x, unsigned long n)
{
return n ? x * pow(x, n-1) : 1;
}
An iterative version is more efficient (or a tail-recursive version and suitable optimizing compiler).
Reduced version, with my changes:
template<typename T>
T powi(T x, T n)
{
T r{1};
for (; n; n /= 2) {
r *= n%2 ? x : 1;
x *= x;
}
return r;
}
template<typename T>
T numOfSums(T x, T n, T i = {})
{
T count{}, j;
for (++i; (j = powi(i, n)) <= x; ++i)
count += j == x ? 1 : numOfSums(x-j, n, i);
return count;
}
#include <iostream>
int main()
{
unsigned long int x = 100, n = 2;
std::cout << numOfSums(x, n) << std::endl;
return 0;
}

Stack around the variable ' ' is corrupted , c++ issue

I got a little problem about this program i am making ,
The main purpose of this program I am making is to get 2 polynomial and sum / sub / multiply it ,
Didn't finished the output and main() parts yet, just on the code itself,
When I try to use the multiply part,
I get this error : stack around the variable 'a' is corrupted ,
Dunno what I did wrong .... took me 1 hours to think of this way and write this , but just 2 hours trying to fix this but can't get anywhere.
class PolyNomial
{
int printcounter;
double *coefficients;
int degree;
public:
PolyNomial()//the default constructor to initialize a polynomial equal to 0
{
degree = 0;
coefficients = new double[degree + 1];
coefficients[0] = 0;
}
PolyNomial(double y[], int x)//the constructor to initialize a polynomial with the given coefficient array and degree
{
degree = x;
if (degree>10)
{
cout<<"Error : The PolyNomial's Degree is bigger than 10 and can not be shown in this program";
}
else
{
int c=0;
coefficients = new double[degree + 1];
for(c=0;c<=degree;c++)
{
coefficients[c] = y[c];
}
}
}
void add(PolyNomial p)
{
int i;
if ( degree < p.degree )
{
i = p.degree;
printcounter = p.degree;
}
else
{
i = degree;
printcounter = degree;
}
for(;i>=0;i--)
{
coefficients[i] = coefficients[i] + p.coefficients[i];
}
}
void sub(PolyNomial p)
{
int i;
if ( degree < p.degree )
{
i = p.degree;
printcounter = p.degree;
}
else
{
i = degree;
printcounter = degree;
}
for(;i>=0;i--)
{
coefficients[i] = coefficients[i] - p.coefficients[i];
}
}
void print()
{
int i;
for(i=0;i<=printcounter;i++)
cout<<coefficients[i]<<" ";
}
void Multiply(PolyNomial p)
{
int i,j;
i = degree;
j = p.degree;
double a[100];
int counter;
for ( counter = 0 ; counter <= i+j; counter++)
{
a[counter]=0;
}
int x= i+ j ;
for(;i>=0;i--)
{
for(;j>=0;j--)
if (i+j>=10)
{
cout<<"Error : The PolyNomial's Degree is bigger than 10 and can not be shown in this program";
break;
}
a[i+j] = a[i+j] + ( coefficients[i] * p.coefficients[j] );
}
PolyNomial k(coefficients,x);
k.print();
}
};
int main()
{
double a[100];
int x,i;
cout<<"Enter the PolyNomial's Degree : ";
cin>>x;
cout<<"\nEnter the coefficients one by one by , from bigger to smaller : ";
for ( i=0 ; i<=x ; i++ )
{
cin>>a[i];
}
PolyNomial p(a,x);
cout<<"\n\nEnter the PolyNomial's Degree : ";
cin>>x;
cout<<"\nEnter the coefficients one by one by , from lowest degree to highest : ";
for ( i=0 ; i<=x ; i++ )
{
cin>>a[i];
}
PolyNomial o(a,x);
_getch();
// p.add(o);
p.Multiply(o);
// p.print();
_getch();
// p.sub(o);
// p.Multiply(o);
}
This line
a[i+j] = a[i+j] + ( coefficients[i] * p.coefficients[j] );
is not inside the for j loop (you haven't used { and } to enclose it}. This means that j is -1 when it gets run. If i is 0 you are assigning to a[-1] which causes the stack corruption message.
Note that you also aren't resetting j each time round the i loop, so the inner loop will only execute once.
In C and C++ local variables are generally stored on the stack, a small(ish) area of memory that programs use to store local/function level data; when an executable calls a function, the processor uses the stack to store the address that the call is being made from, and then branches to the subroutine. When the subroutine finishes, if it has cleaned up it's stack, then it should be back to a state where the top value of the stack is the address it needs to jump back to in order to resume processing.
At the same time, C/C++ programs use the stack to store local variables -- the principle being that when you leave a sub-routine all the variables go away very elegantly.
Your variables "a" are local variables, they are on the stack. Since they are arrays, that means that if you write outside the contraints of the array, you will overwrite areas of the stack being used by other variables or possibly even by the CPU for return-address tracking.
Your variables "a" have 100 elements. This array forms a single, contiguous block:
{a[0]}{a[1]}...{a[99]}
If you write to 'a[100]' you are writing past the end of the array and over some other variable's memory, or possibly the return address of a function.
You might want to consider using a [std::array][1] or a [std::vector][2].
At the time you create your polynomial, you create a coefficients array with the size of degree + 1. So far so good. Now if you add two polynomials, you simply add the coefficients but disregard the allocated space. If the polynomial with the lowest degree should be the result of the addition, you'll get in trouble
Well for now tnx to all the answers and comments i got my code working but it dose not do the job correctly,
Example : if I add a 2 degree polynomial first then a 3 degree like this :
1 2 3
1 2 3 4
The result will be :
0 0 3 6 9 12
Which is only one part of the multiply processes,
The 2 polynomial I added are :
3x^2 + 2x^1 + 1
4x^3 + 3x^2 + 2x^1 + 1
Here is the new code :
class PolyNomial
{
int printcounter;
double *coefficients;
int degree;
public:
PolyNomial()//the default constructor to initialize a polynomial equal to 0
{
degree = 0;
coefficients = new double[degree + 1];
coefficients[0] = 0;
}
PolyNomial(double y[], int x)//the constructor to initialize a polynomial with the given coefficient array and degree
{
degree = x;
if (degree>10)
{
cout<<"Error : The PolyNomial's Degree is bigger than 10 and can not be shown in this program";
}
else
{
int c=0;
coefficients = new double[degree + 1];
for(c=0;c<=degree;c++)
{
coefficients[c] = y[c];
}
}
}
void add(PolyNomial p)
{
int i;
if ( degree < p.degree )
{
i = p.degree;
printcounter = p.degree;
}
else
{
i = degree;
printcounter = degree;
}
for(;i>=0;i--)
{
coefficients[i] = coefficients[i] + p.coefficients[i];
}
}
void sub(PolyNomial p)
{
int i;
if ( degree < p.degree )
{
i = p.degree;
printcounter = p.degree;
}
else
{
i = degree;
printcounter = degree;
}
for(;i>=0;i--)
{
coefficients[i] = coefficients[i] - p.coefficients[i];
}
}
void print()
{
int i;
for(i=0;i<=printcounter;i++)
cout<<coefficients[i]<<" ";
}
void Multiply(PolyNomial p)
{
int i,j;
i = degree;
j = p.degree;
double mult[100];
int counter;
for ( counter = 0 ; counter <= i+j; counter++)
{
mult[counter]=0;
}
int x= i+ j ;
for(;i>=0;i--)
{
for(;j>=0;j--)
{
if (i+j>=10)
{
cout<<"Error : The PolyNomial's Degree is bigger than 10 and can not be shown in this program";
break;
}
mult[i+j] = mult[i+j] + ( coefficients[i] * p.coefficients[j] );
}
}
PolyNomial k(mult,x);
k.printcounter = x;
k.print();
}
};
int main()
{
double a[100];
int x,i;
cout<<"Enter the PolyNomial's Degree : ";
cin>>x;
cout<<"\nEnter the coefficients one by one by , from lowesr degree to highest : ";
for ( i=0 ; i<=x ; i++ )
{
cin>>a[i];
}
PolyNomial p(a,x);
cout<<"\n\nEnter the PolyNomial's Degree : ";
cin>>x;
cout<<"\nEnter the coefficients one by one by , from lowest degree to highest : ";
for ( i=0 ; i<=x ; i++ )
{
cin>>a[i];
}
PolyNomial o(a,x);
_getch();
// p.add(o);
p.Multiply(o);
// p.print();
_getch();
// p.sub(o);
// p.Multiply(o);
}

C++ strange class declaration

I'm practicing ACM problems to become a better programmer, but I'm still fairly new to c++ and I'm having trouble interpreting some of the judges code I'm reading. The beginning of a class starts with
public:
State(int n) : _n(n), _p(2*n+1)
{
and then later it's initialized with
State s(n);
s(0,0) = 1;
I'm trying to read the code but I can't make sense of that. The State class only seems to have 1 argument passed, but the programmer is passing 2 in his initialization. Also, what exactly is being set = to 1? As far as I can tell, the = operator isn't being overloaded but just in case I missed something I've included the full code below.
Any help would be greatly appreciated.
Thanks in advance
/*
* D - Maximum Random Walk solution
* ICPC 2012 Greater NY Regional
* Solution by Adam Florence
* Problem by Adam Florence
*/
#include <cstdio> // for printf
#include <cstdlib> // for exit
#include <algorithm> // for max
#include <iostream>
#include <vector>
using namespace std;
class State
{
public:
State(int n) : _n(n), _p(2*n+1)
{
if (n < 1)
{
cout << "Ctor error, n = " << n << endl;
exit(1);
}
for (int i = -n; i <= n; ++i)
_p.at(i+_n) = vector<double>(n+1, 0.0);
}
void zero(const int n)
{
for (int i = -n; i < n; ++i)
for (int m = 0; m <= n; ++m)
_p[i+_n][m] = 0;
}
double operator()(int i, int m) const
{
#ifdef DEBUG
if ((i < -_n) || (i > _n))
{
cout << "Out of range error, i = " << i << ", n = " << _n << endl;
exit(1);
}
if ((m < 0) || (m > _n))
{
cout << "Out of range error, m = " << m << ", n = " << _n << endl;
exit(1);
}
#endif
return _p[i+_n][m];
}
double& operator()(int i, int m)
{
#ifdef DEBUG
if ((i < -_n) || (i > _n))
{
cout << "Out of range error, i = " << i << ", n = " << _n << endl;
exit(1);
}
if ((m < 0) || (m > _n))
{
cout << "Out of range error, m = " << m << ", n = " << _n << endl;
exit(1);
}
#endif
return _p[i+_n][m];
}
static int min(int x, int y)
{
return(x < y ? x : y);
}
static int max(int x, int y)
{
return(x > y ? x : y);
}
private:
int _n;
// First index is the current position, from -n to n.
// Second index is the maximum position so far, from 0 to n.
// Value is probability.
vector< vector<double> > _p;
};
void go(int ds)
{
// Read n, l, r
int n, nds;
double l, r;
cin >> nds >> n >> l >> r;
const double c = 1 - l - r;
if(nds != ds){
cout << "Dataset number " << nds << " does not match " << ds << endl;
return;
}
// Initialize state, probability 1 at (0,0)
State s(n);
s(0,0) = 1;
State t(n);
State* p1 = &s;
State* p2 = &t;
for (int k = 1; k <= n; ++k)
{
// Compute probabilities at step k
p2->zero(k);
// At step k, the farthest from the origin you can be is k
for (int i = -k; i <= k; ++i)
{
const int mm = State::min( State::max(0, i+k), k);
for (int m = 0; m <= mm; ++m)
{
// At step k-1, p = probability of (i,m)
const double p = p1->operator()(i,m);
if (p > 0)
{
// Step left
p2->operator()(i-1, m) += p*l;
// Step right
p2->operator()(i+1, State::max(i+1,m)) += p*r;
// Stay put
p2->operator()(i, m) += p*c;
}
}
}
swap(p1, p2);
}
// Compute expected maximum position
double p = 0;
for (int i = -n; i <= n; ++i)
for (int m = 0; m <= n; ++m)
p += m * p1->operator()(i,m);
printf("%d %0.4f\n", ds, p);
}
int main(int argc, char* argv[])
{
// Read number of data sets to process
int num;
cin >> num;
// Process each data set identically
for (int i = 1; i <= num; ++i)
go(i);
// We're done
return 0;
}
You are confusing a call to state::operator()(int, int) with an initialization. That operator call lets you set the value of an element of the class instance.
State s(n); // this is the only initialization
s(0,0) = 1; // this calls operator()(int, int) on instance s
In this line:
s(0,0) = 1;
it's calling this:
double& operator()(int i, int m)
and because it returns a reference to a double, you can assign to it.
The second line is no longer initialization. The constructor was invoked in line 1, the second line invokes
double& operator()(int i, int m)
with n=0 and m=0 and writing 1 to the reference that is returned.
This part:
State(int n) : _n(n), _p(2*n+1)
...is a member initializer list. It's sort of similar to if you'd written the construct like:
state(int n) { _n = n; _p = 2*n+1; }
...except that it initializes _n and _p instead of starting with them unitialized, then assigning values to them. In this specific case that may not make much difference, but when you have things like references that can only be initialized (not assigned) it becomes crucial.
The s(0,0) = 1 looks like s is intended to act a little like a 2D array, and they've overloaded operator() to act as a subscripting operator for that array. I posted a class that does that in a previous answer.