Hi I need help finding the complexity of this algorithm.
Could you please answer the complexity line by line not just the final result?
The algorithm is the following one:
int algorithm(int x)
{
int y = 1;
while (y <= x-1)
{
int z = y*2;
while (z <= x)
{
int w = 1;
while (w <= z)
{
w++;
}
z++;
}
y++;
}
}
Any help would be appreciated!
Thanks
int algorithm(int x)
{
int y = 1;
while (y <= x-1) // <<< loop 1
{
int z = y*2;
while (z <= x) // <<< loop 2
int w = 1;
while (w <= z) // <<< loop 3
{
w++;
}
z++;
}
y++;
}
}
Let's break it down.
Loop 1: you go around (x-1) times: we call this O(x). Easy.
Loop 2: We start Z with 2*y, so 2, 4, 6, ... From there we go until x. Let's add them up:
sum((x-2) + (x-4) + (x-6) + ... + (x - x)) =
x * x / 2 - 2 * (1+2+3+...+x/2) =
x * x / 2 - 2 * (x/2)*(x/2+1) / 2 ~
x * x / 2 - x * x / 4 =
x * x / 4
= O(x^2)
Now the innermost loop: it goes from w = 1 to w = z; so it loops z times. And we know that
z = 2, 4, 6, ... x
So the innermost loop adds something of the order of x (x/2... same thing).
Combining the O(x) of loop 3 with the O(x^2) of loop 2 (which included the effect of the first loop) we conclude the "algorithm" is of order x^3. To verify, we can modify your code:
#include <stdio.h>
int algorithm(int x)
{
int c = 0;
int y = 1;
while (y <= x-1)
{
int z = y*2;
while (z <= x)
{
int w = 1;
while (w <= z)
{
c++; // count complexity
w++;
}
z++;
}
y++;
}
return c;
}
int main(void) {
int ii;
for(ii = 200; ii <= 400; ii+=10) {
printf("%d %d\n", ii, algorithm(ii));
}
}
The output is:
200 1338350
210 1549030
220 1780735
230 2034465
240 2311220
250 2612000
260 2937805
270 3289635
280 3668490
290 4075370
300 4511275
310 4977205
320 5474160
330 6003140
340 6565145
350 7161175
360 7792230
370 8459310
380 9163415
390 9905545
400 10686700
Plotting this on a lin-log plot, you get a pretty straight line.
When you take the ratio of algorithm(400) / algorithm(300), you get 2.369. And when you take (400/300)^3, the answer is 2.370. I think that is close enough to be convincing.
Following the formal steps below (I hope you're comfortable with Sigma Notation), you'll be able to obtain the exact order of growth of your algorithm:
Related
Thats one wrong with my code and I dont have any idea about this wrong
Please be attention to that I can just use from for and while and if
The question is:
Write a code that gets the natural number n then tries to find x,y,z (natural numbers) in some way:
n=x+y+z
Then if the following is true of x, y, z, print these three numbers in the output, otherwise print the Not Found statement:
x = y ^ 2 + z ^ 2
(x or y or z) = i + (i + 1) + (i + 2)
Where i is a natural number.
Be it. Then if the following is true of x, y, z, print these three numbers in the output, otherwise print the Not Found statement:
x = y ^ 2 + z ^ 2
(x or y or z) = i + (i + 1) + (i + 2)
Where i is a natural number.
(Note that the input n is such that the int variable is sufficient and does not overflow.)
Input
The input contains a line in which a natural number is given.
Output
The output must either consist of three lines, each integer x, y, and z, respectively, from small to large, or the expression Not Found.
Example
Sample Input 1
48
Copy
Sample output 1
2 6 40
Copy
Sample input 2
5
Copy
Sample output 2
Not found
#include <stdio.h>
int main() {
int z,x,y,n;
scanf("%u",&n);
for(y=1;y<(n/3);y++) {
for(z=y;z<=((2*n)/3);z++) {
(x=(n-(y+z)));
if(x==((y*y)+(z*z))) {
if(((((y-3)%3)!=0)||(y==3))&&((((z-3)%3)!=0)||(z==3))&&((((x-3)%3)!=0)||(x==3))) {
continue;
}
printf("%d\n",y);
printf("%d\n",z);
printf("%d",x); return 0;
}
}
}
printf("Not found");
return 0;
}
This syntax (if(x==((yy)+(zz))) is wrong. It should be if (x == ((y*y)+(z*z))) or use pow function from math.h library like this (if(x == (pow(y,2)+pow(z,2)))
int main()
{
int z, x, y, n;
scanf("%u", &n);
for (y = 1; y < (n / 3); y++)
{
for (z = y; z <= ((2 * n) / 3); z++)
{
(x = (n - (y + z)));
if (x == ((y*y)+(z*z)))
{
if (((((y - 3) % 3) != 0) || (y == 3)) && ((((z - 3) % 3) != 0) || (z == 3)) && ((((x - 3) % 3) != 0) || (x == 3)))
{
continue;
}
printf("%d\n", y);
printf("%d\n", z);
printf("%d", x);
return 0;
}
}
}
printf("Not found");
return 0;
}
I want to write a function that prints all possible patterns like in the examples below. In every case, we must start in the top left of a 3x3 array. It's similar to the patterns to unlock mobile phones, except the line can't go diagonally and must pass through every box.
1--->2--->3 1--->2--->3
| |
v v
8<---7 4 or 6<---5<---4
| ^ | |
v | v v
9 6<---5 7--->8--->9
I started by writing a code where [0][0] was assigned 1 then randomise the rest of the digits in the 2d array until 1[0] or 0 was equal to 2, and so forth. But I feel like this is making the problem even more difficult to solve.
Then tried to use recursion to call the makePattern function again and again until the array is changed; however, it changes all values in the array to 2 because of these lines of code:
int value = 2;
array[x][y] = value;
However, I don't how to loop this value so that it increases as the function is called again.
#include <stdio.h>
#include <stdlib.h>
#define ROW 3
#define COLUMN 3
int makePattern(int array[ROW][COLUMN], int x, int y);
int main(void) {
int x, y;
int count = 2;
int i, j;
int array[ROW][COLUMN] = {
{'1', '0', '0'},
{'0', '0', '0'},
{'0', '0', '0'},
};
makePattern(array, 0, 0);
for (i = 0; i < ROW; i++) {
for (j = 0; j < COLUMN; j++) {
printf("%d", array[i][j]);
}
printf("\n");
}
return 0;
}
int makePattern(int array[ROW][COLUMN], int x, int y) {
int value = 2;
array[x][y] = value;
for (value = 2; value < 9; value++) {
if (x + 1 < ROW && array[x+1][y] == '0') {
makePattern(array, x + 1, y);
}
if (x - 1 >= 0 && array[x - 1][y] == '0') {
makePattern(array, x - 1, y);
}
if (y + 1 < COLUMN && array[x][y + 1] == '0') {
makePattern(array, x, y + 1);
}
if (y - 1 >= 0 && array[x][y - 1] == '0') {
makePattern(array, x, y - 1);
}
value++;
}
}
You're on the right track here in that you're using a 3x3 matrix to keep track of state (visited nodes and to store the path taken), x/y coordinates to represent the current location and spawning four recurse calls to handle the possible move directions (with bounds checks).
However, I'm not sure the loop running to 9 is going to work--this will spawn 36 recursive calls per frame. This might be workable in some implementations, but I think the easiest approach is to treat each frame as exploring one possible direction given an x/y coordinate pair, then backtracking (undoing the move) after all directions have been explored recursively from that square. Whenever we hit the last step, we know we've explored all of the squares and it's time to print the current solution path.
Here's code which achieves this and basically hardcodes the dimensions. An exercise would be to generalize the code to matrices of any size and return the path to separate printing from the traversal logic. I also opted to move state out of the main function.
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
static void print_unlock_patterns_r(int pad[3][3], int x, int y, int step) {
static int const directions[][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
pad[y][x] = 1 + step;
for (int i = 0; i < 4; i++) {
int xp = x + directions[i][0];
int yp = y + directions[i][1];
if (xp >= 0 && xp < 3 && yp >= 0 && yp < 3 && !pad[yp][xp]) {
print_unlock_patterns_r(pad, xp, yp, step + 1);
}
}
if (step == 8) {
for (int i = 0; i < 3; i++, puts("")) {
for (int j = 0; j < 3; printf("%d", pad[i][j++]));
}
puts("");
}
pad[y][x] = 0;
}
void print_unlock_patterns() {
int pad[3][3];
memset(pad, 0, sizeof(pad));
print_unlock_patterns_r(pad, 0, 0, 0);
}
int main(void) {
print_unlock_patterns();
return 0;
}
Output:
123
894
765
123
874
965
123
654
789
129
438
567
145
236
987
189
276
345
187
296
345
167
258
349
I'm supposed to write a program in C for school where I multiply by 4 but I can't get it to work. When I type 2 I get 20, when I type 3 it's 84, when I type 4 it's 340 and so on, why is that?
#include <stdio.h>
int multi(int i)
{
if (i == 1) {
return 4;
}
if (i == 0) {
return 0;
}
if (i > 1) {
return (multi(i-1)*4)+4;
}
}
int main()
{
int i;
printf("type a numer for multiplication by 4\n");
scanf("%d",&i);
printf("%d * 4 is %d\n",i, multi(i));
}
Multiplying X by Y is adding X Y number of times.
X * Y = X + X + X ...Y times
So change
return (multi(i-1)*4)+4;
to
return multi(i-1) + 4;
and it will work as intended for multiplication by 4.
However, if you want to raise X to the power of Y, you have to multiply X Y number of times.
X to the power of Y = X * X * X...Y times
In this case, there are a couple of more changes you have to make to your code which I leave to you as an exercise.
I have implemented this function:
double heron(double a)
{
double x = (a + 1) / 2;
while (x * x - a > 0.000001) {
x = 0.5 * (x + a / x);
}
return x;
}
This function is working as intended, however I would wish to improve it. It's supposed to use and endless while loop to check if something similar to x * x is a. a is the number the user should input.
So far I have no working function using that method...This is my miserably failed attempt:
double heron(double a)
{
double x = (a + 1) / 2;
while (x * x != a) {
x = 0.5 * (x + a / x);
}
return x;
}
This is my first post so if there is anything unclear or something I should add please let me know.
Failed attempt number 2:
double heron(double a)
{
double x = (a + 1) / 2;
while (1) {
if (x * x == a){
break;
} else {
x = 0.5 * (x + a / x);
}
}
return x;
}
Heron's formula
It's supposed to use and endless while loop to check if something similar to x * x is a
Problems:
Slow convergence
When the initial x is quite wrong, the improved |x - sqrt(a)| error may still be only half as big. Given the wide range of double, the may take hundreds of iterations to get close.
Ref: Heron's formula.
For a novel 1st estimation method: Fast inverse square root.
Overflow
x * x in x * x != a is prone to overflow. x != a/x affords a like test without that range problem. Should overflow occur, x may get "infected" with "infinity" or "not-a-number" and fail to achieve convergence.
Oscillations
Once x is "close" to sqrt(a) (within a factor of 2) , the error convergence is quadratic - the number of bits "right" doubles each iteration. This continues until x == a/x or, due to peculiarities of double math, x will endlessly oscillate between two values as will the quotient.
Getting in this oscillation causes OP's loop to not terminate
Putting this together, with a test harness, demonstrates adequate convergence.
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
double rand_finite_double(void) {
union {
double d;
unsigned char uc[sizeof(double)];
} u;
do {
for (unsigned i = 0; i < sizeof u.uc; i++) {
u.uc[i] = (unsigned char) rand();
}
} while (!isfinite(u.d));
return u.d;
}
double sqrt_heron(double a) {
double x = (a + 1) / 2;
double x_previous = -1.0;
for (int i = 0; i < 1000; i++) {
double quotient = a / x;
if (x == quotient || x == x_previous) {
if (x == quotient) {
return x;
}
return ((x + x_previous) / 2);
}
x_previous = x;
x = 0.5 * (x + quotient);
}
// As this code is (should) never be reached, the `for(i)`
// loop "safety" net code is not needed.
assert(0);
}
double test_heron(double xx) {
double x0 = sqrt(xx);
double x1 = sqrt_heron(xx);
if (x0 != x1) {
double delta = fabs(x1 - x0);
double err = delta / x0;
static double emax = 0.0;
if (err > emax) {
emax = err;
printf(" %-24.17e %-24.17e %-24.17e %-24.17e\n", xx, x0, x1, err);
fflush(stdout);
}
}
return 0;
}
int main(void) {
for (int i = 0; i < 100000000; i++) {
test_heron(fabs(rand_finite_double()));
}
return 0;
}
Improvements
sqrt_heron(0.0) works.
Change code for a better initial guess.
double sqrt_heron(double a) {
if (a > 0.0 && a <= DBL_MAX) {
// Better initial guess - halve the exponent of `a`
// Could possible use bit inspection if `double` format known.
int expo;
double significand = frexp(a, &expo);
double x = ldexp(significand, expo / 2);
double x_previous = -1.0;
for (int i = 0; i < 8; i++) { // Notice limit moved from 1000 down to < 10
double quotient = a / x;
if (x == quotient) {
return x;
}
if (x == x_previous) {
return (0.5 * (x + x_previous));
}
x_previous = x;
x = 0.5 * (x + quotient);
}
assert(0);
}
if (a >= 0.0) return a;
assert(0); // invalid argument.
}
Can anyone help me out with the pollard rho implementation? I have implemented this in C. It's working fine for numbers upto 10 digits but it's not able to handle greater numbers.
Please help me out to improve it to carry out factorization of numbers upto 18 digits . My code is this:
#include<stdio.h>
#include<math.h>
int gcd(int a, int b)
{
if(b==0) return a ;
else
return(gcd(b,a%b)) ;
}
long long int mod(long long int a , long long int b , long long int n )
{
long long int x=1 , y=a ;
while(b>0)
{
if(b%2==1) x = ((x%n)*(y%n))%n ;
y = ((y%n)*(y%n))%n ;
b/=2 ;
}
return x%n ;
}
int isprimes(long long int u)
{
if(u==3)
return 1 ;
int a = 2 , i ;
long long int k , t = 0 , r , p ;
k = u-1 ;
while(k%2==0)
{ k/=2 ; t++ ; }
while(a<=3) /*der are no strong pseudoprimes common in base 2 and base 3*/
{
r = mod(a,k,u) ;
for(i = 1 ; i<=t ; i++)
{
p = ((r%u)*(r%u))%u ;
if((p==1)&&(r!=1)&&(r!=(u-1)))
{ return 0 ; }
r = p ;
}
if(p!=1)
return 0 ;
else
a++ ;
}
if(a==4)
return 1 ;
}
long long int pol(long long int u)
{
long long int x = 2 , k , i , a , y , c , s;
int d = 1 ;
k = 2 ;
i = 1 ;
y = x ;
a = u ;
if(isprimes(u)==1)
{
return 1;
}
c=-1 ;
s = 2 ;
while(1)
{
i++;
x=((x%u)*(x%u)-1)% u ;
d = gcd(abs(y-x),u) ;
if(d!=1&&d!=u)
{ printf("%d ",d);
while(a%d==0) { a=a/d; }
x = 2 ;
k = 2 ;
i = 1 ;
y = x ;
if(a==1)
{ return 0 ; }
if(isprimes(a)!=0)
{ return a ; }
u=a ;
}
if(i==k)
{y = x ; k*=2 ; c = x ;} /*floyd cycle detection*/
if(c==x)
{ x = ++s ; }
}
return ;
}
int main()
{
long long int t ;
long long int i , n , j , k , a , b , u ;
while(scanf("%lld",&n)&&n!=0)
{ u = n ; k = 0 ;
while(u%2==0)
{ u/=2 ; k = 1 ; }
if(k==1) printf("2 ") ;
if(u!=1)
t = pol(u) ;
if(u!=1)
{
if(t==1)
{ printf("%lld",u) ; }
else
if(t!=0)
{ printf("%lld",t) ; }
}
printf("\n");
}
return 0;
}
sorry for the long code ..... I am a new coder.
When you're multiplying two numbers modulo m, the intermediate product can become nearly m^2. So if you use a 64-bit unsigned integer type, the maximal modulus it can handle is 2^32, if the modulus is larger, overflow may happen. It will be rare when the modulus is only slightly larger, but that makes it only less obvious, you cannot rely on being lucky if the modulus allows the possibility of overflow.
You can gain a larger range by a factor of two if you choose a representative of the residue class modulo m of absolute value at most m/2 or something equivalent:
uint64_t mod_mul(uint64_t x, uint64_t y, uint64_t m)
{
int neg = 0;
// if x is too large, choose m-x and note that we need one negation for that at the end
if (x > m/2) {
x = m - x;
neg = !neg;
}
// if y is too large, choose m-y and note that we need one negation for that at the end
if (y > m/2) {
y = m - y;
neg = !neg;
}
uint64_t prod = (x * y) % m;
// if we had negated _one_ factor, and the product isn't 0 (mod m), negate
if (neg && prod) {
prod = m - prod;
}
return prod;
}
So that would allow moduli of up to 2^33 with a 64-bit unsigned type. Not a big step.
The recommended solution to the problem is the use of a big-integer library, for example GMP is available as a distribution package on most if not all Linux distros, and also (relatively) easily installable on Windows.
If that is not an option (really, are you sure?), you can get it to work for larger moduli (up to 2^63 for an unsigned 64-bit integer type) using Russian peasant multiplication:
x * y = 2 * (x * (y/2)) + (x * (y % 2))
so for the calculation, you only need that 2*(m-1) doesn't overflow.
uint64_t mod_mult(uint64_t x, uint64_t y, uint64_t m)
{
if (y == 0) return 0;
if (y == 1) return x % m;
uint64_t temp = mod_mult(x,y/2,m);
temp = (2*temp) % m;
if (y % 2 == 1) {
temp = (temp + x) % m;
}
return temp;
}
Note however that this algorithm needs O(log y) steps, so it's rather slow in practice. For smaller m you can speed it up, if 2^k*(m-1) doesn't overflow, you can proceed in steps of k bits instead of single bits (x*y = ((x * (y >> k)) << k) + (x * (y & ((1 << k)-1)))), which is a good improvement if your moduli are never larger than 48 or 56 bits, say.
Using that variant of modular multiplication, your algorithm will work for larger numbers (but it will be significantly slower). You can also try test for the size of the modulus and/or the factors to determine which method to use, if m < 2^32 or x < (2^64-1)/y, the simple (x * y) % m will do.
You can try this C implementation of Pollard Rho :
unsigned long long pollard_rho(const unsigned long long N) {
// Require : a composite number N, not a square.
// Ensure : res is a non-trivial factor of N.
// Option : define a timeout, define a rand function.
static const int timeout = 18;
static unsigned long long rand_val = 2994439072U;
rand_val = (rand_val * 1025416097U + 286824428U) % 4294967291LLU;
unsigned long long res = 1, a, b, c, i = 0, j = 1, x = 1, y = 1 + rand_val % (N - 1);
for (; res == 1; ++i) {
if (i == j) {
if (j >> timeout)
break;
j <<= 1;
x = y;
}
a = y, b = y;
for (y = 0; a; a & 1 ? b >= N - y ? y -= N : 0, y += b : 0, a >>= 1, (c = b) >= N - b ? c -= N : 0, b += c);
y = (1 + y) % N;
for (a = N, b = y > x ? y - x : x - y; (a %= b) && (b %= a););
res = a | b;
}
return res;
}
Otherwise there is a pure C quadratic sieve which factors numbers from 0 to 300-bit.