nested for loop optimisation - c++

I have this expression
for (size_t i = 0; i < expression.size(); i++){
for (size_t j = i + 1; j < expression.size(); j++){
result += (expression.at(j) - expression.at(i));
}
result += (g - expression.at(i));
}
return result;
in the vector expression we have for example [1,2,3]. I am trying to get something like:
f1=[(2-1)+(3-1)]
r1 = g-1
h1 = r1+f1
f2=[3-2]
r2 = g-2
h2 = r2+f2
f3 = 0
r3 = g-3
h3 = r3+f3
then h1+h2+h3
What i am doing right now is in Θ(n^2). Is there a way to make it faster even without for loops?

Addition is commutative and associative so the operations can be reordered and grouped without changing the final result. (Note: not taking into account possible overflows in the intermediate calculations, which may be affected by the order and grouping of operations.)
In pseudo-code with n = expression.size() and x[k] = expression.at(k) the original code can be broken down as follows, with the intermediate results indicated in comments.
a = b = c = d = 0
for i = 0 to (n-1)
for j = (i+1) to (n-1)
a += x[j]
// == x[i+1] + x[i+2] + ... x[n-1]
// a == 0 * x[0] + 1 * x[1] + 2 * x[2] + 3 * x[3] + ... + (n-1) * x[n-1]
for i = 0 to (n-1)
for j = (i+1) to (n-1)
b += x[i];
// == (n-i-1) * x[i]
// b == (n-1) * x[0] + (n-2) * x[1] + ... + 2 * x[n-3] + 1 * x[n-2]
for i = 0 to (n-1)
c += g
// c == n * g
for i = 0 to (n-1)
d += expression.at(i))
// d == x[0] + x[1] + ... + x[n-1]
result = c + a - b - d
= n * g
+ (0 - (n-1) - 1) * x[0]
+ (1 - (n-2) - 1) * x[1]
+ ...
+ ((n-2) - 1 - 1) * x[n-2]
+ ((n-1) - 0 - 1) * x[n-1]
The latter result can be calculated directly from that formula, with one single O(n) loop.

Related

Why is C++ not changing my code's numbers' condition according to pow (-1,i)?

I have C++ code here:
#include <iostream>
#include <cmath>
#include <time.h>
using namespace std;
int main()
{
double n,x;
cin>>n>>x;
double b=1,c=0.0;
for (int i=1;i<=n;i++){
x=pow(x,i);
x=x*pow((-1),(i+1));
cout<<x<<endl;
b=i;
c=c+x/b;
}
cout<<c<<endl;
return 0;
}
I am creating this to calculate x^1-x^2/2+x^3/3-.....+(-1)^(n-1)*(x^n)/n. The user inputs n. The problem appears to be in this line: x=x*pow((-1),(i+1));.
I am creating this to calculate x^1 - x^2/2 + x^3/3 - ... + (-1)^(n-1)*(x^n)/n.
That seems to be the Maclaurin series of ln(1 + x), but it's not what the posted code evaluates, though:
for (int i=1;i<=n;i++)
{
x = pow(x,i);
// ^ This is updated at each iteration! It should be const.
x = x * pow((-1),(i+1));
// ^^^^^^^^^^^^^^^ Please don't (see later).
b=i;
c=c+x/b;
// ^ Okish, but why not use i directly?
}
At the very least, a variable different from x should be introduced to store the results of the powers.
The use of pow((-1),(i+1)) to generate the simple sequence {1, -1, 1, -1, ...} is also questionable, if not prone to rounding errors. I'll show two different ways to accomplish the same task.
// Evaluates the Mclaurin series of ln(1 + x) using n terms.
// Noting that (e.g. with n == 4):
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
// p(4) = x - x*x/2 + x*x*x/3 - x*x*x*x/4
// p(4) = k(1) -x*k(1)/2 + x*x*x/3 - x*x*x*x/4 k(1) = x
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 - x*x*x*x/4 k(2) = -x*k(1)
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 -x*k(3)/4 k(3) = -x*k(2)
// Preconditions: n >= 1 and -1 < x <= 1
double fn(int n, double x)
{
double k{ x };
double sum{ x };
for (int i{ 2 }; i <= n; ++i)
{
k *= -x;
sum += k / i;
}
return sum;
}
Note that, in the interval of convergence, abs(k / i) tends to zero, while outside it grows. Eventually, due to the limited precision of floating-point types like double, sum += k/i won't change the value of sum.
Another approach may be based on Horner's rule.
// Evaluates the Mclaurin series of ln(1 + x) using n terms.
// Applying Horner's rule:
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
// = x*(1 + x*(-1/2 + x*(1/3 + x*(-1/4))))
// = x*(1 + x*(-1/2 + x*( 1/3 + x*k(4) ))) k(4) = 1/4
// = x*(1 + x*( -1/2 + x*k(3) )) k(3) = 1/3 + x*k(4)
// = x*( 1 + x*k(2) ) k(2) = -1/2 + x*k(3)
// = x * k(1) k(1) = 1 + x*k(2)
// Preconditions: n >= 1 and -1 < x <= 1
double fn(int n, double x)
{
double sign{ n % 2 == 0? -1.0 : 1.0 };
double k{ sign / n };
while ( --n > 0 )
{
sign = -sign;
k = sign / n + x * k;
}
return k * x;
}

Number sequence program speed

I have this number sequence - xm = y.xm-1 + z (mod 20 000).
These are the restrictions:
1 ≤ x < 20 000,
0 ≤ y, z ≤ 9,
1 ≤ N ≤ 2 000 000 00
And here is my [code][1].
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
double k =0;
int x,y,z;
unsigned long long n;
int solve()
{
int result = 0;
int prevX = x;
for(unsigned long long i =1; i<n; i++)
{
if(result<20000)
{
result = y * prevX+z;
prevX = result;
}
else
{
result = y * prevX+z;
result = result % 20000;
prevX = result;
}
}
return result;
}
int main()
{
int tests =0;
cin >> tests;
cin.ignore();
while(tests--)
{
scanf("%d %d %d %Ld", &x, &y, &z, &n);
int result = solve();
cout << result;
}
}
Example input:
1
2 3 4 10
Example output:
18730
Details:
1 on the first row is the number of input test.
2 3 4 10 - x,y,z, N;
The judging system that I'm using is giving me a time limit error. So my program is slow.
Is there any way to predict this number sequence, elimanating most of the cycles?
Your solution is linear, because you have a loop from 0 to N. You can do logarithmic instead.
You can get to the equation empirically, with a simple experiment, just plug in a number, like m = 4. Let's ignore the modulo part for the moment because we can just do this on the final number (see for example https://en.wikipedia.org/wiki/Modular_arithmetic#Integers_modulo_n).
x[4] = y * x[3] + z
= y * (y * x[2] + z) + z
= y^2 * x[2] + y * z + z
= y^2 * (y * x[1] + z) + y * z + z
= y^3 * x[1] + y^2 * z + y * z + z
So you can easily get the rule, if you don't, start with m = 5. It is:
x[m] = y^(m-1) * x[1] + y^(m-2) * z + ... + y^0 * z
= y^(m-1) * x[1] + z * (y^(m-2) + ... + y^0)
Observe, that this is a geometric series, i.e.
x[m] = y^(m-1) * x[1] + z * (y^(m-1) - 1) / (y - 1) mod 20000
So what remains is to calculate y^(m-1), which you can do in log m easily.
In all steps be aware of the modulo rules! I.e., if you calculate y * y mod 20000, calculate (y mod 20000) * (y mod 20000) mod 20000 instead.
Example
Let's take z = 10, y = 11, x[1] = 3, then you have
x[2] = 11 * 3 + 10 mod 20000 = 43
x[3] = 11 * 43 + 10 mod 20000 = 483
x[4] = 11 * 1850 + 10 mod 20000 = 5323
x[5] = 11 * 460 + 10 mod 20000 = 58563 mod 20000 = 18563
Or you can get it directly:
x[5] = 11^4 * 3 + 10 * (11^4 - 1) / (11 - 1) mod 20000
= 14641 * 3 + 10 * (14641 - 1) / 10 mod 20000
= 43923 + 14640 mod 20000
= 644204 mod 20000
= 18563
Remember that if y == 19284, you calculate the fourth power as (y^2 mod 20000)^2 mod 20000 = 12656^2 mod 20000 = 14336 to ensure that you don't get overflows.

C++: Matrix Gauss Elimination Does Not Work: Using SINGLE DIMENSION Array to store elements

my codes does not work for Gauss Elimination for Matrix. The core code is ok, but it seems to be missing some final touch which I honestly dont know. Would be great if someone can point out the mistake.
Basically when I input a square 3x3 Matrix filled with 3s, I get back (3, 3, 3, 0, -3, -3, 0, 0, 3) but it should be (3, 3, 3, 0, 0, 0, 0, 0, 0)
n is number of rows of matrix and m is number of columns.
All elements of matrix are stored in a SINGLE DIMENSION array called entries[i]
My code below for GaussElimination basically starts with placing the row with the largest first element on the top row. Then after that I just delete the elements right below the top elements.
Matrix Matrix::GaussElim() const {
double maxEle;
int maxRow;
for (int i = 1; i <= m; i++) {
maxEle = fabs(entries[i-1]);
maxRow = i;
for (int k = i+1; k <= m; k++) {
if (fabs(entries[(k - 1) * n + i - 1]) > maxEle) {
maxEle = entries[(k - 1) * n + i - 1];
maxRow = k;
}
}
for (int a = 1; a <= m; a++) {
swap(entries[(i - 1) * m + a - 1], entries[(maxRow - 1) * m + a - 1]);
}
for (int b = i + 1; b <= n; b++) {
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
for (int d = i; d <= n; d++) {
if (i == d) {
entries[(b - 1) * m + d - 1] = 0;
}
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
}
}
}
}
Matrix Result(n, m, entries);
return Result;
}
For starters, I'd suggest to drop the habit of starting the loops at 1 instead of the more idiomatic 0, it would simplify all of the formulas.
That said, this statement
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
// ^^^
}
Looks suspicious. There should be a += (or a -=, depending on how you choose the sign of the pivot).
Another source of unexpected results is the way chosen to calculate the constant c:
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Even in case of partial pivoting, that value could be zero (or too small), due to the nature of the starting matrix, like in the posted example, or to numerical errors. In those cases, it would be preferable to just zero out all the remaining elements of the matrix.

Mathematical derivation of O(n^3) complexity for general three nested loops

Time complexity of nested for-loop goes into the mathematical derivation through summation of two loops O(n2) complexity.
I tried an exercise to derive how i can get O(n3) for the following examples of three nested loops.
Simple three nested loops.
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
print(i * k * j);
Summation is
= (n + n + n + .... + n) + (n + n + n + ... + n) + ... + (n + n + n + ... + n)
= n^2 + n^2 + .... + n^2
n times n^2 = O(n^3)
Three nested loops not run n times from beginning
for(int i = 1; i <= n; i++)
for(int j = i; j <= n; j++)
for(int k = j; k <= n; k++)
print(i *j * k)
The above is a pretty common form of nested loops and i believe the summation would be something as follows
= (n + (n -1) + (n -2) + (n - 3) + ... + 1)
+ ((n -1) + (n - 2) + (n - 3) +... + 1)
+ ((n -2) + (n -3) + (n - 4) + ... + 1)
+ ...
+ ((n - (n -2)) + 1)
= n(n - 1) /2 + (n-1) (n -2) / 2 + (n-2)(n-3)/2 + .... + 1
=
From here i am slightly not sure if my logic is correct . I believe
each of the above evaluate to a polynomial whose greatest value is n2 and as thats what we care about in time complexity, the above equation breaks down to.
= n^2 + n^2 + n^2 +... +n^2
= which is n times n^2 = O(n^3).
Is my assumption correct?
Three nested loops not run n times from end
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
for(int k = 1; k <= j; k++)
print(i *j * k)
If the above was a two nested loop the summation would have been 1 + 2 + 3 + 4 + ... + n. However, for the three nested occurence i am deducing it to be
= 1 + (1 + 2) + (1 + 2 + 3) + (1 + 2 + 3) + (1 + 2 + 3 + .... + n)
From here i am not sure how to derive O(n^3) or how the above summation would be further simplified.
Using the fact that:
1+2+3+...+i =i*(i+1)/2, the summation above can be written as:
1*(1+1)/2 + 2*(2+1)/2 + ... + n*(n+1)/2.
Obviously i*(i+1) > i^2, therefore:
1*(1+1)/2 + 2*(2+1)/2 + ... + n*(n+1)/2 > (1^2+...+ n^2)/2, as we know:
1^2+...+n^2 = n^3/3 + n^2/2 + n/6 (can prove this by induction).
Therefore, the original sum S is bigger than:
n^3/6 + n^2/4 + n/12, which is O(n^3).

How Can I Remove Pixel Noise from ofxKinect Video?

I'm looking for some help figuring out how to remove some low quality pixel noise from a video, that I'm obtaining from an xbox kinect via open frameworks. I'm running logic against "moving" parts of an image, to determine what color is moving the most, and use those regions to also detect the depth of which those pixels are moving. I'm attaching a photo to try to better explain my issue.
http://imago.bryanmoyles.com/xxw80
Of course I know code will be asked for, so I'll post what I have so far, but what I'm looking for more than anything else, is a good algorithm for smoothing out pixelated regions in a photo using C++
for(int y = 0; y < kinect.height; y += grid_size) {
for(int x = 0; x < kinect.width * 3; x += 3 * grid_size) {
unsigned int total_r = 0, total_b = 0, total_g = 0;
for(int r = 0; r < grid_size; r++) {
for(int c = 0; c < grid_size; c++) {
total_r += color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 0)];
total_b += color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 1)];
total_g += color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 2)];
}
}
unsigned char average_r = total_r / (grid_size * grid_size),
average_b = total_b / (grid_size * grid_size),
average_g = total_g / (grid_size * grid_size);
for(int r = 0; r < grid_size; r++) {
for(int c = 0; c < grid_size; c++) {
color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 0)] = average_r;
color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 1)] = average_b;
color_pixels[(y * kinect.width * 3 + r * kinect.width * 3) + (c * 3 + x + 2)] = average_g;
}
}
}
}
for(int y = 0; y < kinect.height; y++) {
for (int x = 0; x < kinect.width * 3; x += 3) {
int total_difference = abs(color_pixels[y * kinect.width * 3 + x + 0] - rgb[0])
+ abs(color_pixels[y * kinect.width * 3 + x + 1] - rgb[1])
+ abs(color_pixels[y * kinect.width * 3 + x + 2] - rgb[2]);
unsigned char defined_color;
if(total_difference < 40) {
defined_color = (unsigned char) 255;
} else {
defined_color = (unsigned char) 0;
}
color_pixels[y * kinect.width * 3 + x + 0] = defined_color;
color_pixels[y * kinect.width * 3 + x + 1] = defined_color;
color_pixels[y * kinect.width * 3 + x + 2] = defined_color;
}
}
Again, I'd like to reiterate that my code is not the problem, I'm simply posting it here so that you understand I'm not just asking blindly. What I really need, is some direction on how to smooth out pixelated images, so that my averages don't get messed up frame by frame by poor quality.
You can process your image from the camera with some methods from the ofxOpenCV addon. There you will have methods like blur, undistort, erode, etc. Its easy to setup, because its already an addon. Have a look at the openCvExample which should be packed with your openFrameworks. For more information on the mentioned methods, take a look here. If I understand your problem correctly, then a little blur on the image could fix your problem already.