I've got this pseudocode:
COMPARE-EXCHANGE(A,i,j)
if A[i] > A[j]
exchange A[i] with A[j]
INSERTION-SORT(A)
for j = 2 to A.length
for i = j-1 downto 1
COMPARE-EXCHANGE(A,i,i+1)
I would interpret it as:
void insertSort( )
{
int tmp;
for( int j = 2 ; j < MAX ; ++j )
{
for( int i = j - 1 ; i > 0 ; --i )
{
if( unsortedArr[i] > unsortedArr[i + 1] )
{
tmp = unsortedArr[i];
unsortedArr[i] = unsortedArr[i + 1];
unsortedArr[i + 1] = tmp;
}
}
}
}
However that would skip unsortedArr[0].
Which means it won't work.
Changing the 2nd for to:
for( int i = j - 1 ; i >= 0 ; --i )
Will make it run as intended.
Is there a mistake in the pseudocode or was my first try of interpreting it wrong?
However that would skip unsortedArr[0]. Which means it won't work.
It is nearly universal for pseudocode to number array elements from 1, not from zero, as in C/C++
Changing the 2nd for to:
for( int i = j - 1 ; i >= 0 ; --i )
Will make it run as intended.
That is not enough: you also need to start j at 1 rather than 2 in the outer loop.
Also note that the C++ standard library offers a std::swap function which takes care of exchanging the elements of the array for you:
if( unsortedArr[i] > unsortedArr[i + 1] )
{
std::swap(unsortedArr[i], unsortedArr[i+1]);
}
I think your pseudo code is assuming that arrays start with index one [1] -- where in C & C++ they start at zero [0].
I'm guessing that the pseudocode is using 1-based indexing, rather than the 0-based indexing that C++ uses.
Related
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 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
Okay so when my professor was going over it in class it seemed quite simple, but when I got to my homework I became confused. This is a homework example.
for (int i = 0; i < n; i++) // I know this runs at T(n)
for (int j = n - 1; j >= i; j--)
cout << i << " " << j << endl;
Here's an example I understand
for(int i=0; i<n-1; i++) {
for(int j=i+1; j<n; j++) {
1 Simple statement
}
For that example I just plugged in 0, 1, and 2. For 0, it ran for n-1, at 1 for n-2 and at 2 n-3. So I think that for the homework example if I plugged in 0 it would run for n+1 since j has to be greater than or equal to i which is 0. If it's not obvious, i'm pretty confused. If anyone could show me how to solve it, that'd make my day. Thanks guys.
Let's dig into the functon. Let's pick some numbers.
say, n = 5
So our code looks like this (magical pseudo-code uses INCLUSIVE loops, not that it's too important)
(1)for i = 0 to 4
(2)for j = 4 to i
(3)print i j
next
next
So this is a matter of preference, but usually loops are assumed to cost 1 simple statement per execution (comparison, and incrementation). So we'll assume that statements (1) and (2) have a cost of 2. Statement (3) has a cost of 1.
Now to determine T(n).
Our outer loop for i = 0 to 4 runs exactly n times.
Our inner loop for j = 4 to i . . . We'll dig in there for a minute.
For our example with n = 5 loop (2) will execute like so
j = 4; i = 0; j = 4; i = 1; j = 4; i = 2; j = 4; i = 3 j = 4; i = 4;
j = 3; i = 0; j = 3; i = 1; j = 3; i = 2; j = 3; i = 3;
j = 2; i = 0; j = 2; i = 1; j = 2; i = 2;
j = 1; i = 0; j = 1; i = 1;
j = 0; i = 0;
So it makes this kind of pyramid shape, where we do 1 less iteration each time. This particular example ran 5 + 4 + 3 + 2 + 1 = 15 times.
We can write this down as SUM(i; i = 0 to n).
Which we know from precalc: = (1/2)(n)(n+1).
And (3) will execute the exact same number of times as that inner loop since it's the only statement. So our total runtime is going to be. . .
COST(1) + COST(2) + COST(3)
(2)(n) + 2(1/2)(n)(n+1) + (1/2)(n)(n+1)
We can clean this up to be
(3/2)(n)(n+1) + 2n = T(n).
That said, this assumes that loops cost 2 and the statement costs 1. It's usually more meaningful to say loops cost 0 and statements cost 1. If that were the case, T(n) = (1/2)(n)(n+1).
And givent that T(n), we know T(n) is O(n^2).
Hope this helps!
It's not that hard.
3 examples for single loops:
for (int i = 0; i < n; i++)
for(int i = 0; i < n-1; i++)
for(int i = 2; i < n-1; i++)
The first loop executs it's content n times (i=0,1,2,3,...,n-1).
The same way, the second loop is just n-1 times.
The third would be n-3 because it starts not at 0, but 2
(and if n is less than 3, ie. n-3<0, it won't execute at all)
In a nested loop like
for(int i = 0; i < n-1; i++) {
for(int j = 0; j < n; j++) {
//something
}
}
For each pass of the outer loop, the whole inner loop is executed, ie. you can multiply both single loop counts to get how often "something" is executed in total. Here, it is (n-1) * n = n^2 - n.
If the inner loop depends on the value of the outer loop, it gets a bit more complicated:
for(int i = 0; i < n-1; i++) {
for(int j = i+1; j < n; j++) {
//something
}
}
The inner loop alone is n - (i+1) times, the outer one n-1 times (with i going from 0 to n-2).
While there are "proper" ways to calculate this, a bit logical thinking is often easier, as you did already:
i-value => inner-loop-time
0 => n-1
1 => n-2
...
n-2 => n - (n-2+1) = 1
So you´ll need the sum 1+2+3+...+(n-1).
For calculating sums from 1 to x, following formula helps:
sum[1...x] = x*(x+1)/2
So, the sum from 1 to n-1 is
sum[1...n-1] = (n-1)*(n-1+1)/2 = (n^2 - n)/2
and that´s the solution for the loops above (your second code).
About the first code:
Outer loop: n
Inner loop: From n-1 down to i included, or the other way from i up to <=n-1,
or from i up to <n, that´s n-i times
i >= innerloop
0 n
1 n-1
2 n-2
...
n-1 1
...and the sum from 1 to n is (n^2 + n)/2.
One easy way to investigate a problem is to model it and look at resulting data.
In your case, the question is: how many iterations does the inner loop depending on the the value of the outer loop variable?
let n = 10 in [0..n-1] |> List.map (fun x -> x,n-1-x);;
The 1 line above is the model showing what happens. If you now look at the resulting output, you will quickly notice something...
val it : (int * int) list =
[(0, 9); (1, 8); (2, 7); (3, 6); (4, 5); (5, 4); (6, 3); (7, 2); (8, 1);
(9, 0)]
What is it you notice? For a given N you run the outer loop N times - this is trivial. Now we need to sum up the second numbers and we have the solution:
sum(N-1..0) = sum(N-1..1) = N * (N-1) / 2.
So the total count of cout calls is N * (N-1) / 2.
Another easy way to achieve the same is to modify your function a bit:
int count(int n) {
int c = 0;
<outer for loop>
<inner for loop>
c++;
return c;
}
I am using this following code to find 10001th prime number but it is not running.
I am using devc++, but when I run this code, a blank screen comes up.
This is my Code:
#include<iostream>
#include<conio.h>
using namespace std;
int prime(int a)
{
int p=0;
for(int j=2;j<=a/2,p<=0;j++)
{
if(a%j==0)
{
p++;
}
}
if(p==0)
{
return 1;
}
else
return 0;
}
int main()
{
int i,c=0;
for(i=2;c<=10001;i++)
{
if(prime(1))
{
c++;
}
}
cout<<i;
return 0;
}
point 1:
you are passing if(prime(1)) argument 1 every time change this line to
if(prime(i))
point 2:
Change this line
for(int j=2;j<=a/2,p<=0;j++)
To
for(int j=2;(j<=a/2 && p<=0);j++)
Point 3:
Change this line
cout<<i;
To
cout<<i-1; // as at the end of `for` loop it will increment to `1` so print `i-1`.
First of all , I think you meant
if(prime(i))
instead of
if(prime(1))
Secondly, there are many gaps in this code .. First, you can verify if the number a divides by j with j taking a maximum value of sqrt(a) (using math.h library) , it would be faster when working with higher values.
Another thing, you said this is a code for finding the 10001th prime number not the number of prime numbers until 10001 and cout<<i; in the end doesn't make any sense, I think you meant cout<<c;
Let's look at each problem.
First, you need to use
if( prime(i) )
instead of
if( prime(1) )
I believe that was a typo on your part.
Second, as i is incremented after the for loop, you need to change
cout << i;
to
cout << i-1;
Third, the comma operator only executes the expression at the end. What you need here is &&. So change
for(int j = 2 ; j <= a/2 , p <= 0 ; j++)
to
for(int j = 2 ; j <= a/2 && p <= 0 ; j++ )
For more info on the comma operator, see Uses of C comma operator
Lastly, change
for( i = 2 ; c <= 10001 ; i++ )
to
for( i = 2 ; c < 10001 ; i++ )
Otherwise, you will get the 10002th prime number.
These should fix your problem.
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.