Why does this "improvement" to this algoirthm not work? - c++

I created an algorithm to solve the following problem statement:
The problem statement is :
We say that two integers x and y have a variation of at least K, if |x − y| ≥ K (the absolute value of their difference is at least K). Given a sequence of N integers a1,a2,...,aN and K, the total variation count is the number of pairs of elements in the sequence with variation at least K, i.e. it is the size of the set of pairs
{(i,j)|1≤i<j≤N and|ai−aj|≥K}
code:
int n, k, count = 0;
cin >> n >> k;
int v[n];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
sort(v, v + n);
for (int i = 0, j = 1; i < n;) {
if (abs(v[i] - v[j]) >= k) {
count += (n-j);
i++;
}
else
j++;
}
cout << count;
return 0; }
If we have the input:
4 1 // first int is the number of N integers, the second int is the k.
3 1 3 2 // first integers.
So my problem is the following: If I want to improve the algorithm by adding j++ under the i++ in the if block, the output changes from 5 (the correct one) to 4. When i test this improvement on papper and it seems to work, but in code it doesn't, why?

if I trace the execution with your inputs
without the added j++ associated to the i++ :
(abs(v[0] - v[1]) >= k) = 1
count += (n-1)
(abs(v[1] - v[1]) >= k) = 0
(abs(v[1] - v[2]) >= k) = 1
count += (n-2)
(abs(v[2] - v[2]) >= k) = 0
(abs(v[2] - v[3]) >= k) = 0
(abs(v[2] - v[4]) >= k) = 1
count += (n-4)
(abs(v[3] - v[4]) >= k) = 1
count += (n-4)
result 5
if I add j++ in the block containing i++ :
(abs(v[0] - v[1]) >= k) = 1
count += (n-1)
(abs(v[1] - v[2]) >= k) = 1
count += (n-2)
(abs(v[2] - v[3]) >= k) = 0
(abs(v[2] - v[4]) >= k) = 1
count += (n-4)
(abs(v[3] - v[5]) >= k) = 1
count += (n-5)
result 4
This is not the same thing, in that case the result is not the same because of the last count += (n-5) rather than count += (n-4) because of the value of j
[edit add]
The program to test :
#include <iostream>
using namespace std;
int main(int, char **)
{
#if 0
int n, k, count = 0;
cin >> n >> k;
int v[n];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
sort(v, v + n);
#else
int n = 4, k = 1;
int v[] = { 1, 2, 3, 3};
int count = 0;
#endif
for (int i = 0, j = 1; i < n;) {
cout << "(abs(v[" << i << "] - v[" << j << "]) >= k) = " << (abs(v[i] - v[j]) >= k) << endl;
if (abs(v[i] - v[j]) >= k) {
cout << "\tcount += (n-" << j << ")" << endl;
count += (n-j);
j++; // THIS LINE IS IN COMMENT OR OUT OF COMMENT
i++;
}
else
j++;
}
cout << count;
return 0;
}
[/edit]

Related

I cannot seem to find the problem Exception thrown: write access violation. prime was 0x828753A3. C++

I'm currently coding the sieve of Atkin in C++ and it is working well when I'm generating all prime numbers under 50 000 or so but when I try with 50 000 or more the error "Exception thrown: write access violation. prime was 0x828753A3." appears and I can't seem to understand why.
this error appears under the bloc of code where I get rid of multiple of k^2
//get rid of multiple of prime k^2
//start at 5 to skip useless loop with 2 and 3
for (int i = 5; i < n + 1; i++) {
if (prime[i]) {
for (int j = i * i; j <= n; j += i * i) {
prime[j] = false; //Exception thrown: write access violation. prime was 0x828753A3
}
}
}
Here is the full code:
#include <iostream>
using namespace std;
void Atkins(int n) {
bool* prime = new bool[n + 1];
int nbr = 0;
// set all value to false
for (int i = 0; i < n + 1; i++) {
prime[i] = false;
}
//test for all x y combination
for (int x = 1; x*x < n; x++){
for (int y = 1; y * y < n; y++) {
//test three different algorithm possible
int k = 4 * x * x + y * y;
if (k <= n && (k % 12 == 1 || k % 12 == 5)) {
prime[k] = !prime[k];
}
k = 3 * x * x + y * y;
if (k <= n && k % 12 == 7) {
prime[k] = !prime[k];
}
if (x > y) {
k = 3 * x * x - y * y;
if (k <= n && k % 12 == 11) {
prime[k] = !prime[k];
}
}
}
}
//get rid of multiple of prime k^2
//start at 5 to skip useless loop with 2 and 3
for (int i = 5; i < n + 1; i++) {
if (prime[i]) {
for (int j = i * i; j <= n; j += i * i) {
prime[j] = false; //Exception thrown: write access violation. prime was 0x828753A3
}
}
}
//base prime number in list
if (n >= 2) {
cout << "2\n";
nbr++;
}
if (n >= 3) {
cout << "3\n";
nbr++;
}
//print all prime number in list
for (int i = 5; i < n + 1; i++) {
if (prime[i]) {
nbr++;
cout << i << "\n";
}
}
cout << "Il y a " << nbr << " nombre premier entre 0 et " << n << "\n";
delete[] prime;
system("PAUSE");
}
int main() {
Atkins(50000);
return 0;
}
While you're properly guarded all accesses against too big index values, you didn't expect them to be negative.
By running the code under debugger you can see that when error happens, n = -2146737495.
Such value was cause by "integer overflow". When i=46349 -> i*i= 2148229801, which is more than int (32 bit) can take (2^31 - 1).
Simple way is to use long long int data type for multiplication (it has 64 bits, so max value is 2^63 - 1).
int j = i * i; j <= n; j += i * i -> long long int j = (long long int)i * i; j <= n; j += (long long int)i * i.
Several things you need to realize:
On a 32bit platform, INT_MAX is 2147483647. The maximum natural root below that value is 46340 (e.g. root of x^2 = 2147395600.
Automatic representation promotion isn't a language feature. I.e. if you have two int values x=50000 and y=50000, the expression x*y is still int, but because of signed integer overflow, has platform-dependent results. You don't want that.
Yes, you can change the data types to larger 64bit representations, but you don't have to do that. To accommodate the above problem and considerably reduce your workload, understand that you should limit your loops without having to compute i * i or j * j as part of the conditionals. Rather, you can cap the top-end of those loops (and more) using the real thing you're trying to prevent: cross over the square root boundary of n.
For example:
for (int x = 1; x*x < n; x++){
Suppose there was a value nr that was the result of acquiring the integer portion of the square root of n. Then, would what you're really trying to do be better considered as:
int nr = sqrt(n) + 1;
for (int x=1; x < nr; ++x)
So lets do that.
#include <iostream>
#include <cmath>
using namespace std;
void Atkins(int n)
{
bool *prime = new bool[n + 1];
int nbr = 0;
// set all value to false
for (int i = 0; i < n + 1; i++)
{
prime[i] = false;
}
int nr = sqrt(static_cast<double>(n)) + 1;
//test for all x y combination
for (int x = 1; x < nr; x++)
{
for (int y = 1; y < nr; y++)
{
//test three different algorithm possible
int k = 4 * x * x + y * y;
if (k <= n && (k % 12 == 1 || k % 12 == 5))
{
prime[k] = !prime[k];
}
k = 3 * x * x + y * y;
if (k <= n && k % 12 == 7)
{
prime[k] = !prime[k];
}
if (x > y)
{
k = 3 * x * x - y * y;
if (k <= n && k % 12 == 11)
{
prime[k] = !prime[k];
}
}
}
}
//get rid of multiple of prime k^2
//start at 5 to skip useless loop with 2 and 3
for (int i = 5; i < nr; i++)
{
if (prime[i])
{
for (int j = i * i; j <= n; j += i)
{
prime[j] = false; //Exception thrown: write access violation.
}
}
}
//base prime number in list
if (n >= 2)
{
cout << "2\n";
nbr++;
}
if (n >= 3)
{
cout << "3\n";
nbr++;
}
//print all prime number in list
for (int i = 5; i < n + 1; i++)
{
if (prime[i])
{
nbr++;
cout << i << "\n";
}
}
cout << "Il y a " << nbr << " nombre premier entre 0 et " << n << "\n";
delete[] prime;
}
Executing the above version of that function should deliver the results you seek.
See it live here

Range max sum query using sparse table

I Implemented range max sum query using sparse Table ,I Know more efficient approach would be using segment trees.
What I have tried:
I am calculating the max sum in the range (i,2^j-1) for all possible value of i and j and storing them in a table
where i is the index and j denotes the power of 2 (2^j denotes the length of segment from i for which we are calculating max sum)
Now using the above table we can answer the queries
Input:
3
-1 2 3
1
1 2
expected output:
2
actual output:
"wrong answer(garbage value)"
we actually have to tell the max contiguous sum in a given query
Link to the ques spoj gss1
Please help:
#include<iostream>
#include<vector>
#include<algorithm>
#include<climits>
using namespace std;
const int k = 16;
const int N = 1e5;
const int ZERO = 0; // ZERO + x = x + ZERO = x (for any x)
long long table[N][k + 1]; // k + 1 because we need to access table[r][k]
long long Arr[N];
int main()
{
int n, L, R, q;
cin >> n; // array size
for(int i = 0; i < n; i++)
cin >> Arr[i];
// build Sparse Table
for(int i = 0; i < n; i++)
table[i][0] = Arr[i];
for(int j = 1; j <= k; j++) {
for(int i = 0; i <= n - (1 << j); i++)
//table[i][j] = table[i][j - 1] + table[i + (1 << (j - 1))][j - 1];
table[i][j] = max(table[i][j-1],max(table[i+(1<<(j-1))][j-1],table[i+(1<<(j-1))][j-1]+table[i][j-1]));
}
cin >> q; // number of queries
for(int i = 0; i < q; i++) {
cin >> L >> R; // boundaries of next query, 0-indexed
long long int answer = LLONG_MIN;
for(int j = k; j >= 0; j--) {
if(L + (1 << j) - 1 <= R) {
answer = max(answer,answer + table[L][j]);
L += 1 << j; // instead of having L', we increment L directly
}
}
cout << answer << endl;
}
return 0;
}
link to the question Spoj Gss1

Output not correct for my C++ program

So, I have the following problem:
From the file tabl.in a number n will be read (n<=50).
After that a square array with n rows and n columns will be read; all the numbers in the array will be composed by a maximum of 2 digits each.
Shown in the file tabl.out, the modulo between the sum of numbers found on the second diagonal of the array and 10, if the sum is palindrome (true=1, false=0), and the arithmetic mean of elements situated below of the main diagonal.
Will be writing functions for:
reading the array
calculation of the operation sum of secondary diagonal%10
checking if the previous result it is palindrome
calculation of the arithmetic mean below main diagonal
Example:
tabl.in:
4
5 8 2 12
1 0 3 16
1 2 1 11
5 7 2 19
tabl.out:
2 1 3
where
(12+3+2+5)%10 = 22%10 = 2
22 is palindrome = 1
1+2+2+1+7+5 = 18, 18/6=3
My code so far is:
#include <fstream>
using namespace std;
ifstream fin("tabl.in");
ofstream fout("tabl.out");
void readn(int Arr[][51], int n) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
fin >> Arr[i][j];
}
int sumsec(int Arr[][51], int n) {
int s = 0;
float r;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
r = s % 10;
return r;
}
void pald(int Arr[][51], int n) {
int s = 0, pal = 0;
for (int i = 1; i < n; i++)
s = s + Arr[i][n - i + 1];
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == s)
fout << "1 ";
else
fout << "0 ";
}
int ambmd(int Arr[][51], int n) {
int s = 0, k;
float ame;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i - 1; j++) {
s = s + Arr[i][j];
k++;
}
}
ame = s / k;
return ame;
}
int main() {
int Arr[51][51], n;
float r, ame;
fin >> n;
readn(Arr, n);
r = sumsec(Arr, n);
fout << r << " ";
pald(Arr, n);
ame = ambmd(Arr, n);
fout << ame;
}
But I have an issue with the palindrome() function: my output file will have 2 0 3 written to it for the given array from the example, instead of 2 1 3. What am I doing wrong?
Your pald function would work, if you compute s the same way as you do in sumsec and if s would still contain the sum, after you compute pal.
In your case, while (s != 0) {...}, followed by if (pal == s) {...} could be re-written as if (pal == 0), which is clearly not the intended solution. Just save your sum before computing pal, then compare with the saved sum.
Also, change your loop condition for computing s to for (int i = 1; i <= n; i++).
int s = 0, pal = 0, sum = 0;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
sum = s;
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == sum)
fout << "1 ";
else
fout << "0 ";
You should also consider the various comments for code improvements, like not re-computing the sum in the pald function.

C++ Sub sequence Exercise

I was assigned a "project" where I should create a C++ program to find the largest possible sum of two sub sequences. The user inputs N (array length), K (length of each sub sequence) and N numbers representing the array. The two sub sequences can touch but can't override each other e.g. 1 5 20 20 20 15 10 1 1 1 should output 90 ((5+20+20)+(20+15_10)) and not 115 ((20+20+20)+(20+20+15)).
My code until now is:
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N, K, MaxN;
cin >> N;
cin >> K;
int Pi[N];
MaxN = N - K + 1;
int Word[MaxN];
int MaxSum;
for(int nn=0; nn<N; nn++) {
cin >> Pi[nn];
}
for(int y=0;y<MaxN;y++) {
Word[y] = 0;
}
for(int j=0; j<MaxN; j++) {
for(int l=0; l<K; l++) {
Word[j] = Word[j] + Pi[j+l];
}
}
sort(Word, Word + MaxN);
MaxSum = Word[MaxN-2] + Word[MaxN-1];
cout << MaxSum;
return 0;
}
Which is correct only in the case where the 2 sub sequences don't interfere with each other e.g. in an array such as 2 4 15 12 10 1 1 20 4 10 which outputs 71.
Thank you all in advance.
This is solution:
precalculate prefixes and suffixes
iterate end of the first subarray
iterate begin of the second subarray, but start from the end of first sub. ar. + 1
we have sum of numbers on interval from 0 to *end* = prefix[end], but we are interested only in interval [end - k, k], so simply subtract prefix[end] - prefix[end - k - 1]
[0 .. end-k-1, end-k .. end]
The same approach for the second subarray: sum2 = suffix[begin] - suffix[begin + i + 1]
then compare with the previous answer
So we just brute-force all possible sub-arrays which not intersect and find the max their sum
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int N,K,MaxN;
cin >> N;
cin >> K;
int Pi[N];
MaxN=N-K+1;
int Word[MaxN];
int MaxSum;
for(int nn=0;nn<N;nn++){
cin >> Pi[nn];
}
int prefix[N];
int sufix[N];
for (int i = 0; i < N; i++) {
prefix[i] = sufix[i] = 0;
}
for (int i = 0; i < N; i++) {
if (i == 0)
prefix[i] = Pi[i];
else
prefix[i] = Pi[i] + prefix[i - 1];
}
for (int i = N - 1; i >= 0; i--) {
if (i == N - 1)
sufix[i] = Pi[i];
else
sufix[i] = Pi[i] + sufix[i + 1];
}
int ans = 0;
for (int i = K - 1; i < MaxN; i++) {
for (int j = i + 1; j < MaxN; j++) {
int x = prefix[i] - (i - K >= 0 ? prefix[i - K] : 0);
int y = sufix[j] - (j + K < N ? sufix[j + K] : 0);
ans = max(ans, x + y);
}
}
cout << ans;
return 0;
}

C++ Recursion Character Printing

Edit: Corrected Code (Thanks for the answers and help!)
#include <iostream>
using namespace std;
int arr1(const int n,int i, int j){
if(j != 0) {
/* if(i == 2*n ){
cout<<"\n";
--j;}*/
if((i <= (n-j) || (i >= (j+n)) && i <2*n)){
cout<<" ";
}
if(i < n && i > (n-j)){
cout<<"\\";
}
if( i > n && i < (n+j)){
cout<<"/";
}
if(i == n){
cout<<"v";
}
if(i == 2*n ){
cout<<"\n";
i = 0;
--j;}
return arr1(n,++i,j);
}
return 0;
}
int main(){
int c;
cin>>c;
arr1(c,1,c);
}
I'm trying to write a program that takes an integer n and recursively prints an arrowhead type design
n=1 -> v
n=2 -> \v/
v
n=3 -> \\v//
\v/
v
etc:
This is my code so far, yet I keep getting a segmentation error. I assume this because of an infinite loop somewhere in the code.
#include <iostream>
using namespace std;
int arr1(const int n, int i, int j)
{
if (j != 0)
{
if (i == 2 * n)
{
cout << "\n";
--j;
}
if (i <= n - j || i >= j + n)
{
cout << "_";
}
if (i < j)
{
cout << "\\";
}
if (i > j)
{
cout << "/";
}
if (i == n)
{
cout << "v";
}
return arr1(n, ++i, j);
}
return 0;
}
int main()
{
int c;
cin >> c;
arr1(c, 1, c);
return 0;
}
The decision of whether to recurse comes down to the value of j -- but you receive j from main, and never modify it afterwards unless i==2*n, passing the exact same value when it calls itself recursively. So yes, that leads to infinite recursion (assuming you originally pass a non-zero value for j, anyway).
You logic in the arr1 function is wrong, for example, if c=3 in the beginning,
the i, j, n values in arr1 will be in each iteration
i = 1 j = 3 n = 3
i = 2 j = 3 n = 3
i = 3 j = 3 n = 3
i = 4 j = 3 n = 3
i = 5 j = 3 n = 3
i = 6 j = 2 n = 3
i = 7 j = 2 n = 3
i = 8 j = 2 n = 3
i = 9 j = 2 n = 3
i = 10 j = 2 n = 3
i = 11 j = 2 n = 3
...
then it goes for ever until stack overflow.