Is there a reason this is wrong? - c++

#include <iostream>
#include <bits/stdc++.h>
#include <numeric>
using namespace std;
int
gcd (int a, int b)
{
if (a == 0)
return b;
return gcd (b % a, a);
}
int
phi (unsigned int n)
{
unsigned int result = 1;
for (int i = 2; i < n; i++)
if (gcd (i, n) == 1)
result++;
return result;
}
int
gen_priv_n (int p1, int p2)
{
int n = phi (p1) * phi (p2);
return n;
}
int
gen_pub_n (int p1, int p2)
{
int n = (p1 * p2);
return n;
}
int
gen_priv_key (int n, int e)
{
int x = (phi (e) * n + 1) / e;
return x;
}
int
encrypt (int n, int e, int data)
{
int crypt_data = int (pow (data, e)) % n;
return crypt_data;
}
int
decrypt (int c, int d, int n)
{
int data = int (pow (c, d)) % n;
return data;
}
int
main ()
{
int ph1 = 53;
int ph2 = 59;
int e = 3;
int message = 89;
int pub_n = gen_pub_n (ph1, ph2);
cout << "PUBN " << pub_n << "\n";
int priv_n = gen_priv_n (ph1, ph2);
cout << "PRIVN " << priv_n << "\n";
int d = gen_priv_key (gen_priv_n (ph1, ph2), e);
cout << "PRIVKEY " << d << "\n";
int c = encrypt (pub_n, e, message);
cout << "ENCRYPTED " << c << "\n";
int data = decrypt (c, d, pub_n);
cout << "MESSAGE " << data;
}
The PUBN, PRIVN, PRIVKEY, and ENCRYPTED all return the expected numbers, however, the decrypt function should return 89(the message variable), but does not. I'm assuming an arithmetic error in the codes order of operations but I'm not sure. Can the issue be pointed out?
The results of the variables are:
PUBN 3127
PRIVN 3016
PRIVKEY 2011
ENCRYPTED 1394
MESSAGE -763 <-- unexpected result, should be 89

The decrypt (and encrypt) function is broken in that it (a) is exceeding platform representation of int, and (b) is unnecessarily using pow to do it in the first place.
In your trivial example you should be utilizing a technique called modulo chaining . The crux of this is the following.
(a * b) % n == ((a % n) * (b % n)) % n
In your case, you're performing simple exponentiation. That means, for example a^2 % n would be:
(a * a) % n = ((a % n) * (a % n)) % n
Similarly, a^3 % n is:
(a * a * a) % n = (((a % n) * (a % n)) % n) * (a % n)) % n
Using modulo chaining allows you to compute what would otherwise be very large product computation mod some N, so long as no product term pair exceeds your platform representation (and it doesn't in your case).
A trivial version of integer pow that does this is below:
int int_pow_mod(int c, int d, int n)
{
int res = 1;
// may as well only do this once
c %= n;
// now loop.
for (int i=0; i<d; ++i)
res = (res * c) % n;
return res;
}
Understand, this is no silver bullet. You can easily contrive a c that still produces a product exceeding INT_MAX, but in your case, that won't happen due to your choices of starting material. A general solution will employ this with a big-number library that allows exceeding platform int representation. Regardless, doing that should deliver what you seek, as shown below:
#include <iostream>
using namespace std;
unsigned int gcd(unsigned int a, unsigned int b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
int phi(unsigned int n)
{
unsigned int result = 1;
for (unsigned int i = 2; i < n; i++)
if (gcd(i, n) == 1)
result++;
return result;
}
int gen_priv_n(int p1, int p2)
{
int n = phi(p1) * phi(p2);
return n;
}
int gen_pub_n(int p1, int p2)
{
int n = (p1 * p2);
return n;
}
int gen_priv_key(int n, int e)
{
int x = (phi(e) * n + 1) / e;
return x;
}
int int_pow_mod(int c, int d, int n)
{
int res = 1;
// may as well only do this once
c %= n;
// now loop.
for (int i=0; i<d; ++i)
res = (res * c) % n;
return res;
}
int encrypt(int n, int e, int data)
{
int crypt_data = int_pow_mod(data, e, n);
return crypt_data;
}
int decrypt(int c, int d, int n)
{
int data = int_pow_mod(c, d, n);
return data;
}
int main()
{
int ph1 = 53;
int ph2 = 59;
int e = 3;
int message = 89;
int pub_n = gen_pub_n(ph1, ph2);
cout << "PUBN " << pub_n << "\n";
int priv_n = gen_priv_n(ph1, ph2);
cout << "PRIVN " << priv_n << "\n";
int d = gen_priv_key(gen_priv_n(ph1, ph2), e);
cout << "PRIVKEY " << d << "\n";
int c = encrypt(pub_n, e, message);
cout << "ENCRYPTED " << c << "\n";
int data = decrypt(c, d, pub_n);
cout << "MESSAGE " << data;
}
Output
PUBN 3127
PRIVN 3016
PRIVKEY 2011
ENCRYPTED 1394
MESSAGE 89

Related

Friend Function C++ how to design the function that takes 2 class objects as the argument

I find difficulties in this part because it takes the class objects as the parameter of the function:
friend Num_Fact GCD(Num_Fact , Num_Fact);
friend Num_Fact LCM(Num_Fact , Num_Fact);
How to implement the GCD function with arguments of 2 class objects, and return the value back in as Num_Fact as following in cpp:
cin >> value;
Num_Fact A(value);
cout << "Key in number B: ";
cin >> value;
Num_Fact B(value);
cout << " A = "<< A.output() <<" = "<<A.getnum()<<endl;
cout << " B = " <<B.output() << " = " << B.getnum() << endl;
Num_Fact C = GCD(A, B);
Original Code:
#ifndef NUM_FACTOR
#define NUM_FACTOR
#include<iostream>
#include<array>
#include<cmath>
#include<sstream>
using namespace std;
#define Z 20
class Num_Fact {
friend Num_Fact GCD(Num_Fact , Num_Fact);
friend Num_Fact LCM(Num_Fact , Num_Fact);
public:
Num_Fact(int num) {
Num = num;
}
~Num_Fact() {};
long long int findgcd(long long int a, int b) {
if (b == 0) return a;
return findgcd(b, a % b);
}
long long int LCM2(long long int a[], int n) {
long long int res = 1, i;
for (i = 0; i < n; i++) {
res = res * a[i] / findgcd(res, a[i]);
}
fact2num(res);
return res;
}
long long int GCD2(long long int arr[], int n)
{
long long int result = arr[0];
for (int i = 1; i < n; i++)
{
result = findgcd(arr[i], result);
if (result == 1)
{
fact2num(result);
return 1;
}
}
fact2num(result);
return result;
}
long long int GCD(int a, int b) {
int temp;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a;
}
long long int LCM(int a, int b) {
int lcm = (a * b) / GCD(a, b);
return lcm;
}
string Factorize() {
ostringstream output;
int fac = 2;
if (Num == 1) {
output << Num;
}
while (Num > 1)
{
if (Num % fac == 0)
{
output << fac << "^"; //print the base first
Num /= fac;
int pow = 1;
while (Num % fac == 0) //get the power of current base
{
Num /= fac;
pow++;
}
output << pow; //print out the power, now we have fac^pow printed
//if not the last factor, print a multiplication symbol
if (Num != 1)
output << " * ";
}
else
{
fac++;
}
}
return output.str();
}
string output() {
ostringstream output;
output << Factorize();
return output.str();
}
int getnum() {
return Num;
}
private:
int Num;
array<array<int, Z>, 2>fact;
};
#endif
Latest code for Header:
#ifndef NUM_FACTOR
#define NUM_FACTOR
#include<iostream>
#include<array>
#include<cmath>
#include<sstream>
using namespace std;
#define Z 20
int findgcd(long long int a, int b) {
if (b == 0) return a;
return findgcd(b, a % b);
}
int LCM2(long long int a[], int n) {
int res = 1, i;
for (i = 0; i < n; i++) {
res = res * a[i] / findgcd(res, a[i]);
}
return res;
}
int GCD2(long long int arr[], int n)
{
int result = arr[0];
for (int i = 1; i < n; i++)
{
result = findgcd(arr[i], result);
if (result == 1)
{
return 1;
}
}
return result;
}
int GCD1(int a, int b) {
int temp;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a;
}
int LCM(int a, int b) {
int lcm = (a * b) / GCD1(a, b);
return lcm;
}
class Num_Fact {
public:
Num_Fact(int num) {
Num = num;
}
~Num_Fact() {};
string Factorize() {
ostringstream output;
int fac = 2;
if (Num == 1) {
output << Num;
}
while (Num > 1)
{
if (Num % fac == 0)
{
output << fac << "^"; //print the base first
Num /= fac;
int pow = 1;
while (Num % fac == 0) //get the power of current base
{
Num /= fac;
pow++;
}
output << pow; //print out the power, now we have fac^pow printed
//if not the last factor, print a multiplication symbol
if (Num != 1)
output << " * ";
}
else
{
fac++;
}
}
return output.str();
}
string output() {
ostringstream output;
output << Factorize();
return output.str();
}
int getnum() {
return Num;
}
private:
int Num;
array<array<int, Z>, 2>fact;
};
Num_Fact GCD(Num_Fact A, Num_Fact B) {
return GCD(A.getnum(), B.getnum());
}
Num_Fact LCM(Num_Fact A, Num_Fact B) {
return LCM(A.getnum(), B.getnum());
}
#endif
Latest Code for CPP
#include<iostream>
#include<array>
#include<cmath>
#include<sstream>
#include"Num_Factor.h"
using namespace std;
const int S = 20;
void bonus();
int main() {
int value;
cout << "Key in number A: ";
cin >> value;
Num_Fact A(value);
cout << "Key in number B: ";
cin >> value;
Num_Fact B(value);
cout << " A = "<< A.output() <<" = "<<A.getnum()<<endl;
cout << " B = " <<B.output() << " = " << B.getnum() << endl;
Num_Fact C=GCD(A, B);
return 0;
}
It gives error when compiling such as "Unhandled exception at 0x00007FF72E1A53DF in lab09.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000C850A03EB8)." And also its pointing at:
Num_Fact GCD(Num_Fact A, Num_Fact B) {
return GCD(A.getnum(), B.getnum());
}
Num_Fact LCM(Num_Fact A, Num_Fact B) {
return LCM(A.getnum(), B.getnum());
}
The task is to call the Num_Fact C= GCD(A,B), the program is about to find gcd and lcm using classes and by using constructor such as "Num_Fact"
There's a lot of confusion in your class design. but I'm only going to address some of it here. First question, ask yourself why are the int versions of GCD and LCM members of the Num_Fact class? These functions work on integers only, so there is absolutely no reason to put them in the Num_Fact class. So move them out of the class, it will simplify the answer to your actual question. Second question, why are these functions returning long long int? They have integer arguments and they can never return a value that is bigger than an int. So change them to return int, again this will simplify the answer to your actual question.
With those changes done we can talk about your actual question. As we've seen you already have functions that calculate GCD and LCM on integers, so just use those functions when you want to calculate GCD or LCM on Num_Fact. Like this
Num_Fact GCD(Num_Fact a, Num_Fact b) {
return GCD(a.getnum(), b.getnum());
}
Num_Fact LCM(Num_Fact a, Num_Fact b) {
return LCM(a.getnum(), b.getnum());
}
That's it, really simple. In fact these functions doesn't even need to be friends, since they are only using the public methods of Num_Fact.

Blank output screen when I run this searching algorithm

I have been practicing median search algorithm, and this is what I wrote-
#include <iostream>
#include <stdlib.h>
using namespace std;
int S1[10] = { 0 };
int S2[1] = { 0 };
int S3[10] = { 0 };
int mediansearch(int A[], int k, int size)
{
int ran = rand() % size;
int i = 0;
int a = 0;
int b = 0;
int c = 0;
for (i = 0; i < size; i++)
{
if (A[ran] > A[i])
{
S1[a] = A[i];
a++;
}
else if (A[ran] == A[i])
{
S2[b] = A[i];
b++;
}
else
{
S3[c] = A[i];
c++;
}
}
if (a <= k)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
}
int main()
{
int arr[] = { 6, 5, 4, 8, 99, 74, 23 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = mediansearch(arr, 5, n);
cout << "5th smallest is:" << x << endl;
}
And I have been getting output as-
Process returned -1073741676 (0xC0000094) execution time : 1.704 s
So, what am I doing wrong? Any kind of help will be appreciated.
There are a few issues with this code, the first one being the naming of variables.
I suggest you choose more significative names in the future, because good naming is fundamental when someone else has to understand your code and your ideas.
Another thing is that the arguments of are in a counterintuitive order because the pair related to the array are separated by the index you want to look for.
I'd write int mediansearch(int A[], int size, int k)
Here the comparisons are reversed, k should be less than rather than greater than equal a
if (a <= k) // (k < a)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k) // (k < a + b)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
The other thing is that you're sharing S1, S2, and S3 among all the recursive calls and that causes some error that I wasn't able to identify, maybe someone commenting will help me out.
However, I suggest you read this article that explains in detail the procedure you're trying to implement: https://rcoh.me/posts/linear-time-median-finding/
It's python, but it can be easily ported to C/C++, and in fact that's what I did.
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
using namespace std;
int medianSearch(int A[], int size, int k)
{
int *lows = (int *)calloc(size, sizeof(int));
int lowsLen = 0;
int *highs = (int *)calloc(size, sizeof(int));
int highsLen = 0;
int *pivots = (int *)calloc(size, sizeof(int));
int pivotsLen = 0;
int median;
int pivot;
int i;
if (size == 1)
return A[0];
// Other ways of randomly picking a pivot
// pivot = 0;
// pivot = size-1;
// pivot = size/2;
assert(size > 0);
pivot = rand() % size;
for (i = 0; i < size; ++i)
{
if (A[i] < A[pivot])
{
lows[lowsLen] = A[i];
lowsLen++;
}
else if (A[i] > A[pivot])
{
highs[highsLen] = A[i];
highsLen++;
}
else
{
pivots[pivotsLen] = A[i];
pivotsLen++;
}
}
if (k < lowsLen)
median = medianSearch(lows, lowsLen, k);
else if (k < lowsLen + pivotsLen)
median = A[pivot];
else
median = medianSearch(highs, highsLen, k - lowsLen - pivotsLen);
free(lows);
free(highs);
free(pivots);
return median;
}
int compare(const void *a, const void *b)
{
return ( *(int *)a - *(int *)b );
}
int medianSorted(int A[], int size, int k)
{
qsort(A, size, sizeof(int), compare);
return A[k];
}
#define N 1000
int main()
{
int arr[N];
int brr[N];
int n = sizeof(arr) / sizeof(arr[0]);
int k = 200;
int x;
int y;
for (int i = 0; i < n; ++i)
arr[i] = brr[i] = rand();
x = medianSearch(arr, n, (k-1)%n);
y = medianSorted(brr, n, (k-1)%n);
string suffix;
switch (k % 10)
{
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0: suffix = "th"; break;
}
cout << k << suffix << " smallest is: " << x << endl;
cout << k << suffix << " smallest is: " << y << endl;
}
https://onlinegdb.com/HJc2V6Lbu

C++ Divide and conquer algorithm problems

I have just learnt about Divide and Conquer algorithm and I'm a little bit confused about it. The question is my homework, I have tried many ways to fix my code but it did not run.
#include <iostream>
using namespace std;
void inputArray(int* a, int& n)
{
cout << "Input n:";
cin >> n;
for (int i = 0; i < n; i++)
{
cout << "input a[" << i << "]= ";
cin >> a[i];
}
}
int sumeven(int* a, int l, int r)
{
if (l == r && a[l] % 2 == 0)
{
return a[l];
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n;
int a[20];
inputArray(a, n);
cout<<sumeven(a, 0,n-1);
return 0;
}
Try to test your programs without user input first:
#include <iostream>
using namespace std;
int sumeven(int* a, int l, int r)
{
if (r >= 6) return 0;
if (l > r ) return 0;
if (l >= r)
{
if (a[l] % 2 == 0)
{
return a[l];
}
else
{
return 0;
}
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n=6;
int a[6]={1,2,3,48,5,6};
cout<<sumeven(a,0,n-1);
return 0;
}

Merge and QuickSort - stack overloaded

Helo everyone. :)
I have to write a program where I have 4 types of sorting: bubble-, insertion-, merge- i quick-sort.
Program has to sort points x,y in array of structures (random) by amount of total of their coordinates //e.g.: (1,3) is less than (0,6) because 1+3<0+6//. It saves sorted ones in this same array and also in txt file with time of sorting by each B,I,M,Q-sort.
Code from Merge and MergeSort:
void Merge(Structure *tab, int A, int sr, int Z)
{
Structure *tmp = new Structure[Z];
int i;
for (i = A; i <= Z; ++i)
{
tmp[i] = tab[i];
}
i = A;
int j = sr + 1;
int q = A;
while (i <= sr && j <= Z)
{
if (Compare(tab, i, j)) //'Compare' tells if total of coordinates from tab[i] is bigger than total from tab[j]
{
tab[q] = tmp[i];
++j;
}
else
{
tab[q] = tmp[j];
++i;
}
++q;
}
if(i <= sr)
{
while (i <= sr)
{
tab[q] = tmp[i];
++i;
++q;
}
}
else
{
while(j <= Z)
{
tab[q] = tmp[j];
++j;
++q;
}
}
delete[] tmp;
}
void MergeSort(Structure *tab, int A, int Z)
{
int sr = (A + Z)/2;
if(A < Z)
{
MergeSort(tab, A, sr);
MergeSort(tab, sr + 1, Z);
Merge(tab, A, sr, Z);
}
}
And to QuickSort:
int DivideQS(Structure *tab, int A, int Z)
{
Structure tmp;
Structure pivot = tab[A]; // first el. for pivot (A=0)
int i = A, j = Z; //indexes in array
while (true)
{
while (Compare(tab, j, A))
j--;
while (!Compare(tab, i, A)) // until elements are lower than pivot, that's this '!' for
i++;
if (i < j) // swap when i < j
{
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
i++;
j--;
}
else
return j;
}
}
void QuickSort(Structure *tab, int A, int Z)
{
int dziel;
if (A < Z)
{
dziel = DivideQS(tab, A, Z);
QuickSort(tab, A, dziel);
QuickSort(tab, dziel+1, Z);
}
}
My problem is a stack. No matter how big I make this, it still goes overloaded. I can't manage this problem. I don't know if that's because of mistake in code or it's somewhere else. Bubble and Insertion work impeccable.
I was looking for solving on many sites, in my language and foreign ones (I'm Pole), and modificating code in so many ways but still have no clue what to do.
Help me, please.
===================================
How could I be so blind! Thank you #user3187084. :D
But I think I went from bad to worse. Now I've received new error message:
Windows has triggered a breakpoint in Projekt_AiSD.exe.
This may be due to a corruption of the heap, which indicates a bug in Projekt_AiSD.exe or any >of the DLLs it has loaded.
This may also be due to the user pressing F12 while Projekt_AiSD.exe has focus.
The output window may have more diagnostic information.
And after that this showed to me: http://i40.tinypic.com/314qyl5.png
And this is code for checking:
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <Windows.h>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
struct Structure
{
int x;
int y;
};
bool Compare(Structure *tab, int i, int j)
{
if ( (tab[i].x + tab[i].y) > (tab[j].x + tab[j].y))
return true;
return false;
}
void LosujWspolrzedne(Structure* tab, int K)
{
srand(time(NULL));
for (int i = 0; i < K; i++)
{
tab[i].x = rand()%21;
tab[i].y = rand()%21;
}
//return;
}
void Save (Structure *tab, int K, string NazwaPliku)
{
ofstream zap(NazwaPliku);
for (int i = 0; i < K; i++)
{
zap << tab[i].x << ' ' << tab[i].y << endl;
}
zap.close();
}
void Load (Structure *tab, int K, string NazwaPliku)
{
ifstream wcz(NazwaPliku);
if (!wcz)
{
cout << "Can't open the file!!!" << endl;
exit(1);
}
for (int i = 0; i < K; ++i)
{
wcz >> tab[i].x >> tab[i].y;
}
wcz.close();
}
void Time(long long a, long long b, string NazwaPliku)
{
ofstream czas(NazwaPliku);
if (!czas)
{
cout << "Can't open the file!!!" << endl;
}
czas << (b - a) << " ms" << endl;
czas.close();
}
void CopyArray(Structure *tab, Structure *tab1, int K)
{
for (int i = 0 ; i < K ; i++)
{
tab1[i].x = tab[i].x;
tab1[i].y = tab[i].y;
}
}
void Call_MS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
MergeSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla MergeSort" << endl;
Save(tab, K, "WartLos_MS_1k.txt");
Time(startTime, endTime, "WartLos_MS_1k_czas.txt");
}
void Call_QS(Structure *tab, int A, int K)
{
Load(tab, K, "1k.txt");
long long startTime = GetTickCount64();
QuickSort(tab, A, K-1);
long long endTime = GetTickCount64();
cout << (endTime - startTime) << "ms dla QuickSort" << endl;
Save(tab, K, "WartLos_QS_1k.txt");
Time(startTime, endTime, "WartLos_QS_1k_czas.txt");
}
const int MAX_EL = 30;
int _tmain(int argc, _TCHAR* argv[])
{
Structure *punkt = new Structure[MAX_EL];
void LosujWspolrzedne(Structure *punkt, int MAX_EL);
Structure *punkt1= new Structure[MAX_EL];
void CopyArray(Structure *punkt, Structure *punkt1, int MAX_EL);
delete[] punkt;
Save(punkt1, MAX_EL, "1k.txt");
cout<<"Start:"<<endl;
Call_MS(punkt1, 0, MAX_EL);
Call_QS(punkt1, 0, MAX_EL);
delete[] punkt1;
return 0;
}
You have MergeSort(tab, A, Z) inside MergeSort, so you always call itself with exact arguments
It should be MergeSort(tab, A, st)
You are using MergeSort(tab,A,Z) which call the same function again with same arguments which is will go one for infinite recursion hence error. You should only pass MergeSort(tab,A,sr) which will reduce your problem to half size.

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.