This code should count the number of prime numbers based on user input. If user input is 10, then I should get 4. However, I only get 0. Why does the second loop not run?
#include<stdio.h>
#include<math.h>
int main()
{
int N;
scanf("%d", &N);
int numprime;
numprime = 0;
int P=1;
for (P; P<N; P++)
{
if (P%2==0)
continue;
int e = sqrt(P);
for (int j=3;j<=e;j+=2)
{
if (P%j!=0)
{
numprime = numprime + 1;
}
else
{
continue;
}
}
}
printf("%d", numprime);
}
Why does the second loop not run?
It does run, once, when e is equal to 3 (that means that this happens when P is equal to 9), in the case that input is 10.
Change this:
for (P; P<N; P++)
to this:
for (; P <= N; P++)
since the first part had no effect, and more importantly, you want to check all N numbers, so the stop condition had to be modified.
Then, you need to change this:
for (int j=3;j<=e;j+=2)
to this:
for(int j = 2; j <= e; j+=2)
in order to check for prime numbers, are suggested here.
Furthermore, you need to change this:
if (P % j != 0)
to this:
if (P % j == 0)
since P is actually a prime number when the condition is met.
Moreover, you need to get rid of this:
if(P % 2 == 0) continue;
since for example 2 is a prime number, but it meets this condition, and will not be taken into account!
From your code, it looks like P starts out as 1, so e is sqrt(1), which is again 1, and j is 3. Therefore, j is not less than or equal to 1, and the test at the top of the inner loop fails, so the loop doesn't execute the first time through. This pattern continues for each iteration of the outer loop until P becomes large enough that sqrt(P) is greater than 3, at which point the inner loop does run.
Related
Let me start by saying that I am a beginner. I'm trying to define a function that calculates/identifies the largest prime number below an input value. However, my current approach is flawed.
I've tried implementing a nested for loop. Generating numbers from one below the input down to 1, subsequently running each number through the second loop so as to identify whether or not it is prime. If it is prime (if count == 2) the function is supposed to return the number that was generated by the first loop (n)
I've been permitted to assume that the input will be a positive integer greater than 2.
int prime(int maximum)
{
int i, j, count = 0, n;
for (i = 1; i < maximum; i++) {
n = maximum - i; /* generating number below input value*/
for (j = 1; j <= maximum; j++) {
if (n % j == 0) { /* testing whether or not it is prime */
count++;
}
} if(count == 2) {
break;
}
}
return n;
}
I'd expect an input of 10 to produce an output of 7, an input of 30 to produce an output of 29 and an input of 100 to produce an output of 97.
However, the function is currently generating an output of 1 - consistently.
The code is not generating any error messages
note: This is my first time utilising this platform, my most sincere apologies if the formatting of my question is incorrect
The problem is you are not resetting the count to 0 in the outer loop.
This will solve the problem.
Adding further,
There are some other optimizations that can be done in the code too.
You need not run the inner loop maximum times, only n times will be sufficient as you are checking whether n is prime or not.
You can put the break condition inside the inner for loop for those whose count has crossed 2 to avoid further iterations.
int prime(int maximum)
{
int i, j, count = 0, n;
for (i = 1; i < maximum; i++) {
count = 0; # <----- Reset it to 0.
n = maximum - i; /* generating number below input value*/
for (j = 1; j <= n; j++) {
if (n % j == 0) { /* testing whether or not it is prime */
count++;
if(count > 2) # to avoid further iterations as we know, this number is not prime.
break;
}
} if(count == 2) {
break;
}
}
return n;
}
int dup_chk(int a[], int length)
{
int i = length;
while (i > 0)
{
i--;
int j = i -1;
while (j >= 0)
{
if (a[i] == a[j])
{
return 1;
}
j--;
}
}
return 0;
}
So what I think I know is the following:
line 1 is just 1.
First while loop is N+1.
i--; is N times since its inside the first while loop.
j = i -1; is also N.
Second while loop is (N+1)N = N^2+N since its a while loop within a while loop
if statement: ???
j--; is N(N) = N^2
return 0; is 1
I'm really new to calculating the time complexity of algorithms so I'm not even sure if what I think I know is completely right.
But what is messing with me is the if statement, I do not know how to calculate that (and what if there is an else after it as well?)
EDIT: The grand total is equal to 3/2N^2 + 5/2N+3
I understand that this function is O(N^2) but don't quite get how the grand total was calculated.
Usually such accurate analysis of time complexity is not required. It suffices to know it in terms of Big-O. However, I did some calculations for my own curiosity.
If your concern is just a worst case analysis to obtain the time complexity, consider an array with only unique elements. In such a scenario:
The return 1 statement never executes. The inner while loop executes N(N-1)/2 times (summation i-1 from 1 to N), and three things happen - the while condition is checked (and evaluates to true), the if condition is checked (and evaluates to false) and the variable j is decremented. Therefore, the number of operations is 3N(N-1)/2.
The outer while loop executes N times, and there are three statements apart from the condition check - i is decremented, j is assigned, and the inner while condition fails N times. That is 4N more operations.
Outside all loops, there are three more statements. Initialisation of i, the while condition fails once, and then the return statement. Add 3 more to our tally.
3/2N2 - 3/2N + 4N + 3.
That's 3/2N2 + 5/2N + 3. There is your 'grand total'.
To repeat myself, this calculation is completely unnecessary for all practical purposes.
Maybe this can help you understand what goes wrong in your code. I have added some printout that make easier to understand what happens in your code. I think this should be sufficient to find your error
int dup_chk(int a[], int length)
{
int j = 0;
int i = length;
char stringa[30];
printf("Before first while loop j = %d and i = %d \n", j, i);
while (i > 0)
{
i--;
j = i - 1;
printf("\tIn first while loop j = %d and i = %d\n", j, i);
while (j >= 0)
{
printf("\t\tIn second while loop j = %d and i = %d\n", j, i);
if (a[i] == a[j])
{
printf("\t\tIn if statment j = %d and i = %d\n", j, i);
return 1;
}
j--;
printf("\t\tEnd of second while loop j = %d and i = %d\n", j, i);
}
}
printf("After first while loop j = %d and i = %d \n", j, i);
printf("Press any key to finish the program and close the window\n");
return 0;
}
I should also recomend to debug your code understand what goes on better.
The if check is executed as many times as the inner while loop iterates.
The return 1 is by definition only executed once max. It appears you assume there are no duplicates in the input (ie. worst case), in which case the return 1 statement never executes.
You'll eventually get a feel for what parts of the code you can ignore, so you won't need to calculate this "grand total", and just realize there are two nested loops that each traverse the array - ie. O(N^2).
int dup_chk(int a[], int length)
{
int i = length;
while (i > 0) // Outer loop
{
i--;
int j = i -1;
while (j >= 0) // Inner loop
{
if (a[i] == a[j])
{
return 1;
}
j--;
}
}
return 0;
}
The above program is exactly your code with two comments I took the liberty to add.
Let's consider the worst case scenario (because that's what everyone cares / is worried about). If you notice carefully, you will observe that for every value of i, the Inner loop executes i - 1 times. Thus if your Outer loop executes n times, the Inner loop will execute n * (n - 1) times in total (i.e. n - 1 times for each value of n).
n * (n - 1) yields n^2 - n in general algebra. Now, n^2 increases in leaps and bounds (as compared to n) as you go on increasing the value of n. Asymptotic notation let's us consider the factor which will have the greatest impact on the number of steps to be executed. Thus, we can ignore n and say that this program has a worst case running time of O(n^2).
That's the beauty and simplicity of the Big-O notation. - Quoting Jonathan Leffler from the comments above.
Thorough evaluation:
This program has a special feature: it terminates if a pair (a[I], a[J]) of equal values is found. Assume that we know I and J (we will see later what if there is no such pair).
The outer loop is executed for all I <= i < L, hence L-I times. Each time, the inner loop is executed for all 0 <= j < i, hence i times, except for the last pass (i = I): we have J <= j < I hence I-J iterations.
We assume that the "cost" of a loop is of the form a N + b, where a is the cost of a single iteration and b some constant overhead.
Now for the inner loop, which is run L-I times with decreasing numbers of iterations, using the "triangular numbers" formula, the cost is
a (L-1 + L-2 + ... I+1 + I-J) + b (L - I) = a ((L-1)L/2 - I(I+1)/2 + I-J) + b (L-I)
to which we add the cost of the outer loop to get
a ((L-1)L/2 - I(I+1)/2 + I-J) + b (L-I) + c
(where b is a different constant than above).
In general, this function is quadratic in L, but if a pair is found quickly (say I = L-3), it becomes linear; in the best case (I = L-1,J = L-2), it is even the constant a + b + c.
The worst case occurs when the pair is found last (I = 1, J = 0), which is virtually equivalent to no pair found. Then we have
a (L-1)L/2 + b (L - 1) + c
obviously O(L²).
so my requirements are
REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
PROMISES
The return value is 1 if n == 1.
If n > 1, the return value is 1 if a[0] ... a[n-1] form
an arithmetic sequence.
PROMISES
Otherwise, the return value is 0.
my function so far is
int is_arith_seq(const int *a, int n)
{
assert(n >= 1);
if (n == 1)
return 1;
int i;
int initaldif = a[1]-a[0];
int currentdif,result;
for (i=0;i<n;i++)
{
currentdif = a[i+1]-a[i];
if(initaldif!=currentdif)
return 0;
}
return 1;
}
My code does not work,as I am completely stuck now, what can I do to correct it.
If array has n elements your for loop will cause a segmentation fault. It goes all the way to n-1 but you are accessing a[i+1]. a[n] is out of bounds. Modify like this :
for (i = 0; i < n - 1; i++)
{
currentdif = a[i+1]-a[i];
if (initaldif != currentdif)
return 0;
}
Problem is here
currentdif = a[i+1]-a[i];
What do you think will happen to this code during n-1 th iteration?
i = n-1 + 1 = n
Therefore the function either returns 1 if n=1 or returns 0 due to the error!
Off-by-one errors are one of the most common programming mistakes. A good way to quickly track many of these down is to look at the very first and last iterations of your loops.
Your intent is that your loop computes the differences
a[1]-a[0] a[2]-a[1] ... a[n-1]-a[n-2]
The first iteration has i=0 and computes a[1]-a[0], and the last iteration has i=n-1 and computes a[n]-a[n-1]. Whoops, that's wrong! Need to adjust the loop.
Your arithmetic sequence test should set the initialdif as you have done, but then predict what the next element is throughout the sequence. If any term fails, the string of numbers is not an arithmetic sequence:
int initaldif = a[1]-a[0];
for (i = 2; i < n; i++)
if (a[i] != a[i-1] + initaldif)
return 0;
return 1;
Here is a link to the problem I'm trying to solve: http://acm.timus.ru/problem.aspx?space=1&num=1086
Here is my approach:
#include <stdio.h>
#include <math.h>
int main()
{
int n, i, m, p;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &m);
p = find_prime(m);
printf("%d\n", p);
}
return 0;
}
int find_prime(int a)
{
int i, p = 1, t, prime[15000], j;
prime[0] = 2;
for(i = 0; i < a; )
{
if(p == 2)
{
p++;
}else
{
p = p + 1;
}
t = 0;
for(j = 0; prime[j] <= sqrt(p); j++)
{
if(p%prime[j] == 0 && p != 2)
{
t = 1;
break;
}
}
if(t != 1)
{
i++;
prime[i] = p;
}
}
return p;
}
I know the algorithm is fine and it produces the correct answer. But I always get "Time Limit Exceeded". I can't get the runtime download to 2 seconds. It's always equal to 2.031 seconds. I have tried few other approaches, for example, I iterated through all the numbers until I found the mth prime number, I tried skipping the even integers greater than 2 but I still get 2.031 seconds.
What should I do?
Your buffer for prime numbers doesn't need to be a local variable that's recalculated every time.
You can try to memoize by storing the buffer in the global scope and using a global counter to keep track of how many primes you have already calculated until now and which number was the maximum number requested.
If the next number that's requested from you is smaller than the previous maximum, you should fall back to the corresponding pre-calculated number. If the next number is larger than the previous maximum, make it the new maximum - and also try to start calculating from where you last left off.
Remove
if(p == 2)
{
p++;
}else
{
p = p + 1;
}
and replace it with
p++
as I understand it,
the problem is to find the next prime greater that the sum of all the prior input numbers.
That means there are certain expectations.
1) the sum of the prior input numbers is available in find_prime().
2) for simplification, the last found prime number is available in find_prime().
Neither of these expectations are implemented.
Then there is that 60 thousand byte array on the stack in find_prime().
Suggest moving that to a file global position and including a 'static' modifier.
move the prior sum of inputs to a file global location, so it is always available.
for overall speed,
calculate all the primes in the array as a first thing, thereby filling the array with prime values. then
1) add new input to sum,
2) index into array using sum.
3) return value found in array.
/*
Program to calculate trip and plan flights
*/
#define TRIP 6
#define DEST 1
#include <stdio.h>
int main(void)
{
int type_num, cont_num, index, i, dest_code, trip_num, row, col;
int travelint[TRIP][DEST]= {{0}};
printf("Please enter the number of trips:");
scanf("%d", &trip_num);
for (i=0; i < trip_num ; i++)
{
printf("Please enter destination code:");
scanf("%d", &dest_code);
cont_num = dest_code / 10000;
type_num = dest_code/1000 - cont_num*10;
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
dest_code = travelint[i][0];
else
printf("Invalid code\n");
}
printf("%2d", travelint[0][0]);
return 0;
}
I'm having trouble printing from the array I'm not sure if I'm either printing it wrong or that the number isn't actually being assign in the array. I'm still having trouble with the concept of assign values from input into the array..
An array dimension with only one element in the row is a trifle pointless. You normally only use dimensions with more than one element in each row.
Additionally, you are never assigning to the travelint array - only reading from it. So, since it is initialized to all zeroes, all you will ever see when you print it are zeroes.
You probably simply need to change this:
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
dest_code = travelint[i][0];
to:
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
travelint[i][0] = dest_code;
This assigns to travelint.
To print out a full 2D array, you would normally use:
for (int j = 0; j < TRIP; j++)
{
for (int k = 0; k < DEST; k++)
printf("Trip[%d][%d] = %d\n", j, k, travelint[j][k]);
}
Given that the inner loop will be executed just once per iteration of the outer loop (in your example, where DEST is 1), you could simplify that to:
for (int j = 0; j < TRIP; j++)
{
printf("Trip[%d][%d] = %d\n", j, 0, travelint[j][0]);
}
You should validate the trip_num after the user enters it. You should check that scanf() actually converted a value; if the user types 'A', then your program will go into a rapid loop printing out "Invalid code" every time. Always check that inputs succeed. In theory, you should also check that outputs succeed, but that rule is more often ignored than honoured. Also, if the user is nasty and types 200, then your program is not going to be happy after the user enters the sixth trip destination. It should be between 0 and TRIP (inclusive), of course. You should handle the degenerate (0) case properly, of course. And the printing loop becomes:
for (int j = 0; j < trip_num; j++)
{
printf("Trip[%d][%d] = %d\n", j, 0, travelint[j][0]);
}