Regarding the approach of a recursive to iterative past year paper question - c

How would you convert this recursive function into iterative?
int sum(int n) {
if (n < 1) return 1;
return sum(n - 1) * (n - 1) + n;
Can I do it like this? (Refer below)
int sum(int n){
if(n<1) return 1;
while(n >= 1){
sum = sum(n-1) * (n-1) + n;
}
return sum;
}

Your answer is still in a recursive form.
Observe that you have a base case, i.e. where n = 0. This is the initial value of your sum. You can then iterate over n, for each iteration applying the formula given for the sum. The iterative case, then, looks like this:
int sum_iterative (int n) {
int sum = 1; //n = 0
for (int i = 1; i <= n; i++) {
sum = sum * (i-1) + i; //sum(n-1) * (n-1) + n
}
return sum;
}

Related

How do I solve this equation?

I can’t solve this equation.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int n, result, sum, product;
sum = 0; product = 1, result = 0;
for (int n = 1; n <= 20; n++) {
for (int i = 1; i <= n; i++) {
sum = sum + ((i - n) / (i + n));
product *= sum;
result = sum + product;
}
}
printf("result::%d",result);
return 0;
}
You are on the right track, but note these problems:
you should use double arithmetics for the computation and values, otherwise the result will be meaningless.
you should initialize sum to 0 before the inner loop
you should move the product outside the inner loop
n is redefined in the outer for loop
result is probably not needed.
Here is a modified version:
#include <stdio.h>
int main() {
double product = 1.0;
for (int n = 1; n <= 20; n++) {
double sum = 0.0;
for (int i = 1; i <= n; i++) {
sum += (double)(i - n) / (double)(i + n);
}
product *= sum;
}
printf("result: %f\n", product);
return 0;
}
The above direct translation of the formula outputs -0.000000. The explanation is simple: if you look at the formula, you will see that the first term of the product for n=1 is sum for i from 1 to 1 of (i - n) / (i + n), which is (1 - 1) / (1 + 1), that is 0. Multiplying that by any finite quantity will stay invariably null.
Hence the formula can be solved algebraically and produce a much simplified version. A good algorithm beats any brute force approach:
#include <stdio.h>
int main() {
printf("result: 0\n");
return 0;
}

Finding two consecutive primes such that the gap between them is greater than or equal to N

I am writing a program to read an integer n (0 < n <= 150) and find the smallest prime p and consecutive prime q such that q - p >= n.
My code works, but it runs for about 10 seconds for larger n.
#include <stdio.h>
#include <stdlib.h>
int isPrimeRecursive(int x, int i){
if (x <= 2){
return (x == 2 ? 1:0);
}
if (x % i == 0){
return 0;
}
if (i * i > x){
return 1;
}
return isPrimeRecursive(x, i+1);
}
int findSuccessivePrime(int x){
while (1){
x++;
if (isPrimeRecursive(x, 2)){
return x;
}
}
return 0;
}
int findGoodGap(int n, int *arr){
int prime = findSuccessivePrime(n*n);
while (1){
int gap;
int succPrime;
succPrime = findSuccessivePrime(prime);
gap = succPrime - prime;
if (gap >= n){
arr[0] = succPrime;
arr[1] = prime;
return gap;
}
prime = succPrime;
}
return 0;
}
int main(int argc, char *argv[]){
int n;
int arr[2];
scanf("%d", &n);
int goodGap;
goodGap = findGoodGap(n, arr);
printf("%d-%d=%d\n", arr[0], arr[1], goodGap);
return 0;
}
How can I make the program more efficient? I can only use stdio.h and stdlib.h.
The algorithm is very inefficient. You're recalculating the same stuff over and over again. You could do like this:
int n;
// Input n somehow
int *p = malloc(n * sizeof *p);
for(int i=0; i<n; i++) p[i] = 1; // Start with assumption that all numbers are primes
p[0]=p[1]=0; // 0 and 1 are not primes
for(int i=2; i<n; i++)
for(int j=i*2; j<n; j+=i) p[j] = 0;
Now, p[i] can be treated as a boolean that tells if i is a prime or not.
The above can be optimized further. For instance, it's quite pointless to remove all numbers divisible by 4 when you have already removed all that are divisible by 2. It's a quite easy mod:
for(int i=2; i<n; i++) {
while(i<n && !p[i]) i++; // Fast forward to next prime
for(int j=i*2; j<n; j+=i) p[j] = 0;
}
As Yom B mentioned in comments, this is a kind of memozation pattern where you store result for later use, so that we don't have to recalculate everything. But it takes it even further with dynamic programming which basically means using memozation as a part of the algorithm itself.
An example of pure memozation, that's heavily used in the C64 demo scene, is precalculating value tables for trigonometric functions. Even simple multiplication tables are used, since the C64 processor is MUCH slower at multiplication than a simple lookup. A drawback is higher memory usage, which is a big concern on old machines.
I think it would be a good approach to have all of the prime numbers found and store it in an array; in that case you wouldn't need to do divisions from scratch to find out whether a number is a prime number or not
This is the algorithm which checks if the number "n" is prime simply by doing divisions
bool isPrime(int n) {
if(n <= 1) return false;
if(n < 4) return true;
if(n % 2 == 0) return false;
if(n < 9) return true;
if(n % 3 == 0) return false;
int counter = 1;
int limit = 0;
while(limit * limit <= n) {
limit = limit * 6;
if(n % (limit + 1) == 0) return false;
if(n % (limit - 1) == 0) return false;
}
return true;
}
If you use the algorithm above which its time complexity is in order of sqrt(n) , your overall time complexity would be more than n^2
I suggest you to use "Sieve of Eratosthenes" algorithm to store prime numbers in an array
Check out this link
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Here is the code. I used optimized sieve in Main function.
#include <iostream>
using namespace std;
void Sieve(bool* list, const int n);
void OptimizedSieve(bool* list, const int n);
int main() {
bool list[100 / 2];
for(int i = 0; i < 100 / 2; i++) list[i] = true;
OptimizedSieve(list, 100 / 2);
for(int i = 0; i < 100 / 2; i++){
if(list[i]) cout << (2 * i) + 1 << endl;
}
return 0;
}
void Sieve(bool* list, const int n){
list[0] = false;
list[1] = false;
for(int p = 2; p * p <= n; p++){
if(!list[p]) continue;
for(int j = p * p; j < n; j += p){
if(list[j] == true) list[j] = false;
}
}
}
void OptimizedSieve(bool* list, const int n){
list[0] = false;
for(int p = 3; p * p <= n; p += 2){
if(!list[(2 * p) + 1]) continue;
for(int j = p * p; j <= n; j += 2 * p){
int index = (j - 1) / 2;
if(list[index]) list[index] = false;
}
}
}

How to fix 'time limit exceeded' in some test cases when using the for loop?

We have a series of numbers which is the sum of numbers from 1 to n.(1,3,6,10,...)
The question wants me to find the smallest number in this series which has k divisors.
My code works properly on all test cases but it exceeds the time limits.
It has one while loop and one for loop inside it.
int main()
{
int k, sum, counter = 0, n = 1;
scanf("%d", &k);
while (counter != k) {
counter = 0;
sum = n*(n + 1) / 2; //sum of numbers from 1 to n.(formula)
for (int i = 1; i <= sum / 2; i++) //counts the divisors
if (sum%i == 0)counter++;
counter++; //adds one to the counter because of number 1
n++;
}
printf("%d",sum);
return 0;
}
And here is a example:
Input:k=4
Output:6
What should I do to have a faster and better program?
Did not find a good dup. Here is a solution with O(sqrt(n)) complexity. It's taken from https://www.geeksforgeeks.org/count-divisors-n-on13/
// function to count the divisors
int countDivisors(int n)
{
int cnt = 0;
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
// If divisors are equal,
// count only one
if (n / i == i)
cnt++;
else // Otherwise count both
cnt = cnt + 2;
}
}
return cnt;
}
On the same site, there is one that runs in O(n^(1/3)) that is slightly more complex. It's for C++, but just add #include <stdbool.h> and it should work.
void SieveOfEratosthenes(int n, bool prime[],
bool primesquare[], int a[])
{
// Create a boolean array "prime[0..n]" and initialize all entries as
// true. A value in prime[i] will finally be false if i is Not a prime,
// else true.
for (int i = 2; i <= n; i++)
prime[i] = true;
// Create a boolean array "primesquare[0..n*n+1]" and initialize all
// entries it as false. A value in squareprime[i] will finally be true
// if i is square of prime, else false.
for (int i = 0; i <= (n * n + 1); i++)
primesquare[i] = false;
// 1 is not a prime number (Look it up if you doubt it)
prime[1] = false;
for (int p = 2; p * p <= n; p++) {
// If prime[p] is not changed, then it is a prime
if (prime[p] == true) {
// Update all multiples of p
for (int i = p * 2; i <= n; i += p)
prime[i] = false;
}
}
int j = 0;
for (int p = 2; p <= n; p++) {
if (prime[p]) {
// Storing primes in an array
a[j] = p;
// Update value in primesquare[p*p], if p is prime.
primesquare[p * p] = true;
j++;
}
}
}
// Function to count divisors
int countDivisors(int n)
{
// If number is 1, then it will have only 1
// as a factor. So, total factors will be 1.
if (n == 1)
return 1;
bool prime[n + 1], primesquare[n * n + 1];
int a[n]; // for storing primes upto n
// Calling SieveOfEratosthenes to store prime factors of n and to store
// square of prime factors of n
SieveOfEratosthenes(n, prime, primesquare, a);
// ans will contain total number of distinct divisors
int ans = 1;
// Loop for counting factors of n
for (int i = 0;; i++) {
// a[i] is not less than cube root n
if (a[i] * a[i] * a[i] > n)
break;
// Calculating power of a[i] in n.
int cnt = 1; // cnt is power of prime a[i] in n.
while (n % a[i] == 0) // if a[i] is a factor of n
{
n = n / a[i];
cnt = cnt + 1; // incrementing power
}
// Calculating number of divisors. If n = a^p * b^q then total
// divisors of n are (p+1)*(q+1)
ans = ans * cnt;
}
// if a[i] is greater than cube root of n
// First case
if (prime[n])
ans = ans * 2;
// Second case
else if (primesquare[n])
ans = ans * 3;
// Third casse
else if (n != 1)
ans = ans * 4;
return ans; // Total divisors
}
If the above is not enough, you should look into some kind of dynamic programming. Both of the above method is calculating each number from scratch. But if you're going to do it for several numbers, it is quite possible that you can use information from previous numbers. Just to give an idea for how it works, here is an algorithm calculating all primes from 2 to n:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
// After running this function, prime[n] will be true iff n is a prime
void createPrimeArray(bool *prime, size_t size)
{
prime[0] = prime[1] = false;
for(size_t i=2; i<size; i++)
prime[i] = true;
for(size_t i=2; i<sqrt(size); i++) {
size_t j=i;
while(!prime[j])
j++;
for(size_t k=2*j; k<size; k+=j)
prime[k] = false;
}
}
int main(void)
{
bool prime[200];
createPrimeArray(prime, 200);
for(int i=0; i<200; i++) {
if(prime[i])
printf("%d ", i);
}
}
The above can possibly be optimized further. It's purpose is to show how you can reuse information. After the first run in the second for loop in createPrimeArray we have marked all numbers that are dividable by 2 as non-primes, and thus we don't have to care about those anymore.

Find an exact function indicating the number of steps taken by the algorithm

int mystery(int n) {
int s = 0;
int tmp = n+1;
for (int i; i<=n; i++) {
s = tmp + i;
tmp = s;
}
return s;
}
How can I determine this function and what the function does? Also, can this function be improved with respect to its running time?
There is some superfluous code in the above; s is completely unnecessary. Re-writing it without it makes it clearer.
int mystery(int n) {
int tmp = n + 1;
for (int i = 1; i<=n; i++) {
tmp += i;
}
return tmp;
}
What it does is
Set tmp to n + 1
Add 1 then 2 then 3 then 4 and so on
This currently has a running time of O(n). However, it turns out that there is a constant time formula for 1 + 2 + 3 + ... + N. We can use this to create the following, which is constant time.
int mystery(int n) {
int triangleNumber = (n * (n + 1)) / 2;
return triangleNumber + n + 1;
}

Why this reverse function can not work in the for loop?

#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.

Resources