Factorial in bignum library - bignum

Ive tried to create my own implementation of a bignum library
I cant seem to get the factorial to work. If I ask it to solve 4!, it gives out 96. It multiplies 4 twice. similarly, 5! is 600, not 120. I haven't implemented division, so I cant/dont want to divide the answer by the number
//bignum project
#include <iostream>
using namespace std;
class bignum
{
public:
int number[100];
int dpos;
int operator/ (bignum);
bignum operator- (bignum);
bignum operator* (bignum);
bignum operator+ (bignum);
bignum operator= (string);
void output()
{
int begin=0;
for(int i=0; i<=99; i++)
{
if(number[i]!=0 || begin==1)
{
cout<<number[i];
begin=1;
}
}
}
};
bool num_is_zero(bignum k)
{
for(int a=0; a<=99; a++)
{
if(k.number[a]!=0)
{
return false;
}
}
return true;
}
bignum factorial(bignum a)
{
bignum j;
bignum fact;
fact="1";
while(!num_is_zero(a))
{
j="1";
fact=fact*a;
a=a-j;
}
return fact;
}
bignum bignum::operator= (string k)
{
int l;
l=k.length()-1;
for(int h=0; h<=99; h++)
{
number[h]=0;
}
for(int a=99; a>=0 && l>=0; a--)
{
number[a]=k[l]-'0';
l--;
}
}
bignum bignum::operator+ (bignum b)
{
bignum a;
int carry=0;
for(int k=0; k<=99; k++)
{
a.number[k]=0;
}
for(int i=99; i>=0; i--)
{
a.number[i]= number[i]+b.number[i]+a.number[i];
if(a.number[i]>9)
{
carry=(a.number[i]/10);
a.number[i-1]+=carry;
a.number[i]=(a.number[i]%10);
}
}
return (a);
}
bignum bignum::operator- (bignum c)
{
bignum a;
int sign=0;
for(int k=0; k<=99; k++)
{
a.number[k]=0;
}
for(int i=99; i>=0; i--)
{
if(number[i]<c.number[i])
{
number[i]+=10;
if(i!=0)
number[i-1]--;
}
a.number[i]=number[i]-c.number[i];
}
return (a);
}
bignum bignum::operator* (bignum b)
{
bignum ans;
int ans_grid[100][100],x,lines=0,carry,sum[100];
for(int a=0; a<=99; a++)
{
for(int b=0; b<=99; b++)
{
ans_grid[a][b]=0;
}
}
for(int i=99; i>=0; i--)
{
for(int j=i,x=99; j>=0; j--,x--)
{
ans_grid[lines][j]=(number[i]*b.number[x]);
}
lines++;
}
//------------------------------------------------Carry Forward and assign to ans------------------------------------------------//
for(int j=99; j>=0; j--)
{
for(int i=99; i>=0; i--)
{
if(ans_grid[j][i]>9 && i!=0)
{
carry=(ans_grid[j][i]/10);
ans_grid[j][i-1]+=carry;
ans_grid[j][i]%=10;
}
}
}
for(int col=99; col>=0; col--)
{
for(int row=99; row>=0; row--)
{
sum[col]+=ans_grid[row][col];
}
}
for(int i=99; i>=0; i--)
{
if(sum[i]>9 && i!=0)
{
carry=(sum[i]/10);
sum[i-1]+=carry;
sum[i]%=10;
}
}
for(int l=0; l<=99; l++)
ans.number[l]=sum[l];
//-------------------------------------------------------------------------------------------------------------------------------//
return (ans);
}

I think your problem is that sum is uninitialized in your operator*. I'm reluctant to give a partial answer, since I took the code and fiddled with it a bit, so here's my version which appears to work (and also prints "0" correctly):
Update: I couldn't resist making several structural improvements. I didn't touch your multiplication routine, so you should still be able to extract the bugfix even if you don't care for the rest.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class bignum
{
public:
int number[100];
bignum() { std::fill(number, number + 100, 0); }
bignum(const bignum & other) { std::copy(other.number, other.number + 100, number); }
bignum(const std::string &);
bignum & operator-=(const bignum &);
inline bignum operator-(const bignum & c) const { return bignum(*this) -= c; }
bignum operator*(const bignum &) const;
inline bignum & operator= (const std::string & k) { return *this = bignum(k); }
inline operator bool() const
{
for (size_t a = 0; a < 100; ++a)
if (number[a] != 0) return true;
return false;
}
};
std::ostream & operator<<(std::ostream & o, const bignum & b)
{
bool begun = false;
for (size_t i = 0; i < 100; ++i)
{
if (begun || b.number[i] != 0)
{
cout << b.number[i];
begun = true;
}
}
if (!begun) o << "0";
return o;
}
bignum::bignum(const std::string & k)
{
std::fill(number, number + 100, 0);
for(size_t h = 0; h < std::min(k.length(), 100U); ++h)
number[99 - h] = k[k.length() - 1 - h] - '0';
}
bignum & bignum::operator-=(const bignum & c)
{
for (int i = 99; i >= 0; --i)
{
if (number[i] < c.number[i])
{
number[i] += 10;
if (i != 0) --number[i-1];
}
number[i] -= c.number[i];
}
return *this;
}
bignum bignum::operator*(const bignum & b) const
{
bignum ans;
int ans_grid[100][100], lines = 0, carry, sum[100];
std::fill(sum, sum + 100, 0);
for (size_t i = 0; i < 100; ++i) std::fill(ans_grid[i], ans_grid[i] + 100, 0);
for(int i=99; i>=0; i--)
{
for(int j=i,x=99; j>=0; j--,x--)
{
ans_grid[lines][j]=(number[i]*b.number[x]);
}
lines++;
}
//------------------------------------------------Carry Forward and assign to ans------------------------------------------------//
for(int j=99; j>=0; j--)
{
for(int i=99; i>=0; i--)
{
if(ans_grid[j][i]>9 && i!=0)
{
carry=(ans_grid[j][i]/10);
ans_grid[j][i-1]+=carry;
ans_grid[j][i]%=10;
}
}
}
for(int col=99; col>=0; col--)
{
for(int row=99; row>=0; row--)
{
sum[col]+=ans_grid[row][col];
}
}
for(int i=99; i>=0; i--)
{
if(sum[i]>9 && i!=0)
{
carry=(sum[i]/10);
sum[i-1]+=carry;
sum[i]%=10;
}
}
for(int l=0; l<=99; l++)
ans.number[l]=sum[l];
//-------------------------------------------------------------------------------------------------------------------------------//
return (ans);
}
bignum factorial(bignum a)
{
bignum j; j = "1";
bignum fact; fact="1";
while(a)
{
fact = fact * a;
a = a-j;
}
return fact;
}
int main(int argc, char * argv[])
{
if (argc < 2) return 0;
bignum a;
a = std::string(argv[1]);
bignum b = factorial(a);
cout << a << std::endl << b << std::endl;
}
The string assignment is still broken for strings with more than one digit, but that wasn't your question I suppose...

Related

space complexity when a vector is copied

what will be the space complexity of this class? and why?
what will be the space complexity used by the function moveZeroes
class Solution {
public:
void moveZeroes(vector<int>& nums) {
vector<int>nums2(nums);
int j=0;
int numOfZeros=0;
for(int i=0;i<nums2.size();i++){
if(nums2[i]!=0){
nums[j]=nums2[i];
j++;
}
else{
numOfZeros++;
}
}
for (int k =numOfZeros; k >0 ; k--)
{
nums[j]=0;
j++;
}
}
};

TLE in Foe Pairs (Educational Codeforces Round 10)

On implementing O(N+M) complexity code for Foe Pairs problem
http://codeforces.com/contest/652/problem/C, I am getting TLE in Test Case 12.
Constraint : (1 ≤ N, M ≤ 3·105)
I am not getting, why for this constraint O(N+M) is getting TLE.
Here, is the code
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
std::vector<int> v(n+1);
for (int i = 0; i < n; ++i)
{
int x;
cin>>x;
v[x] = i;
}
std::vector<int> dp(n,0);
for (int i = 0; i < m; ++i)
{
int a,b;
cin>>a>>b;
if(v[a]>v[b])
swap(a,b);
dp[v[b]] = max(dp[v[b]], v[a]+1);
}
for (int i = 1; i < n; ++i)
{
dp[i] = max(dp[i], dp[i-1]);
}
long long s = 0;
for (int i = 0; i < n; ++i)
{
s+=(i+1-dp[i]);
}
cout<<s;
}
Is there anything, I am missing?
I changed all cin to scanf, it passed all test cases : http://codeforces.com/contest/652/submission/17014495
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,m;
scanf("%d%d", &n, &m);
//cin>>n>>m;
std::vector<int> v(n+1);
for (int i = 0; i < n; ++i)
{
int x;
//cin>>x;
scanf("%d", &x);
v[x] = i;
}
std::vector<int> dp(n,0);
for (int i = 0; i < m; ++i)
{
int a,b;
//cin>>a>>b;
scanf("%d%d", &a, &b);
if(v[a]>v[b])
swap(a,b);
dp[v[b]] = max(dp[v[b]], v[a]+1);
}
for (int i = 1; i < n; ++i)
{
dp[i] = max(dp[i], dp[i-1]);
}
long long s = 0;
for (int i = 0; i < n; ++i)
{
s+=(i+1-dp[i]);
}
cout<<s;
return 0;
}
You should always try to use scanf when the amount of input is large as it is faster.
You can read more about scanf being faster here : Using scanf() in C++ programs is faster than using cin?

Retrieving and manipulating data from file

The following code is supposed to retrieve the data related to the players info, sort it out and then rewrite the file now organized. Going to give an example of the files.
Original layout:
3
2 2
John 33 M 5
Anna 20 F 2
Rody 23 M 1
What it has to look like after the code:
3
2 2
Rody 23 M 1
Anna 20 F 2
John 33 M 5
I made the following code:
vector<string> playerScoresFromFile(const string filename) //Gets each one of those lines with the name, ..., and score of the person
{
int dim = filename[7] - '0'; // char to integer
vector<string> vec;
string line;
ifstream fin (filename.c_str());
for (int i = 0; i < dim + 1; i++)
{
getline(fin, line);
}
while(! fin.eof())
{
getline(fin, line);
vec.push_back(line);
}
return vec;
}
vector< vector<int> > readBoardFromFile(const string filename) //gets the board from the file (first 3 numbers)
{
int dim = filename[7] - '0'; // char to integer
string line;
vector< vector<int> >vec(dim, vector<int>(dim));
ifstream fin (filename.c_str());
int i = 0;
int j, k;
while(i < dim)
{
getline(fin, line);
int sizeOfLine = line.length();
if (line[0] == '\0')
{
break;
}
else
{
for (j = 0, k = 0; j < (sizeOfLine / 3); j++, k += 3)
{
string elementOfVectorStr = (line.substr(k,3));
int elementOfVectorInt = stringToInt(elementOfVectorStr);
if (abs(elementOfVectorInt) > 100) // when the element is a " ", the corresponding integer is always
{ // a very large number, positive or negative
elementOfVectorInt = 0;
}
vec[i][j] = elementOfVectorInt;
}
}
i++;
}
return vec;
}
vector<string> sortPlayersByTime (vector<string> &vec) // Creates a substring of the string extracted by "playerScoresFromFile" and analyses the times (Which are the last numbers to the right)
{
vector<int> timesInt(vec.size());
for (size_t i = 0; i < vec.size(); i++)
{
string str = vec[i];
timesInt[i] = stringToInt(str.substr(26));
}
for (size_t i = 0; i < vec.size() - 1; i++)
{
if(timesInt[i] > timesInt[i+1])
{
swap(vec[i], vec[i+1]);
}
}
return vec;
}
bool isOrdered (const vector<string> vec) //Checks if the vector is ordered
{
vector<int> timesInt(vec.size());
for (size_t i = 0; i < vec.size(); i++)
{
string str = vec[i];
timesInt[i] = stringToInt(str.substr(26));
}
for (size_t i = 0; i < vec.size() - 1; i++)
{
if(timesInt[i] > timesInt[i+1])
{
return false;
}
}
return true;
}
void writeBoardToFile(vector< vector<int> >&vec, string filename) //Rewrites the board to the file (Those first 3 numbers of the file)
{
ofstream fout(filename.c_str());
for (size_t i = 0; i < vec.size(); i++)
{
for (size_t j = 0; j < vec.size(); j++)
{
if(vec[i][j] != 0)
{
fout << setw(3) << vec[i][j];
}
else
{
fout << setw(3) << " ";
}
}
fout << endl;
}
fout << endl;
}
void vec_to_file(vector<string> vec, string filename) //Rewrites the vector to the file
{
ofstream fout(filename, ios::app);
for (int i = 0; i < vec.size(); i++)
{
fout << vec[i] <<endl;
}
}
void displayFile (string filename) //Displays the final board to check if it worked
{
vector<string> vec;
string line;
ifstream myfile (filename);
while ( ! myfile.eof() )
{
getline (myfile, line);
vec.push_back(line);
}
for (size_t i = 0; i < vec.size(); i++)
{
cout << vec[i] <<endl;
}
}
int main()
{
vector< vector<int> > vec = readBoardFromFile("puzzle_2x2_001.txt");
vector<string> vecxz = playerScoresFromFile("puzzle_2x2_001.txt");
writeBoardToFile(vec, "puzzle_2x2_001.txt"); //Writes the board to the file
while (! isOrdered(vecxz)) //This loop should run while they haven't been sorted out, but the program crashes here and I have no idea why.
{
sortPlayersByTime(vecxz);
}
//vec_to_file(vecxy, "puzzle_2x2_001.txt"); //Should write the vector to the file upon sorting them out successfully.
cin.get();
}
My problem is the program crashes everytime it gets to the while(! isOrdered(vecxz)) loop but I have no idea why. Can anyone give me a hand? I'd be thankful :)

sudoku algorithm analysis

This is the code for solving sudoku (9x9):
#include <iostream>
#define dim 9
#define br_polja dim*dim
using namespace std;
bool Fsearch (int tab[dim][dim],int *x,int *y, int cand[dim], int *num_cand, int &free) {
int min=9;
*x=-1;
*y=-1;
free=0;
for (int i=0;i<dim;i++) {
for (int j=0;j<dim;j++) {
if (tab[i][j]!=0) continue;
free+=1;
*num_cand=0;
int cand_f[dim];
for (int w=0;w<dim;w++)
cand_f[w]=1;
int p,q;
p=i+3-(i%3);
q=j+3-(j%3);
for (int w=p-3;w<p;w++)
for (int r=q-3;r<q;r++)
if (tab[w][r]!=0){
cand_f[tab[w][r]-1]=0;
}
for (int w=0;w<dim;w++) {
if (tab[w][j]!=0) cand_f[tab[w][j]-1]=0;
if (tab[i][w]!=0) cand_f[tab[i][w]-1]=0;
}
for (int w=0;w<dim;w++)
if (cand_f[w]!=0)
*num_cand+=1;
if (*num_cand==1) {
*x=i;
*y=j;
int z=0;
for (int w=0;w<dim;w++)
if (cand_f[w]!=0) {
cand[z]=w+1;
z++;
}
return true;
}
else if (*num_cand<min && *num_cand>0) {
int z=0;
for (int w=0;w<dim;w++)
if (cand_f[w]!=0) {
cand[z]=w+1;
z++;
}
min=*num_cand;
*x=i;
*y=j;
}
else if (*num_cand==0) {
return false;
}
}
}
*num_cand=min;
if (free<1) return false;
else return true;
}
bool Fsudoku(int tab[dim][dim]) {
int free=0;
int x,y;
int cand[dim];
int num_cand;
brojacK=0;
if (!Fsearch(tab,&x,&y,cand, &num_cand,free)) {
if (free==0) return true;
else return false;
}
for (int i=0;i<num_cand;i++) {
tab[x][y]=cand[i];
if (Fsudoku(tab)) return true;
else tab[x][y]=0;
}
return false;
}
Can someone tell help me classify this algorithm in Big O or Big Theta notation. I got O(n^3) but as we can see that's not true! So, give me a tip or an advice how to start, I would be very thankful.
And if you like, I can post this in pseudo-code too!
Thanks,
MB
Big O is about which terms dominate.
So how many times do each of the loops run?
Are they of fixed length, or do they vary?
What parameters can change that would effect the run time?

CUDA optimization question

Here's a simple program:
void multiply(const int* v_in, const int* w_in, int n_v, int n_w, int* w_out)
{
for(int i=0; i<n_w; i++)
{
int sum=0;
for(int j=0; j<n_v; j++)
sum += (w_in[i]*v_in[j])>>1;
w_out[i]=sum;
}
}
Presume n_v, n_w ~10^6. Clearly, there's at least a dozen equivalent ways to do this in CUDA, with different ways to subdivide (n_v*n_w) operations into threads, with and without shared memory... Which way should, theoretically speaking, be the fastest?
simplest:
void multiply(const int* v_in, const int* w_in, int n_v, int n_w, int* w_out)
{
int *v = shared; // dynamic
for(int i = block.rank; i < n_w; i += block.size)
{
int w = w_in[i]; // coalesced
int sum=0;
for(int j=0; j<n_v; j += block.size) { // assumption
v[block.rank] = v_in[j+block.rank];
__synch();
for(int k = 0; k < block.size; ++k)
sum += (w*v[k])>>1; //
__synch(); // ouch
}
w_out[i] = sum; // ditto
}
}