Degree: Polynomial Class (Odd Cases for User Input Expected) - c++

I have a polynomial class that prompts the user to enter values to be put into a vector of integers (vector<int> vect_poly). I'm trying to think of a way to detect the degree of the polynomial for cases where the user does something like this in the while loop:
0↵0↵0↵0↵4↵0↵0↵0↵0 ← x^4 (degree=4)
(OR)
0↵0↵0↵0↵0↵0↵0↵0↵0 ← (degree=0)
(OR)
4↵0↵0↵0↵0↵0↵0↵0↵0 ← x^0 (degree=0)
(OR)
0↵0↵0↵0↵0↵0↵0↵0↵4 ← x^8 (degree=8)
I'm really just looking for a slick algorithm.
What about this:
int degree()
{
int d = 0;
for ( int i = 0; i < 100; i++ )
if ( coef[i] != 0 ) d = i;
return d;
}

If u have this vector where user have enter the value of coefficient, you can traverse the vector from index 0 to the last element (Assuming user will enter the value of coefficient in correct order), and just save the value of last index whose value is not zero.
int degreeOfPolynomial=0;
for(int i=0 ; i < vect_poly.size() ; i++)
{
if(vect_poly[i] != 0)
degreeOfPolynomial = i;
}
After execution of above part of code, degreeOfPolynomial will store right value of degree of polynomial.

Why not just keep track of it?
std::vector<int> polynomial;
int degree = 0;
int inputs = 0;
int coefficient;
while (std::cin >> coefficient)
{
polynomial.push_back(coefficient);
if (coefficient != 0)
{
degree = inputs;
}
inputs++;
}

I see two options:
Simply copy the input into the vector, then search for the last non-zero and truncate the vector after that.
Copy input into a temporary vector, and each time a non-zero is entered, move-append the temporary vector to vect_poly, like this:
std::vector<int> temp;
int n;
while (std::cin >> n) {
temp.push_back(n);
if (n != 0) {
vect_poly.insert(vect_poly.end(), temp.begin(), temp.end());
temp.clear();
}
}
That way, you get everything except the trailing zero sequence in vect_poly.
EDIT
3. You can also keep the 0s in a counter:
int n;
size_t zeroes = 0;
while (std::cin >> n) {
if (n == 0) {
++zeroes;
} else {
vect_poly.insert(vect_poly.end(), zeroes, 0);
vect_poly.push_back(n);
zeroes = 0;
}
}

You can use a local variable to keep track of the max, and each time the user presses enter, you compare their input to the current max value.
int max=0;
while(1)
{
int input=0;
std::cin>>input;
if(input>max)
{
max=input;
}
}
Of course with some breakout condition so the loop doesn't run forever. You could try to mess with the ternary operator at the if statement, but I see little value in that.
EDIT: if you want to know the last set value (ie degree) of a previously generated but essentially random vector as quickly as possible, run a loop like this:
int max=0;
for(int k= myvec.size()-1; k>=0; k--)
{
if(myvec[k]>0)
{
max=k;
break;
}
}

Related

C++ How to optimize this algorithm ? (std::map)

The problem is the following: We are given a number 's', s ∈ [0, 10^6], and a number 'n', n ∈ [0, 50000], then n numbers, and we have to find how many number pairs' sum is equal to the 's' number (and we must use either maps or sets to solve it)
Here is the example:
Input:
5 (this is s)
6 (this is n)
1
4
3
6
-1
5
Output:
2
explanation : these are the (1,4) and (6,−1) pairs. (1 +4 = 5 and 6 + (-1) = 5)
Here is my "solution" , I don't even know if it's correct, but it works for the example that we got.
#include <iostream>
#include <map>
#include <iterator>
using namespace std;
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
int s;
cin >> s;
int n;
cin >> n;
map<int, int> numbers;
int element;
int counter = 0;
for(int i=0; i<n;i++)
{
cin >> element;
numbers.insert(pair<int, int>(element, s-element));
}
for(map<int, int>::iterator it = numbers.begin(); it != numbers.end(); it++)
{
map<int, int>::iterator it2 = it;
while(it2 != numbers.end())
{
if(it->second == it2->first)
{
counter++;
break;
}
it2++;
}
}
cout << counter << "\n";
return 0;
}
Thanks for the answers in advance! I'm still a beginner and I'm learning, sorry.
element, s-element is a good idea but there is no reason to store all the pairs and only then check for duplicates. This removes the O(n^2) loop you have there at the end.
The standard way using hashing would be:
seen=unordered_map<number,count>()
for 1...n:
e = read_int()
if (s-e) in seen:
duplicates+=seen[s-e] # Found new seen[s-e] duplicates.
if e in seen:
seen[e]+=1
else:
seen.insert(e,1)
return duplicates
Here's a brute-force method, using a vector:
int target_s = 0;
int quantity_numbers = 0;
std::cin >> target_s >> quantity_numbers;
std::vector<int> data(quantity_numbers);
for (int i = 0; i < quantity_numbers; ++i)
{
cin >> data[i];
}
int count = 0;
for (int i = 0; i < quantity_numbers; ++i)
{
for (j = 0; j < quantity_numbers; ++j)
{
if (i == j) continue;
int pair_sum = data[i] + data[j];
if (pair_sum == target_s) ++count;
}
}
std::cout << count;
The above code includes the cases where pair <a,b> == s and pair <b,a> == s. Not sure if the requirement only wants pair <a,b> in this case.
As always with this kind of questions, the selection of the appropriate algorithm will improve your solution. Writing some "better" C++ code, will nearly never help. Also, brute forcing is nearly never a solution for such an algorithm.
With the following described approach (which was of course not invented by me), we need just one std::map (or even better, a std::unordered_map) and one for loop. We do not need to store the read values in an additional std::vector or such alike. So, we can come up with low memory condumption and fast computation.
Approach. Any time, after reading a value, we will calculate the delta from the desired sum.
If we look at the required condition that the current value and some previuosly read value, should add up to the desired sum, we can write the following mathematical equations:
currentValue + previouslyReadValue = desiredSum
or
desiredSum - currentValue = previouslyReadValue
or with
delta = desiredSum - currentValue
-->
delta == previouslyReadValue
So, we need to look at the already read values and if they are equal to the delta (Because then they would add up the the desired sum), add their count of occurence the the resulting count of valid pairs.
The already read values and their count of occurence will be stored in a std::unordered_map.
All this will result in a 10 line solution:
#include <iostream>
#include <unordered_map>
int main() {
// Initialize our working variables
int numberOfValues{}, desiredSum{}, currentValue{}, resultingCount{};
// Read basic parameters. Desired sum and overall number of input values.
std::cin >> desiredSum >> numberOfValues;
// Here, we will store all values and their count of occurence
std::unordered_map<int, int> valuesAndCount{};
// Read all values and operate on them
for (int i{}; i < numberOfValues; ++i) {
std::cin >> currentValue; // Read from cin
const int delta{ desiredSum - currentValue }; // Calculate the delta from the desired sum
// Look, if the calculated delta is already in the map. Becuase, if the delta and the
// current value sum up to our desired sum, then we found a valid pair.
if (valuesAndCount.find(delta) != valuesAndCount.end())
// Increase the resulting count, by the number of times that this delta value has already been there
resultingCount += valuesAndCount[delta];
// Nothing special, Just cound the occurence of this value.
valuesAndCount[currentValue]++;
}
return !!(std::cout << resultingCount);
}

How do online judges pass the input data?

I'm trying to solve this problem from an online judge (Codeforces):
One day Deivis came across two Vectors of integers A and B, and wondered, could it be possible to form the number X by adding an element of A to another element of B?
More formally, it is possible to choose two indexes i and j such that Ai + Bj = x?
Input
The first entry line is two integers n and x. The second line contains n numbers, the vector A. The third and last line contains n numbers, vector B.
Output
Print 1 if it is possible to form the number x from a sum of one element of each vector, and 0 otherwise."
My problem is that I can not fill in the second vector, when the program runs on the site it fills the vector with zeros. I am using C ++, here's my code:
#include <bits/stdc++.h>
using namespace std;
#define MAX 10
int main()
{
int n, x, i = 0, j = 0, resp = 0, sum;
vector<int> vetA(MAX), vetB(MAX);
cin >> n >> x;
while (scanf("%d", &vetA[i]) == 1)
i++;
while (scanf("%d", &vetB[j]) == 1)
j++;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
sum = vetA[i] + vetB[j];
if (sum == x)
{
resp = 1;
goto END;
}
}
}
END: printf("%d", resp);
return 0;
}
I try to use getchar() after each while loop, but seems that on the site it does not do data capture like on a keyboard, and so the second vector isn't receiving any data. I've also tried to capture data as a std::string but that doesn't work.
Can someone help me?
Here are some hints/examples to compare your program to:
#include <iostream> //Include each standard library seperately
#include <vector> //#include <bits/stdc++.h> is bad practice
// Only declare variables as they are used.
int n; // Better coding practice is one variable per line.
int x; // Competitions shouldn't care how many lines.
if (!(std::cin >> n >> x)) //This is basically the same as cin.fail()
{
std::cerr << "Error inputting data.\n";
return 1;
}
// Now create the vectors, after the size has read in.
std::vector<int> vetA(n);
std::vector<int> vetB(n);
// The number of elements is known, so use a "for" loop.
for (size_t i = 0; i < n; ++i)
{
std::cin >> vetA[i];
}
for (size_t i = 0; i < x; ++i)
{
std::cin >> vetB[i];
}
You should add in some error handling because your program will be given some invalid inputs.
The inputs and vector sizes are examples since you didn't specify the input format in your Post.

While loop task in c++

I am a beginner in c++ and I am having problems with making this code work the way I want it to. The task is to write a program that multiplies all the natural numbers up to the loaded number n.
To make it print the correct result, I divided x by n (see code below). How can I make it print x and not have to divide it by n to get the correct answer?
#include<iostream>
using namespace std;
int main(){
int n,x=1;
int i=0;
cout<<"Enter a number bigger than 0:"<<endl;
cin>>n;
while(i<n){
i++;
x=i*x;
};
cout<<"The result is: "<<x/n<<endl;
return 0;
}
At very first a principle you best get used to as quickly as possible: Always check user input for correctness!
cin >> n;
if(cin && n > 0)
{
// valid
}
else
{
// appropriate error handling
}
Not sure, why do you need a while loop? A for loop sure is nicer in this case:
int x = 1;
for(int i = 2; i < n; ++i)
x *= i;
If you still want the while loop: Start with i == 2 (1 is neutral anyway) and increment afterwards:
i = 2;
while(i < n)
{
x *= i;
++i;
}
In case of n == 1, the loop (either variant) simply won't be entered and you are fine...
You already have two very good options, but here is an other one you might want to take a look at when you are at ease enough in programming :
unsigned factorial(unsigned value)
{
if (value <= 1)
{
return 1;
}
else
{
return value * factorial(value - 1);
}
}
It's a recursive function, which is kind of neat when used in proper moments (which could not be the case here unfortunately because the execution stack might get so big you fill your memory before you're done. But you can check it out to learn more about recursive functions)
When your memory is full, you then crash your app with what is called actually a stack overflow.
How can I make it so that in the last cout I can only put x and not have to divide x by n to get the correct answer?
It will be better to use a for loop.
// This stops when i reaches n.
// That means, n is not multiplied to the result when the loop breaks.
for (int i = 1; i < n; ++i )
{
x *= i;
}
cout << "The result is: " << x <<endl;

Count number of ways for choosing two numbers in efficient algorithm

I solved this problem but I got TLE Time Limit Exceed on online judge
the output of program is right but i think the way can be improved to be more efficient!
the problem :
Given n integer numbers, count the number of ways in which we can choose two elements such
that their absolute difference is less than 32.
In a more formal way, count the number of pairs (i, j) (1 ≤ i < j ≤ n) such that
|V[i] - V[j]| < 32. |X|
is the absolute value of X.
Input
The first line of input contains one integer T, the number of test cases (1 ≤ T ≤ 128).
Each test case begins with an integer n (1 ≤ n ≤ 10,000).
The next line contains n integers (1 ≤ V[i] ≤ 10,000).
Output
For each test case, print the number of pairs on a single line.
my code in c++ :
int main() {
int T,n,i,j,k,count;
int a[10000];
cin>>T;
for(k=0;k<T;k++)
{ count=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
{
if(i!=j)
{
if(abs(a[i]-a[j])<32)
count++;
}
}
}
cout<<count<<endl;
}
return 0;
}
I need help how can I solve it in more efficient algorithm ?
Despite my previous (silly) answer, there is no need to sort the data at all. Instead you should count the frequencies of the numbers.
Then all you need to do is keep track of the number of viable numbers to pair with, while iterating over the possible values. Sorry no c++ but java should be readable as well:
int solve (int[] numbers) {
int[] frequencies = new int[10001];
for (int i : numbers) frequencies[i]++;
int solution = 0;
int inRange = 0;
for (int i = 0; i < frequencies.length; i++) {
if (i > 32) inRange -= frequencies[i - 32];
solution += frequencies[i] * inRange;
solution += frequencies[i] * (frequencies[i] - 1) / 2;
inRange += frequencies[i];
}
return solution;
}
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int N;
int search (int x){
int low = 0;
int high = N;
while (low < high)
{
int mid = (low+high)/2;
if (a[mid] >= x) high = mid;
else low = mid+1;
}
return low;
}
int main() {
cin >> N;
for (int i=0 ; i<N ; i++) cin >> a[i];
sort(a,a+N);
long long ans = 0;
for (int i=0 ; i<N ; i++)
{
int t = search(a[i]+32);
ans += (t -i - 1);
}
cout << ans << endl;
return 0;
}
You can sort the numbers, and then use a sliding window. Starting with the smallest number, populate a std::deque with the numbers so long as they are no larger than the smallest number + 31. Then in an outer loop for each number, update the sliding window and add the new size of the sliding window to the counter. Update of the sliding window can be performed in an inner loop, by first pop_front every number that is smaller than the current number of the outer loop, then push_back every number that is not larger than the current number of the outer loop + 31.
One faster solution would be to first sort the array, then iterate through the sorted array and for each element only visit the elements to the right of it until the difference exceeds 31.
Sorting can probably be done via count sort (since you have 1 ≤ V[i] ≤ 10,000). So you get linear time for the sorting part. It might not be necessary though (maybe quicksort suffices in order to get all the points).
Also, you can do a trick for the inner loop (the "going to the right of the current element" part). Keep in mind that if S[i+k]-S[i]<32, then S[i+k]-S[i+1]<32, where S is the sorted version of V. With this trick the whole algorithm turns linear.
This can be done constant number of passes over the data, and actually can be done without being affected by the value of the "interval" (in your case, 32).
This is done by populating an array where a[i] = a[i-1] + number_of_times_i_appears_in_the_data - informally, a[i] holds the total number of elements that are smaller/equals to i.
Code (for a single test case):
static int UPPER_LIMIT = 10001;
static int K = 32;
int frequencies[UPPER_LIMIT] = {0}; // O(U)
int n;
std::cin >> n;
for (int i = 0; i < n; i++) { // O(n)
int x;
std::cin >> x;
frequencies[x] += 1;
}
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
frequencies[i] += frequencies[i-1];
}
int count = 0;
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
int low_idx = std::max(i-32, 0);
int number_of_elements_with_value_i = frequencies[i] - frequencies[i-1];
if (number_of_elements_with_value_i == 0) continue;
int number_of_elements_with_value_K_close_to_i =
(frequencies[i-1] - frequencies[low_idx]);
std::cout << "i: " << i << " number_of_elements_with_value_i: " << number_of_elements_with_value_i << " number_of_elements_with_value_K_close_to_i: " << number_of_elements_with_value_K_close_to_i << std::endl;
count += number_of_elements_with_value_i * number_of_elements_with_value_K_close_to_i;
// Finally, add "duplicates" of i, this is basically sum of arithmetic
// progression with d=1, a0=0, n=number_of_elements_with_value_i
count += number_of_elements_with_value_i * (number_of_elements_with_value_i-1) /2;
}
std::cout << count;
Working full example on IDEone.
You can sort and then use break to end loop when ever the range goes out.
int main()
{
int t;
cin>>t;
while(t--){
int n,c=0;
cin>>n;
int ar[n];
for(int i=0;i<n;i++)
cin>>ar[i];
sort(ar,ar+n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ar[j]-ar[i] < 32)
c++;
else
break;
}
}
cout<<c<<endl;
}
}
Or, you can use a hash array for the range and mark occurrence of each element and then loop around and check for each element i.e. if x = 32 - y is present or not.
A good approach here is to split the numbers into separate buckets:
constexpr int limit = 10000;
constexpr int diff = 32;
constexpr int bucket_num = (limit/diff)+1;
std::array<std::vector<int>,bucket_num> buckets;
cin>>n;
int number;
for(i=0;i<n;i++)
{
cin >> number;
buckets[number/diff].push_back(number%diff);
}
Obviously the numbers that are in the same bucket are close enough to each other to fit the requirement, so we can just count all the pairs:
int result = std::accumulate(buckets.begin(), buckets.end(), 0,
[](int s, vector<int>& v){ return s + (v.size()*(v.size()-1))/2; });
The numbers that are in non-adjacent buckets cannot form any acceptable pairs, so we can just ignore them.
This leaves the last corner case - adjacent buckets - which can be solved in many ways:
for(int i=0;i<bucket_num-1;i++)
if(buckets[i].size() && buckets[i+1].size())
result += adjacent_buckets(buckets[i], buckets[i+1]);
Personally I like the "occurrence frequency" approach on the one bucket scale, but there may be better options:
int adjacent_buckets(const vector<int>& bucket1, const vector<int>& bucket2)
{
std::array<int,diff> pairs{};
for(int number : bucket1)
{
for(int i=0;i<number;i++)
pairs[i]++;
}
return std::accumulate(bucket2.begin(), bucket2.end(), 0,
[&pairs](int s, int n){ return s + pairs[n]; });
}
This function first builds an array of "numbers from lower bucket that are close enough to i", and then sums the values from that array corresponding to the upper bucket numbers.
In general this approach has O(N) complexity, in the best case it will require pretty much only one pass, and overall should be fast enough.
Working Ideone example
This solution can be considered O(N) to process N input numbers and constant in time to process the input:
#include <iostream>
using namespace std;
void solve()
{
int a[10001] = {0}, N, n, X32 = 0, ret = 0;
cin >> N;
for (int i=0; i<N; ++i)
{
cin >> n;
a[n]++;
}
for (int i=0; i<10001; ++i)
{
if (i >= 32)
X32 -= a[i-32];
if (a[i])
{
ret += a[i] * X32;
ret += a[i] * (a[i]-1)/2;
X32 += a[i];
}
}
cout << ret << endl;
}
int main()
{
int T;
cin >> T;
for (int i=0 ; i<T ; i++)
solve();
}
run this code on ideone
Solution explanation: a[i] represents how many times i was in the input series.
Then you go over entire array and X32 keeps track of number of elements that's withing range from i. The only tricky part really is to calculate properly when some i is repeated multiple times: a[i] * (a[i]-1)/2. That's it.
You should start by sorting the input.
Then if your inner loop detects the distance grows above 32, you can break from it.
Thanks for everyone efforts and time to solve this problem.
I appreciated all Attempts to solve it.
After testing the answers on online judge I found the right and most efficient solution algorithm is Stef's Answer and AbdullahAhmedAbdelmonem's answer also pavel solution is right but it's exactly same as Stef solution in different language C++.
Stef's code got time execution 358 ms in codeforces online judge and accepted.
also AbdullahAhmedAbdelmonem's code got time execution 421 ms in codeforces online judge and accepted.
if they put detailed explanation to there algorithm the bounty will be to one of them.
you can try your solution and submit it to codeforces online judge at this link after choosing problem E. Time Limit Exceeded?
also I found a great algorithm solution and more understandable using frequency array and it's complexity O(n).
in this algorithm you only need to take specific range for each inserted element to the array which is:
begin = element - 32
end = element + 32
and then count number of pair in this range for each inserted element in the frequency array :
int main() {
int T,n,i,j,k,b,e,count;
int v[10000];
int freq[10001];
cin>>T;
for(k=0;k<T;k++)
{
count=0;
cin>>n;
for(i=1;i<=10000;i++)
{
freq[i]=0;
}
for(i=0;i<n;i++)
{
cin>>v[i];
}
for(i=0;i<n;i++)
{
count=count+freq[v[i]];
b=v[i]-31;
e=v[i]+31;
if(b<=0)
b=1;
if(e>10000)
e=10000;
for(j=b;j<=e;j++)
{
freq[j]++;
}
}
cout<<count<<endl;
}
return 0;
}
finally i think the best approach to solve this kind of problems to use frequency array and count number of pairs in specific range because it's time complexity is O(n).

Return the count of negative numbers in the optimal way

A variation of "Searching in a Matrix that is sorted rowwise and columnwise"
Given a 2D Matrix that is sorted rowwise and columnwise. You have to return the count of negative numbers in most optimal way.
I could think of this solution
initialise rowindex=0
if rowindex>0 rowindex++
else apply binary search
And implemented in with this code for 5X5 matrix
#include<iostream>
#include<cstdio>
using namespace std;
int arr[5][5];
int func(int row)
{
int hi=4;
int lo=0;
int mid=(lo+hi)/2;
while(hi>=lo)
{
mid=(lo+hi)/2;
.
if(mid==4)
{
return 5;
}
if(arr[row][mid]<0 && arr[row][mid+1]<0)
{
lo=mid+1;
}
else if(arr[row][mid]>0 && arr[row][mid+1]>0)
{
hi=mid-1;
}
else if(arr[row][mid]<0 && arr[row][mid+1]>0)
{
return mid+1;
}
}
}
int main()
{
int ri,ci,sum;
ri=0; //rowindex
ci=0; //columnindex
sum=0;
for(int i=0; i<5; i++)
{
for(int j=0; j<5; j++)
{
cin>>arr[i][j];
}
}
while(ri<5)
{
if(arr[ri][ci]>=0)
{
ri++;
}
else if(arr[ri][ci]<0)
{
int p=func(ri);
sum+=p;
ri++;
}
}
printf("%d\n",sum);
}
I ran the code here http://ideone.com/PIlNd2
runtime O(xlogy) for a matrix of x rows and y columns
Correct me if i am wrong in time complexity or implementation of code
Does anyone have any better idea than this to improve Run-time complexity?
O(m+n) algorithm, where m and n are the dimensions of the array, working by sliding down the top of the negative portion, finding the last negative number in each row. This is most likely what Prashant was talking about in the comments:
int negativeCount(int m, int n, int **array) {
// array is a pointer to m pointers to n ints each.
int count = 0;
int j = n-1;
for (int i = 0, i < m; i++) {
// Find the last negative number in row i, starting from the index of
// the last negative number in row i-1 (or from n-1 when i==0).
while (j >= 0 && array[i][j] >= 0) {
j--;
}
if (j < 0) {
return count;
}
count += j+1;
}
return count;
}
We can't do better than worst-case O(m+n), but if you're expecting far fewer than m+n negative numbers, you may be able to get a better usual-case time.
Suppose you have an n by n array, where array[i][j] < 0 iff i < n-j. In that case, the only way the algorithm can tell that array[i][n-1-i] < 0 for any i is by looking at that cell. Thus, the algorithm has to look at at least n cells.
You are conducting a binary search. Whereby you divide n by 2 to find the midpoint then continue to divide, before returning a value. That looks like a binary search, even though you are dividing columns for each row. Therefore, you are performing O(log n). Or something like O(x log n/y).