Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 days ago.
Improve this question
Problem:
Generate a function who take a number x as argument and another number p as an argument, it then takes p number of prime no. on both left and right side and return the average of all those elements.
Attempt:
I wrote the following code: but I wanted to see if the time complexity could be reduced.
#include <stdio.h>
int is_prime(int n)
{
if (n == 1)
return 0;
if (n == 2 || n == 3)
return 1;
if (n % 2 == 0 || n % 3 == 0)
return 0;
for (int i = 5; i * i <= n; i = i + 6)
{
if (n % i == 0 || n % (i + 2) == 0)
return 0;
}
return 1;
}
double sum_of_primes(int x, int p)
{
int sum = 0;
int countls = 0;
int countrs = 0;
int count = 0;
if (is_prime(x))
{
sum = x;
count = 1;
}
int i = x - 1;
int j = x + 1;
while (countls < p)
{
if (is_prime(i))
{
sum += i;
countls++;
count++;
}
i--;
}
while (countrs < p)
{
if (is_prime(j))
{
sum += j;
countrs++;
count++;
}
j++;
}
return (double)sum / count;
}
int main()
{
int x, p;
scanf("%d %d", &x, &p);
printf("%f", sum_of_primes(x, p));
return 0;
}
see if the time complexity could be reduced.
That is a worthy goal after getting functionality correct.
is_prime(2147483647) returns 0, yet is a prime.
This is due to overflow in i * i <= n. Infinite loop when n = INT_MAX. To fix:
// for (int i = 5; i * i <= n; i = i + 6) {
for (int i = 5; i <= n/i; i = i + 6) {
is_prime(-1), is_prime(-2147483647) and various negative values return 1, yet are not primes. To fix:
//if (n == 1)
if (n <= 1)
return 0;
Patched code
int is_prime(int n) {
//if (n == 1)
if (n <= 1)
return 0;
if (n == 2 || n == 3)
return 1;
if (n % 2 == 0 || n % 3 == 0)
return 0;
// for (int i = 5; i * i <= n; i = i + 6) {
for (int i = 5; i <= n/i; i = i + 6) {
if (n % i == 0 || n % (i + 2) == 0)
return 0;
}
return 1;
}
Overflow
With int sum, sum += j; readily overflows. Use long long sum.
To improve time performance with this code that checks primality of a contiguous set of integers, research Sieve of Eratosthenes.
This is effectively a re-write then for OP, yet it has faster execution time.
Related
i have a code and im trying to get a O(sqrt(n)) without using math library in c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int is_abundant(int num);
int main()
{
int num;
scanf("%d", &num);
printf("%d\n", is_abundant(num));
return 0;
}
int is_abundant(int num)
{
int sum = 1;
for (int i = 1; i < num; i++) {
if (num % i == 0)
{
sum += i;
}
}
sum = sum - num;
if (sum > num)
{
return 1;
}
else
return 0;
}
what can i do to get O(sqrt(n)) ? any help ?
When num % i == 0 is true, num % (num / i) == 0 will also be true.
Therefore, you can reduce the loop
for (int i = 1; i < num; i++) {
if (num % i == 0)
{
sum += i;
}
}
to
if (num > 1) {
for (int i = 1; i * i <= num; i++) {
if (num % i == 0)
{
sum += i;
if (num / i > i) sum += num / i;
}
}
}
Note that simply changing the condition i < num to i * i <= num will allow it to enter the loop when num = 1, so I added an if statement to deal with this case.
For finding out factors you don't have to run the loop till n times, rather you can just run it till i <= sqrt(n) times or if you don't want to use sqrt lib then simply multiply i two times check if it is less than or equal to num or not.
int is_abundant(int num)
{
int sum = 1;
for (int i = 1; i*i <= num; i++) {
if (num % i == 0)
{
sum += i;
sum += num/i; // if all factors you want to add, otherwise ignore
}
}
sum = sum - num;
if (sum > num)
{
return 1;
}
else
return 0;
}
I want to find all the decompositions of a number using only odd numbers and up to N numbers max.
For example for the number 7 and N = 3, I can only get 1+1+5, 1+3+3, 7. I can't get 1+1+1+1+3 because it's greater then N.
They hint us to use backtracking.
I strated writing the code and I am stuck. If someone can explian to me how to solve this problem it will be great.
int T(int n, int k)
{
if (k == 0)
{
return;
}
int arr[N];
int f;
for (f = 0; f < N; f++)
{
arr[f] = 0;
}
int sum = 0;
int j = 1;
int i = 1;
int c = 0;
while (j < k) {
sum = sum + i;
arr[c] = i;
if (sum == n)
{
for (f = 0; f < N; f++)
{
if (arr[f] != 0)
{
printf("%d ", arr[f]);
}
}
printf("\n");
}
else if (sum > n)
{
arr[c] = 0;
sum = sum - i;
i = i - 2;
}
else
{
i = i + 2;
j++;
c++;
}
}
T(n, k - 1);
}
Please compile with warnings (-Wall) and fix all of them (-Werror helps make sure you do this). I didn't build your code, but int T(int n, int k) says it returns an int, yet the function code is void.
With backtracking, you can't print at each node because the current node in the graph might not actually lead to a solution. It's premature to commit anything to the result set until you actually reach it.
It's best not to print in functions that perform logical tasks anyway, but it can make the coding easier while developing the logic so I'll stick wiith it.
The backtracking suggestion is a good one. Here's the logic:
The "found result" base case is when n == 0 && k >= 0, if you're decrementing n and k and using them to represent the remaining value to reach the goal and the number of choices left. If you're incrementing variables to count up to n and k, that's fine too, in which case the base case is current_total == n && taken_so_far <= k.
Next, the "failure" base case is k < 0 || n < 0 because we've either overshot n or run out of numbers to take.
After that, the recursive case is, in English, "try taking each odd number i up to n, recursing on the possibility that i might be part of the solution". Per your spec, we don't accept any sequence of descending numbers which prunes the recursion tree a bit.
Here's the code; again, returning a result is an exercise. I'm using a k-sized array to store potential results, then dumping it to stdout only when a result was found.
#include <stdio.h>
#include <stdlib.h>
void odd_decomposition_search(
int n, const int k, int taken_length, int *taken
) {
if (n == 0 && taken_length <= k && taken_length > 0) {
for (int i = 0; i < taken_length - 1; i++) {
printf("%d+", taken[i]);
}
printf("%d\n", taken[taken_length-1]);
}
else if (n > 0 && taken_length < k) {
int i = taken_length ? taken[taken_length-1] : 1;
for (; i <= n; i += 2) {
taken[taken_length] = i;
odd_decomposition_search(n - i, k, taken_length + 1, taken);
}
}
}
void odd_decomposition(const int n, const int k) {
if (n <= 0 || k <= 0) {
return;
}
int taken[k];
odd_decomposition_search(n, k, 0, taken);
}
int main() {
int n = 7;
int k = 3;
odd_decomposition(n, k);
return 0;
}
If you're having trouble understanding the call stack, here's a visualizer you can run in the browser:
const oddDecomp = (n, k, taken=[]) => {
console.log(" ".repeat(taken.length), `[${taken}]`);
if (n === 0 && taken.length <= k && taken.length) {
console.log(" ".repeat(taken.length), "-> found result:", taken.join("+"));
}
else if (n > 0 && taken.length < k) {
for (let i = taken.length ? taken[taken.length-1] : 1; i <= n; i += 2) {
taken.push(i);
oddDecomp(n - i, k, taken);
taken.pop(i);
}
}
};
oddDecomp(7, 3);
I really tried but still don't know what's wrong with my code.
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int minus, i, judge;
for (minus = 0, judge = 1; judge == 1; minus++, n -= minus) {
for (i = 2; i * i < n; i++) {
if (n % i == 0)
judge = 1;
else judge = 0;
}
if (judge == 1)
continue;
else break;
}
printf("%d\n", n);
return 0;
}
When I input 143, the output is 143 not 139.
However, when I input 11, the output is the correct answer 11.
The loop test is incorrect: for (i = 2; i * i < n; i++)
If n is the square of a prime number, the loop will stop just before finding the factor.
You should either use i * i <= n or i <= n / i.
Furthermore, you do not enumerate all numbers as you decrement n by an increasing value at each iteration.
Note also that the loop would not find the closest prime to n, but the greatest prime smaller than n, which is not exactly the same thing.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
int isPrime(int n) {
if (n <= 2 || n % 2 == 0)
return n == 2;
for (int i = 3; i <= n / i; i += 2) {
if (n % i == 0)
return 0;
}
return 1;
}
int main() {
int n;
if (scanf("%d", &n) != 1)
return 1;
if (n <= 2) {
printf("2\n");
} else {
for (i = 0;; i++) {
if (isPrime(n - i))
printf("%d\n", n - i);
break;
}
if (n <= INT_MAX - i && isPrime(n + i))
printf("%d\n", n + i);
break;
}
}
}
return 0;
}
#include <stdio.h>
#include <math.h>
int prime (long n);
long reverse(long n);
int main(void)
{
long n;
long i, j;
puts("Enter n dight number, and we will help you find symmetrical prime number");
scanf("%ld", &n);
for (i = 11; i < (pow(10, n) - 1); i+= 2)
{
if (prime(i))
{
j = reverse(i);
if (i == j)
{
printf("%ld\n", i);
}
}
}
}
int prime (long n) //estimate whether the number n is primer number
{
int status = 0;
int j;
//1 is prime, 0 is not
if (n % 2 == 0 || n == 3)
{
if (n == 2)
status = 1;
if (n == 3)
status = 1;
else
{
n++;
status = 0;
}
}
else
{
j = 3;
while (j <= sqrt(n))
{
if (n % j == 0)
{
status = 0;
break;
}
else
status = 1;
j+= 2;
}
}
return status;
}
long reverse(long n) //reverse a number
{
int i, j, x;
long k, sum;
int digit = 0;
int ar[1000];
while (n > 0)
{
k = n;
n = n / 10;
x = (k - n*10);
digit++;
ar[digit] = x;
}
for (i = 1,j = digit - 1; i <= digit; i++, j--)
{
sum += ar[i] * pow(10, j)
}
return sum;
}
I build a reverse function in order to reverse numbers, for example, 214, to 412.
This function works fine in individual number, for instance, I type reverse(214), it return 412, which is good. But when I combine reverse() function with for loop, this function can not work... it produces some strange number...
so How can I fix this problem?
The reverse function is extremely complicated. The better way to go about it would be:
long reverse (long n)
{
long result = 0;
while (n != 0)
{
result *= 10;
result += n % 10;
n /= 10;
}
return result;
}
I think the problem in your code is that in the following segment
digit++;
ar[digit] = x;
you first increment the position then assign to it, thus leaving ar[0] unintialized.
How can I fix this problem?
You need to initialize sum
long k, sum = 0;
^
See the code from #Armen Tsirunyan for a simpler approach.
I've been doing a few of the challenges on the Sphere Online Judge (SPOJ), but I can't seem to get the second problem (the prime generator) to run within the time limit. How can the speed of the following code be increased?
#include <stdio.h>
#include <math.h>
int is_prime(int n);
void make_sieve();
void fast_prime(int n);
int primes[16000];
int main()
{
int nlines;
int m, n;
make_sieve();
scanf("%d", &nlines);
for (; nlines >= 1; nlines--) {
scanf("%d %d", &m, &n);
if (!(m % 2)) {
m++;
}
for ( ; m < n; m+=2) {
fast_prime(m);
}
printf("\n");
}
return 0;
}
/* Prints a number if it's prime. */
inline void fast_prime(int n)
{
int j;
for (int i = 0; ((j = primes[i]) > -1); i++) {
if (!(n % j)) {
return;
}
}
printf("%d\n", n);
}
/* Create an array listing prime numbers. */
void make_sieve()
{
int j = 0;
for (int i = 0; i < 16000; i++) {
primes[i] = -1;
}
for (int i = 2; i < 32000; i++) {
if (i % 2) {
if (is_prime(i)) {
primes[j] = i;
j++;
}
}
}
return;
}
/* Test if a number is prime. Return 1 if prime. Return 0 if not. */
int is_prime(int n)
{
int rootofn;
rootofn = sqrt(n);
if ((n <= 2) || (n == 3) || (n == 5) || (n == 7)) {
return 1;
}
if (((n % 2) == 0) || ((n % 3) == 0) || ((n % 5) == 0) || ((n % 7) == 0)) {
return 0;
}
for (int i = 11; i < rootofn; i += 2) {
if ((n % i) == 0) {
return 0;
}
}
return 1;
}
isprime() does not make use of the prime number table primes[].
Plus, implement a search of the primes array that will complete quickly using a binary search algorithm. The standard library has one.
To see where your time is spent in code you can use profiling
gcc example
gcc -p -g - o mycode mycode.c
===run the code--
gprof mycode
Currently, your problem isn't time limit. Its the fact that your program never print any numbers.
The most obvious error is that in fast_prime you are checking if n is divisible by prime[0], prime[1],... up to prime[k]. Even if n is prime, you won't print it, because n is somewhere in primes[], and so you'll get that n is divisible by some number...
To correct this, you need to check that n is divisible by some prime number up to the square root of n (this will also have the side effect of speeding up the code, as less numbers will be checked before deciding some number is a prime)
change fast_prime to
inline void fast_prime(int n)
{
int j;
int rootofn;
rootofn = sqrt(n);
for (int i = 0; ((j = primes[i]) > -1) && (j<rootofn); i++) {
if (!(n % j)) {
return;
}
}
printf("%d\n", n);
}