Error in saving degrees of polynomial for Polynomial Calculator - c++

I am creating a polynomial calculator for 2 polynomials in C++. For different operations, I have created different functions. Below is my approach for the function for multiplication. For multiplying, first I must save all the possible degrees. This should mean a max of highest degree of polynomial1+polynomial2, and least of smallest degree of either. I am first just saving all the possible degree options taking into consideration polynomial1 and polynomial 2. I will then sort the degrees in descending order, perform calculations on coefficients, and save the coefficient according to the degree calculated.
However I am unable to properly save all the possible degree options, and can't spot the error. The values that are actually being saved, I can't seem to understand, why they are being saved, and where is the error. I am writing this program without utilising external libraries like for performing calculations. Kindly spot the error, and how I can successfully save all the possible degree options correctly. The comments are my understanding of what is happening/ should be happening. Thanks.
The ideal output should be:
"99, 97, 95, 93, 91, 89, 98, 96, 94, 92, 90, 88...."
The current output is:
"99 96 93 90 87 84 81 78 75 72 688904896 32629 119 114 109 104 97 94 89 84 79 74 1377809792 65258 218 210 202 194 184 178"
#include <iostream>
using namespace std;
void multiply(int degree_poly1[], int terms_poly1, int degree_poly2[], int terms_poly2, int degree_result[])
{
int temp=0;
for(int a=0; a<terms_poly1*terms_poly2; a++)
{//this is first term
//degrees
for(int b=0; b<=a; b++)
{//this is 2nd term
if(degree_result[b]==0){
//checks if location is empty or not
//dr[0]=0, so go on
temp=degree_poly1[a]+degree_poly2[b];
for(int c=0; c<=b; c++)
{
if(temp==degree_result[c]){
//checks if there is already a value temp in previous array throughout. yes means stop
break;
}
if(temp!=degree_result[c]){
//checks
degree_result[b]=temp;
}
}
temp=0;
}
}
}
for(int a=0; a<terms_poly1*terms_poly2; a++)
{
cout<<degree_result[a]<<" ";
}
}
int main()
{
int degree_poly11[10]={79,78,77,76,75}, terms_poly11=5, degree_poly22[10]={20,18,16,14,12}, terms_poly22=6, degree_resultt[100]={};
/*
The whole program saves a polynomial 5x^9 + 7x^3 + 2x^2 as coefficients 5,7,2 in coefficient1[0], coefficient1[1], coefficient1[2] AND the degrees 9,3,2 in degree_poly11[0], degree_poly11[1], degree_poly11[2]. terms_poly11 gives the no. of total terms in the equation i.e. 3.
This array is currently not present here but is present in complete program.
Similarly for another polynomial2 in coefficient22[] and degree_poly22[].
*/
multiply(degree_poly11, terms_poly11, degree_poly22, terms_poly22, degree_resultt);
return 0;
}

One problem in your code is
temp=degree_poly1[a]+degree_poly2[b];
both a and b loop till 30, but both arrays have only 10 elements. You are accessing the arrays out of bounds and your code has undefined behavior. Even if all the rest would be ok, the output of the code could be anything because of this out-of-bounds access.
It is hard to understand the intended logic of your multiply function. Naming variables is a big issue in your code. a, b and c are completely meaningless to the reader of the code. Though already in main names are confusing.
You have
int degree_poly11[10]={79,78,77,76,75}, terms_poly11=5, ...;
I suppose degree_poly11 are the coefficients of the first polynome. Further, I guess that terms_poly11=5 is the degree of the polynome. If thats the case then name them like that.
When you need arrays of variable size you should think: std::vector.
I suggest to take pen and paper and calculate some examples (not one, but some). When you multiply two polynomials, their degrees add up and the coefficients are:
( poly1 * poly2)_{i} = sum_{j,k,j+k==i} ( poly1_{j} * poly2_{k} )
ie, the i-th coefficient is a sum of all products of coefficients from the input polynomials, such that their indices add up to i. Frankly, I don't see anything like that in your code.
Just this directly translated to code can look like this:
#include <vector>
#include <iostream>
std::vector<double> mult(const std::vector<double>& a,const std::vector<double>& b) {
std::vector<double> result(a.size() + b.size() - 1);
for (int i=0; i< result.size(); ++i) {
for (int j = 0; j <= i && j < a.size(); ++j) {
int k = i-j;
if (k >= b.size()) continue;
result[i] += a[j] * b[k];
}
}
return result;
}
int main(){
auto res = mult( {-1,1},{1,1});
for (int i=0;i<res.size();++i){
std::cout << res[i] << "*x^" << i << " + ";
}
}
Output is:
-1*x^0 + 0*x^1 + 1*x^2 +
Seems to be correct, because (x+1)*(x-1) == (x^2 -1). I didn't test more yet.
(x+1) and (x-1) are of degree 1, thats one less than they have coefficients, and the result has one coefficient more than its degree (a polynomial of degree 0 is a constant, it has 1 coefficient). Hence the size of the output vector a.size() + b.size() - 1.
The outer loop is to calculate i-th coefficient. Loop counters are choosen such that all combinations of j and k that add up to i are passed and included in the sum. Because I know my first attempt is off by one somewhere I have additional checks to be sure that j < a.size() and k < b.size().

Related

Troubleshooting a nested FOR loop that increments two variables

I am trying to solve the apartments problem on CSES. VERY new to coding and not looking for a solution.. just help with troubleshooting.
https://cses.fi/problemset/task/1084/.
I want to match n applicants to m apartments based on cost, given a list of each. It works with sample inputs, but many tests still fail. I think the issue is with my vector manipulation in the nested for loop.
Example of a test that fails
n 10
m 10
k 10
n integers 90 41 20 39 49 21 35 31 74 86
m integers 14 24 24 7 82 85 82 4 60 95
Expected result for aptsMatched: 6, my result: 3
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, k, aptfill, aptsize;
int aptsMatched = 0;
vector<int> desiredSize;
vector<int> apts;
int b=0;
cin >> n;
cin >> m;
cin >> k;
I'm sure there's a better way to do this.. but I'm brand new and attempted to do this in an intuitive manner. Was able to successfully fill my vectors with the inputs below.
for (int i = 0; i < n; i++) {
cin >> aptfill;
desiredSize.push_back(aptfill);
sort(desiredSize.begin(), desiredSize.end());
reverse(desiredSize.begin(), desiredSize.end());
}
for (int i = 0; i < m; i++) {
cin >> aptsize;
apts.push_back(aptsize);
sort(apts.begin(), apts.end());
reverse(apts.begin(), apts.end());
}
I'm attempting to iterate through the apts vector 3x, each time holding the apts index value constant while iterating through the desiredSize vector indices. Suspect something is wrong with the nested loop - either j<desiredSize.size(); or flawed logic in the if statement... or even with the erase function. My questions are: how can I test what's going wrong here? is there possibly a better container?
for (int i = 0; i < m; i++) {
for (int j = 0; j < desiredSize.size(); j++) {
if (abs(apts[b] - desiredSize[j]) <= k) {
desiredSize.erase(desiredSize.begin() + j);
b++;
aptsMatched++;
break;
}
else {
continue;
}
}
}
cout << aptsMatched;
}
I realize this code is pretty hideous, and that there are much faster ways to achieve the same idea. I'd first like to understand this methodology (if it's not completely flawed to start with), but am open to more effective ways to approach this problem too.
Thanks
One way could be to sort both the desired sizes and the appartment sizes and start matching from the smallest and upwards.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
int max_diff = 10;
std::vector<int> desired{90, 41, 20, 39, 49, 21, 35, 31, 74, 86};
std::vector<int> apts{14, 24, 24, 7, 82, 85, 82, 4, 60, 95};
std::sort(desired.begin(), desired.end());
std::sort(apts.begin(), apts.end());
int aptsMatched = 0;
auto dit = desired.begin(); // iterator to the desired sizes
auto ait = apts.begin(); // iterator to appartment sizes
// loop until one of them reaches the end
while(dit != desired.end() && ait != apts.end()) {
// do we have a good fit?
if(*dit + max_diff >= *ait // the maximum size is >= appartment size
&&
*dit - max_diff <= *ait ) // the minimum size is <= appartment size
{
++aptsMatched;
++dit;
++ait;
} else // not a good fit, step the iterator to the smallest size
if(*dit < *ait) ++dit;
else ++ait;
}
std::cout << aptsMatched << '\n';
}
I want to match n applicants to m apartments based on cost
But there is no cost; you mean desired size, right? ... but even then - how do you want to match applicants to apartments?
Since you're a beginner, consider writing down your algorithm in your own words, in English - both for yourself, before you write your C++ code, and for us if you want help understanding what' going wrong.
Also, here are some red flags for you:
You're sorting your (partial) data repeatedly - n and m times respectively! That's almost certainly the wrong thing to do.
You're reversing your (partial) data repeatedly. This too seems quite redundant.
Other issues with your code:
You really should not include internal library headers which are not defined by the standard, like <bits/whatever>. See here.
Your shorthand names are confusing. First, n and m are quite opaque. Also, aptfill, b? No idea what that's supposed to mean.
Why bother sorting in one direction, then reversing? Just sort in the opposite direction. Or, alternatively, you can iterate the sorted array backwards.

How to calculate the minimum cost to convert all n numbers in an array to m?

I have been given the following assignment:
Given N integers in the form of A(i) where 1≤i≤N, make each number
A(i) in the N numbers equal to M. To convert a number A(i) to M, it
will cost |M−Ai| units. Find out the minimum cost to convert all the N
numbers to M, so you should choose the best M to get the minimum cost.
Given:
1 <= N <= 10^5
1 <= A(i) <= 10^9
My approach was to calculate the sum of all numbers and find avg = sum / n and then subtract each number by avg to get the minimum cost.
But this fails in many test cases. How can I find the optimal solution for this?
You should take the median of the numbers (or either of the two numbers nearest the middle if the list has even length), not the mean.
An example where the mean fails to minimize is: [1, 2, 3, 4, 100]. The mean is 110 / 5 = 22, and the total cost is 21 + 20 + 19 + 18 + 78 = 156. Choosing the median (3) gives total cost: 2 + 1 + 0 + 1 + 97 = 101.
An example where the median lies between two items in the list is [1, 2, 3, 4, 5, 100]. Here the median is 3.5, and it's ok to either use M=3 or M=4. For M=3, the total cost is 2 + 1 + 0 + 1 + 2 + 97 = 103. For M=4, the total cost is 3 + 2 + 1 + 0 + 1 + 96 = 103.
A formal proof of correctness can be found on Mathematics SE, although you may convince yourself of the result by noting that if you nudge M a small amount delta in one direction (but not past one of the data points) -- and for example's sake let's say it's in the positive direction, the total cost increases by delta times the number of points to the left of M minus delta times the number of points to the right of M. So M is minimized when the number of points to its left and the right are equal in number, otherwise you could move it a small amount one way or the other to decrease the total cost.
#PaulHankin already provided a perfect answer. Anyway, when thinking about the problem, I didn't think of the median being the solution. But even if you don't know about the median, you can come up with a programming solution.
I made similar observations as #PaulHankin in the last paragraph of his last answer. This made me realize, that I have to eliminate outliers iteratively in order to find m. So I wrote a program that first sorts the input array (vector) A and then analyzes the minimum and maximum values.
The idea is to move the minimum values towards the second smallest values and the maximum values towards the second largest values. You always move either the minimum or maximum values, depending on whether you have less minimum values than maximum values or not. If all array items end up being the same value, then you found your m:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int getMinCount(vector<int>& A);
int getMaxCount(vector<int>& A);
int main()
{
// Example as given by #PaulHankin
vector<int> A;
A.push_back(1);
A.push_back(2);
A.push_back(3);
A.push_back(4);
A.push_back(100);
sort(A.begin(), A.end());
int minCount = getMinCount(A);
int maxCount = getMaxCount(A);
while (minCount != A.size() && maxCount != A.size())
{
if(minCount <= maxCount)
{
for(int i = 0; i < minCount; i++)
A[i] = A[minCount];
// Recalculate the count of the minium value, because we changed the minimum.
minCount = getMinCount(A);
}
else
{
for(int i = 0; i < maxCount; i++)
A[A.size() - 1 - i] = A[A.size() - 1 - maxCount];
// Recalculate the count of the maximum value, because we changed the maximum.
maxCount = getMaxCount(A);
}
}
// Print out the one and only remaining value, which is m.
cout << A[0] << endl;
return 0;
}
int getMinCount(vector<int>& A)
{
// Count how often the minimum value exists.
int minCount = 1;
int pos = 1;
while (pos < A.size() && A[pos++] == A[0])
minCount++;
return minCount;
}
int getMaxCount(vector<int>& A)
{
// Count how often the maximum value exists.
int maxCount = 1;
int pos = A.size() - 2;
while (pos >= 0 && A[pos--] == A[A.size() - 1])
maxCount++;
return maxCount;
}
If you think about the algorithm, then you will come to the conclusion, that it actually calculates the median of the values in the array A. As example input I took the first example given by #PaulHankin. As expected, the code provides the correct result (3) for it.
I hope my approach helps you to understand how to tackle such kind of problems even if you don't know the correct solution. This is especially helpful when you are in an interview, for example.

Having trouble formatting code to solve for Standard Deviation of a 2D array

Most of my code for the program is completed. I need help with the standard deviation. When I run the program, it compiles and gives me values, but I think the std value is not correct. I don't think using arr[ROWS][COLS] is the best way to go about it, but I used it anyway to show all of the values in the array. I think that is what is giving me the incorrect output. How do I fix it? Use a different way to show each value, but how? The loop should run 24 times. Each time it will use like say number[0] - average and then keep it and then add it to say number[1] - average all the way till it hits the max amount of numbers in the array.
Here is a formula for standard deviation.
s is the standard deviation.
M is the mean or average. -----> I already have double average as M
n is the number of values in the array. -------> I have MAX_VALUES equal to n.
* X is for each value in the array.
89 93 23 89 78 99
95 21 87 92 90 89
94 88 65 44 89 91
77 92 97 68 74 82
//To calculate standard deviation of 2-D array
double getStandardDeviation(int arr[ROWS][COLS], double &std, double average, int num, const int MAX_VALUES)
{
double devSum = 0; //sum of every value in array minus the average that is then squared
for (int x = 0; x < MAX_VALUES; x++)
{
devSum += pow((arr[ROWS][COLS] - average), 2);
}
std = sqrt(devSum / (MAX_VALUES - 1));
return std;
}
//end of getStandardDeviation method
The error in getStandardDeviation is that you are using the wrong indices, ROW and COL, for every value of x.
Instead of
for (int x = 0; x < MAX_VALUES; x++)
{
devSum += pow((arr[ROWS][COLS] - average), 2);
// ^^^^^^^^^^^ Wrong indices
}
use
double square(double x)
{
return x*x;
}
for ( int r = 0; r < ROWS; ++r )
{
for ( int c = 0; c < COLS; ++c )
{
// Use of pow(..., 2) is not necessary.
// devSum += pow((arr[r][c] - average), 2);
// Use a more efficient method.
devSum += square(arr[r][c] - average);
}
}

What is the complexity of this program

I have solved a question on HackerEarth.
The question is
Phineas is Building a castle in his backyard to impress Isabella ( strange, isn't it? ). He has got everything delivered and ready. Even the ground floor has been finished. Now is time to make the upper part. This is where the things become interesting. As Ferb is sleeping in the house after a long day painting the fence (and you folks helped him, didn't ya!), Phineas has to do all the work himself. He is good at this, and all he wants you to do is operate the mini crane to lift the stones. Stones for the wall has been cut and ready waiting for you to lift them up.
Now we don't have Ferb to operate the mini crane, in which he is an expert, we got to do the job as quick as possible. We are given the maximum lifting capacity of the crane, and the weight of each stone. Since it's a mini crane, we cannot place more then 2 stones (of any possible size) at a time, or it will disturb the balance of the crane. we need to find out in how many turns we can deliver the stones to Phineas, who is building the castle.
INPUT: First line of input gives T, the number of test cases. For each test case, first line gives M, the maximum lifting capacity of the crane. first integer N of next line of each test case gives the number of stones, followed by N numbers, specifying the weight of individual stone X.
OUTPUT: For each test case, print the minimum number of turns the crane is operated for all stones to be lifted.
CONSTRAINTS:
1 <= T <= 50
1 <= M <= 1000
1 <= N <= 1000
Sample Input
1
50
3 28 22 48
Sample Output
2
Explanation
In first turn, 28 and 22 will be lifted together. In second turn 48 will be lifted.
Discard the stones with weight > max capacity of crane.
Now I have solved this question and I my source code is
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;
int main(void) {
int T = 0;
scanf("%d",&T);
while(T--) {
int i = 0,M = 0, N = 0,max = 0, res = 0, index = 0, j = 0, temp = 0;
vector<int> v1;
scanf("%d",&M);
scanf("%d",&N);
for(i = 0; i < N ;++i) {
scanf("%d",&temp);
if(temp <= M)
v1.push_back(temp);
}
for(i = 0; i < v1.size() ; ++i) {
max = 0;
index = 0;
if(v1[i] != -1) {
for(j = i + 1; j < v1.size(); ++j) {
if(v1[j] != -1) {
temp = v1[i] + v1[j];
if(temp > max && temp <= M) {
max = temp;
index = j;
}
}
}
++res;
v1[i] = -1;
v1[index] = -1;
}
}
printf("%d\n",res);
}
return 0;
}
Now here are my question
I want to know the average case time complexity of this code. Also I think worst case complexity of this code would be O(N^2).
This is a brute force approach or dynamic programming approach?
Is there any better approach then this?
This is a simplified version of Knapsack Prolblem
While the Knapsack problem is a typical dynamic programming question, this simplified question does not require dynamic Programming. Complexity of your solution is indeed O(n^2), the approach is more suitable described as Greedy As you tried to find a optimal pair for each stone, if there exist. The complexity can be further reduced to O(nlgn) if you sort the stones first and work on a sorted vector.

Number of parallelograms on a NxM grid

I have to solve a problem when Given a grid size N x M , I have to find the number of parallelograms that "can be put in it", in such way that they every coord is an integer.
Here is my code:
/*
~Keep It Simple!~
*/
#include<fstream>
#define MaxN 2005
int N,M;
long long Paras[MaxN][MaxN]; // Number of parallelograms of Height i and Width j
long long Rects; // Final Number of Parallelograms
int cmmdc(int a,int b)
{
while(b)
{
int aux = b;
b = a -(( a/b ) * b);
a = aux;
}
return a;
}
int main()
{
freopen("paralelograme.in","r",stdin);
freopen("paralelograme.out","w",stdout);
scanf("%d%d",&N,&M);
for(int i=2; i<=N+1; i++)
for(int j=2; j<=M+1; j++)
{
if(!Paras[i][j])
Paras[i][j] = Paras[j][i] = 1LL*(i-2)*(j-2) + i*j - cmmdc(i-1,j-1) -2; // number of parallelograms with all edges on the grid + number of parallelograms with only 2 edges on the grid.
Rects += 1LL*(M-j+2)*(N-i+2) * Paras[j][i]; // each parallelogram can be moved in (M-j+2)(N-i+2) places.
}
printf("%lld", Rects);
}
Example : For a 2x2 grid we have 22 possible parallelograms.
My Algorithm works and it is correct, but I need to make it a little bit faster. I wanna know how is it possible.
P.S. I've heard that I should pre-process the greatest common divisor and save it in an array which would reduce the run-time to O(n*m), but I'm not sure how to do that without using the cmmdc ( greatest common divisor ) function.
Make sure N is not smaller than M:
if( N < M ){ swap( N, M ); }
Leverage the symmetry in your loops, you only need to run j from 2 to i:
for(int j=2; j<=min( i, M+1); j++)
you don't need an extra array Paras, drop it. Instead use a temporary variable.
long long temparas = 1LL*(i-2)*(j-2) + i*j - cmmdc(i-1,j-1) -2;
long long t1 = temparas * (M-j+2)*(N-i+2);
Rects += t1;
// check if the inverse case i <-> j must be considered
if( i != j && i <= M+1 ) // j <= N+1 is always true because of j <= i <= N+1
Rects += t1;
Replace this line: b = a -(( a/b ) * b); using the remainder operator:
b = a % b;
Caching the cmmdc results would probably be possible, you can initialize the array using sort of sieve algorithm: Create an 2d array indexed by a and b, put "2" at each position where a and b are multiples of 2, then put a "3" at each position where a and b are multiples of 3, and so on, roughly like this:
int gcd_cache[N][N];
void init_cache(){
for (int u = 1; u < N; ++u){
for (int i = u; i < N; i+=u ) for (int k = u; k < N ; k+=u ){
gcd_cache[i][k] = u;
}
}
}
Not sure if it helps a lot though.
The first comment in your code states "keep it simple", so, in the light of that, why not try solving the problem mathematically and printing the result.
If you select two lines of length N from your grid, you would find the number of parallelograms in the following way:
Select two points next to each other in both lines: there is (N-1)^2
ways of doing this, since you can position the two points on N-1
positions on each of the lines.
Select two points with one space between them in both lines: there is (N-2)^2 ways of doing this.
Select two points with two, three and up to N-2 spaces between them.
The resulting number of combinations would be (N-1)^2+(N-2)^2+(N-3)^2+...+1.
By solving the sum, we get the formula: 1/6*N*(2*N^2-3*N+1). Check WolframAlpha to verify.
Now that you have a solution for two lines, you simply need to multiply it by the number of combinations of order 2 of M, which is M!/(2*(M-2)!).
Thus, the whole formula would be: 1/12*N*(2*N^2-3*N+1)*M!/(M-2)!, where the ! mark denotes factorial, and the ^ denotes a power operator (note that the same sign is not the power operator in C++, but the bitwise XOR operator).
This calculation requires less operations that iterating through the matrix.