int inc = swap ? 1 : -1;
for(int j=j1; j!=j2; j+=inc){
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
}
I found out that in some case, this for loop infinitely. When looking with a debugger, j does reach j2 but for some reason continue to loop.
I then tried to add a break if j == j2 inside the loop (technically j-inc since j is incremented as it enter into the loop again)
for(int j=j1; j!=j2; j+=inc){
if (j - inc == j2)
{
qDebug() << "break =================================";
break;
}
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
}
And doing that indeed solved the problem (and the "break" is indeed printed), but it doesn't really make any sense ?
Why does the first for loop act this way ?
Edit :
I'm iterating over a part of a list (between values j1 and 2). The iteration can go both side depending of the swap parameter (boolean). If j reach one of the end of the list, it continue on the other side (for example if j1=5, j2=1 and the list size is 7, j will take the following values : 5 6 0 1)
It should be noted that I'm only guessing about what happens here...
My guess is that j becomes equal to j2 inside the loop, by one of the assignments. But then the increase j += inc happens and j is no longer equal to j2 when the loop condition is checked.
Generally speaking, a for loop is equivalent to a while loop:
for (a; b; c)
d
is equivalent to
{
a;
while (b)
{
d;
c;
}
}
That means your first loop is equal to (with extra comments added)
{
int j = j1;
while (j != j2)
{
if(j < 0)
j = curve2->controlPoints()->size()-1;
if(j >= curve2->controlPoints()->size())
j = 0;
curve->addControlPoint(curve2->controlPoint(j)->pos(), curve2->controlPoint(j)->triangle());
// At this point `j == j2`, so the loop condition is false
// BUT then you do
j += inc;
// Here `j != j2` again, and the loop condition is true and will continue
}
}
Perhaps your loop condition should be j - inc == j2 instead?
Related
#include<bits/stdc++.h>
using namespace std;
int main() {
int a[5] = {1, 2, 3, 4, 5};
int k;
cin >> k;
int i, j, ct;
i = 0;
j = 4;
ct = 0;
while (i < j) {
if (a[i] + a[j] > k) {
--j;
}
else if (a[i] + a[j] < k) {
++i;
}
else {
ct++;
}
}
cout << ct;
}
Trying to print the total number of pairs ct in a given sorted array whose sum is equal to k, k is any given input. But the problem is, value of i changes once and value of j remains same. why? hence i < j is always true and loop runs to infinite hence no certain value of ct comes out. Where is the problem in this code?
There are many issues in your code, but the reason for it being stuck is pretty simple. You have three cases
larger
smaller
equal
If you reach the equal case, then you do not change i nor j so it will always go to case equal, forever.
Let's say k=5:
In the while loop (i>j) or (0<4):
First case (1+5>k): true
j = 3
the while loop (0<3):
Second case (1+4 = 5)
ct = 1
the while loop (0<3):
Third case (1+4 = 5)
ct = 2
the while loop (0<3):
Fourth case (1+4 = 5)
ct = 3
the while loop (0<3):
Fifth case (1+4 = 5)
ct = 4
So you end up with an infinite loop that never ends because neither the i or j value is being updated
i.e the "else{} " is being infinitely run because the loop condition still holds.
This is code -
for (i = 1; i<=1000000 ; i++ ) {
for ( j = 1; j<= 1000000; j++ ) {
for ( k = 1; k<= 1000000; k++ ) {
if (i % j == k && j%k == 0)
count++;
}
}
}
or is it better to reduce any % operation that goes upto million times in any programme ??
edit- i am sorry ,
initialized by 0, let say i = 1 ok!
now, if i reduce the third loop as #darshan's answer then both the first
&& second loop can run upto N times
and also it calculating % , n*n times. ex- 2021 mod 2022 , then 2021 mod 2023..........and so on
so my question is- % modulus is twice (and maybe more) as heavy as compared to +, - so there's any other logic can be implemented here ?? which is alternate for this question. and gives the same answer as this logic will give..
Thank you so much for knowledgeable comments & help-
Question is:
3 integers (A,B,C) is considered to be special if it satisfies the
following properties for a given integer N :
A mod B=C
B mod C=0
1≤A,B,C≤N
I'm so curious if there is any other smartest solution which can greatly reduces time complexity.
A much Efficient code will be the below one , but I think it can be optimized much more.
First of all modulo (%) operator is quite expensive so try to avoid it on a large scale
for(i = 0; i<=1000000 ; i++ )
for( j = 0; j<= 1000000; j++ )
{
a = i%j;
for( k = 0; k <= j; k++ )
if (a == k && j%k == 0)
count++;
}
We placed a = i%j in second loop because there is no need for it to be calculated every time k changes as it is independent of k and for the condition j%k == 0 to be true , k should be <= j hence change looping restrictions
First of all, your code has undefined behavior due to division by zero: when k is zero then j%k is undefined, so I assume that all your loops should start with 1 and not 0.
Usually the % and the / operators are much slower to execute than any other operation. It is possible to get rid of most invocations of the % operators in your code by several simple steps.
First, look at the if line:
if (i % j == k && j%k == 0)
The i % j == k has a very strict constrain over k which plays into your hands. It means that it is pointless to iterate k at all, since there is only one value of k that passes this condition.
for (i = 1; i<=1000000 ; i++ ) {
for ( j = 1; j<= 1000000; j++ ) {
k = i % j;
// Constrain k to the range of the original loop.
if (k <= 1000000 && k > 0 && j%k == 0)
count++;
}
}
To get rid of "i % j" switch the loop. This change is possible since this code is affected only by which combinations of i,j are tested, not in the order in which they are introduced.
for ( j = 1; j<= 1000000; j++ ) {
for (i = 1; i<=1000000 ; i++ ) {
k = i % j;
// Constrain k to the range of the original loop.
if (k <= 1000000 && k > 0 && j%k == 0)
count++;
}
}
Here it is easy to observe how k behaves, and use that in order to iterate on k directly without iterating on i and so getting rid of i%j. k iterates from 1 to j-1 and then does it again and again. So all we have to do is to iterate over k directly in the loop of i. Note that i%j for j == 1 is always 0, and since k==0 does not pass the condition of the if we can safely start with j=2, skipping 1:
for ( j = 2; j<= 1000000; j++ ) {
for (i = 1, k=1; i<=1000000 ; i++, k++ ) {
if (k == j)
k = 0;
// Constrain k to the range of the original loop.
if (k <= 1000000 && k > 0 && j%k == 0)
count++;
}
}
This is still a waste to run j%k repeatedly for the same values of j,k (remember that k repeats several times in the inner loop). For example, for j=3 the values of i and k go {1,1}, {2,2}, {3,0}, {4,1}, {5,2},{6,0},..., {n*3, 0}, {n*3+1, 1}, {n*3+2, 2},... (for any value of n in the range 0 < n <= (1000000-2)/3).
The values beyond n= floor((1000000-2)/3)== 333332 are tricky - let's have a look. For this value of n, i=333332*3=999996 and k=0, so the last iteration of {i,k}: {n*3,0},{n*3+1,1},{n*3+2, 2} becomes {999996, 0}, {999997, 1}, {999998, 2}. You don't really need to iterate over all these values of n since each of them does exactly the same thing. All you have to do is to run it only once and multiply by the number of valid n values (which is 999996+1 in this case - adding 1 to include n=0).
Since that did not cover all elements, you need to continue the remainder of the values: {999999, 0}, {1000000, 1}. Notice that unlike other iterations, there is no third value, since it would set i out-of-range.
for (int j = 2; j<= 1000000; j++ ) {
if (j % 1000 == 0) std::cout << std::setprecision(2) << (double)j*100/1000000 << "% \r" << std::flush;
int innerCount = 0;
for (int k=1; k<j ; k++ ) {
if (j%k == 0)
innerCount++;
}
int innerLoopRepeats = 1000000/j;
count += innerCount * innerLoopRepeats;
// complete the remainder:
for (int k=1, i= j * innerLoopRepeats+1; i <= 1000000 ; k++, i++ ) {
if (j%k == 0)
count++;
}
}
This is still extremely slow, but at least it completes in less than a day.
It is possible to have a further speed up by using an important property of divisibility.
Consider the first inner loop (it's almost the same for the second inner loop),
and notice that it does a lot of redundant work, and does it expensively.
Namely, if j%k==0, it means that k divides j and that there is pairK such that pairK*k==j.
It is trivial to calculate the pair of k: pairK=j/k.
Obviously, for k > sqrt(j) there is pairK < sqrt(j). This implies that any k > sqrt(j) can be extracted simply
by scanning all k < sqrt(j). This feature lets you loop over only a square root of all interesting values of k.
By searching only for sqrt(j) values gives a huge performance boost, and the whole program can finish in seconds.
Here is a view of the second inner loop:
// complete the remainder:
for (int k=1, i= j * innerLoopRepeats+1; i <= 1000000 && k*k <= j; k++, i++ ) {
if (j%k == 0)
{
count++;
int pairI = j * innerLoopRepeats + j / k;
if (pairI != i && pairI <= 1000000) {
count++;
}
}
}
The first inner loop has to go over a similar transformation.
Just reorder indexation and calculate A based on constraints:
void findAllSpecial(int N, void (*f)(int A, int B, int C))
{
// 1 ≤ A,B,C ≤ N
for (int C = 1; C < N; ++C) {
// B mod C = 0
for (int B = C; B < N; B += C) {
// A mod B = C
for (int A = C; A < N; A += B) {
f(A, B, C);
}
}
}
}
No divisions not useless if just for loops and adding operations.
Below is the obvious optimization:
The 3rd loop with 'k' is really not needed as there is already a many to One mapping from (I,j) -> k
What I understand from the code is that you want to calculate the number of (i,j) pairs such that the (i%j) is a factor of j. Is this correct or am I missing something?
I wrote some code I wrote to print the powers of 2 up to like 39 or 40 idk but it dm. Anyway, I wrote it and rather than run the code and it not working because of a logic error, i ran the code and found that it works, and then spotted some logic errors showing that the code shouldn't work. Here is the code:
#include <iostream>
using namespace std;
int main()
{
int i = 1;
int j = 1;
int k = 1;
while (i < 40)
{
while (k < i)
{
j = j * 2;
cout << j <<"\n";
k++;
}
i++;
}
}
The output of this code is the powers of 2 up to about 2^40.
Why it shouldn't work: the second while loop shouldn't run because k = 1 and i = 1 so (k < i) is false. Also after each time the second while loop is completed, j and k should be reset to 1 in order for the logic to work however I don't resent them.
Can someone please explain why although all these logic errors, the code still works?
Also I tried this in python and got the same result.
Initial values:
i=1, k=1, j=1
Then we check i < 40. True. Then we check k < i. False. Then we increment i. Now:
i=2, k=1, j=1
Check i < 40. True. Check k < i. True. j=j*2 sets j=2. Print 2. Increment k. Check if k < i. False. Increment i. Now:
i=3, k=2, j=2
Following this, the inner loop executes at most once for every iteration of the outer loop. k < i is true until the k++ line, and then becomes true again at the i++ line.
I'm not sure whether I understand why there are nested loops here in the first place. It could be replaced with
while (i < 40) {
j = j * 2;
count << j << "\n";
i++
}
What was the intention of k?
I have a situation where I am using openMP for the Xeon Phi Coprocessor, and I have an opportunity to parallelize an "embarrassingly parallel" double for loop.
However, the for loop is looping through the upper triangle (including the diagonal):
for (int i = 0; i < n; i++)
// access some arrays with the value of i
for (int j = i; j < n; j++)
// do some stuff with the values of j and i
So, I've got the total size of the loop,
for (int q = 0; q < ((n*n - n)/2)+n; q++)
// Do stuff
But where I am struggling is:
How do I calculate i and j from q? Is it possible?
In the meantime, I'm just doing the full matrix, calculating i and j from there, and only doing my stuff when j >= i...but that still leaves a hefty amount of thread overhead.
If I restate your problem, to find i and j from q, you need the greatest i such that
q >= i*n - (i-1)*i/2
to define j as
j = i + (q - i*n - (i-1)*i/2)
If you have such a greatest i, then
(i+1)*n - i*(i+1)/2 > q >= i*n - (i-1)*i/2
n-i > (q - i*n - (i-1)*i/2) >= 0
n > j = i + (q - i*n - (i-1)*i/2) >= i
Here is a first iterative method to find i:
for (i = 0; q >= i*n - (i-1)*i/2; ++i);
i = i-1;
If you iterate over q, the computation of i is likely to exploit the iterative process.
A second method could use sqrt since
i*n - i²/2 + i/2 ~ q
i²/2 - i(n+1/2) + q ~ 0
delta = (n+0.5)² - 2q
i ~ (n+0.5) - sqrt(delta)
i could be defined as floor((n+0.5) - sqrt((n+0.5)² - 2q))
OK, this isn't an answer as far as I can tell. But, it is a workaround (for now).
I was thinking about it, and creating an array (or corresponding pointer), a[(n*n + n)/2 + n][2], and reading in the corresponding i and j values in my calling code, and passing this to my function would allow for the speed up.
You can make your loop to iterate as it is iterating on the whole matrix.
And just to keep track on your current line and each time you are entering a new line increment the index with the value of that line.
Then: i == line and j == i%n.
See this code:
int main() {
int n = 10;
int line = 0;
for (int i=0; i<n*n; i++){
if (i%n == 0 && i!=0){
line++;
i += line;
cout << endl;
}
cout << "("<<line<<","<<i%n<<")";
}
return 0;
}
Running Example
int s_dynamic(int n,int k) {
int maxj = n-k;
int *arr = new int[maxj+1];
for (int i = 0; i <= maxj; ++i)
arr[i] = 1;
for (int i = 1; i <= k; ++i)
for(int j = 1; j <= maxj; ++j)
arr[j] += i*arr[j-1];
return arr[maxj];
}
Here's my attempt at determining Stirling numbers using Dynamic Programming.
It is defined as follows:
S(n,k) = S(n-1,k-1) + k S(n-1,k), if 1 < k < n
S(n,k) = 1, if k=1 ou k=n
Seems ok, right? Except when I run my unit test...
partitioningTest ..\src\Test.cpp:44 3025 == s_dynamic(9,3) expected: 3025 but was: 4414
Can anyone see what I'm doing wrong?
Thanks!
BTW, here's the recursive solution:
int s_recursive(int n,int k) {
if (k == 1 || k == n)
return 1;
return s_recursive(n-1,k-1) + k*s_recursive(n-1,k);
}
Found the bug.
You already computed your dynamic array of Stirlings numbers for k=1 (S(n,1)=1 for all n).
You should start computing S(n,2) - that is:
for (int i = 2; i <= k; ++i) //i=2, not 1
for(int j = 1; j <= maxj; ++j)
arr[j] += i*arr[j-1];
Your approach is just fine, except you seem to have made a simple indexing error. If you think about what indexes i and j represent, and what the inner loop transforms arr[j] to, you'll see it easy enough (I lie, it took me a good half hour to figure out what was what :)).
From what I can decode, i represents the value k during calculations, and arr[j] is transformed from S(i+j, i-1) to S(i+1+j, i). The topmost for loop that initializes arr sets it up as S(1+j, 1). According to these loops, the calculations look just fine. Except for one thing: The very first i loop assumes that arr[j] contains S(0+j, 0), and so it is where your problem lies. If you change the starting value of i from 1 to 2, all should be OK (you may need an if or two for edge cases). The initial i=2 will transform arr[j] from S(1+j, 1) to S(2+j, 2), and the rest of the transformations will be just fine.
Alternatively, you could have initialized arr[j] to S(0+j, 0) if it were defined, but unfortunately, Stirling's numbers are undefined at k=0.
EDIT: Apparently I was wrong in my last comment. If you initialize arr to {1, 0, 0, ...}, you can leave starting value of i as 1. For this, you use the initial values S(0, 0)=1, and S(n, 0)=0, n>0 instead.