how to use recursion to formulate using simple array - c

I am a beginner in coding .I want to solve the following problem using simple recursion and array. But I can't visualize it. I came up with solution using link list .Following are problem and my way of solving
Given n rows of integers, such that the ith row (1 <= i <= n)
contains i integers. Using the following set of path rules, find the
path having the maximum weight.
Path traversal rules:
A valid path sequence would be top-down i.e. begins with the integer in the first row, and traverses all rows selecting only one
integer in each row.
From any jth integer in the ith row i.e. row[i][j], traversal can happen either downward (i.e. to row[i+1][j]) or diagonally downward
to the right (i.e. to row[i+1][j+1]).
The weight of a Path is the sum of values of integers in the Path
sequence.
Example:
No. of Rows: 5
4
2 9
15 1 3
16 92 41 44
8 142 6 4 8
Expected Output: 4, 2, 15, 92, 142 (Max weight is 255)
Sol.c
#include<stdio.h>
#include<stdlib.h>
int n,**ar;
struct n
{
int i,j;
int w;
struct n *ptr;
};
struct n* maxweight(int i,int j,struct n* x)
{
struct n* tmp=malloc(sizeof(struct n)),*t1,*t2;
tmp->i=i;
tmp->j=j;
tmp->ptr=x;
tmp->w=ar[i][j];
if(x)tmp->w+=x->w;
if(i==n-1)return tmp;
t1=maxweight(i+1,j,tmp);
t2=maxweight(i+1,j+1,tmp);
if(t1->w>t2->w)return t1;
return t2;
}
int main()
{
int i,j;
struct n * s;
printf("Enter the value of n\n");
scanf("%d",&n);
ar=malloc(n*sizeof(int*));
for(i=0;i<n;i++)
{
ar[i]=malloc((i+1)*sizeof(int));
for(j=0;j<=i;j++)scanf("%d",&ar[i][j]);
}
s=maxweight(0,0,NULL);
printf("MAX WEIGHT is :%d\nPATH: ",s->w);
while(s)
{
printf("%d ",ar[s->i][s->j]);
s=s->ptr;
}
printf("\n");
return 0;
}
How do I solve this using recursion simply without link-list using n x n matrix ? Is dynamic programming is applicable to this problem.

Focus on calculating the weight of the path that lies ahead of you; don't look back.
Start by solving a trivial edge case. Suppose you made it to the bottom row. Then there is nothing more to follow; the remaining path has weight zero.
In code:
int getWeight(int i, int j)
{
int remaining = 0;
In any other row, you have to make a choice. Should you go left or right? Since there is no way of knowing at this point which one is best, you just have to try both directions:
if (i < lastRow)
{
int weightLeft = getWeight(i + 1, j);
int weightRight = getWeight(i + 1, j + 1);
Notice I recursively called my own function; with a blind faith in that function's capability to come up with the optimal weight for the remaining path!
Having tried both directions, pick whichever came up with the highest weight:
int best_j = weightLeft > weightRight ? j : j + 1;
Now we walk the chosen path one more time.
remaining = getWeight(i + 1, best_j);
}
This is not very efficient, but it helps to collect the individual steps of the optimal path. I will use a straightforward array pathColumns.
pathColumns[i] = j;
Finally, we need to sum the values.
return row[i][j] + remaining;
}
To set the whole thing in motion, just call the function, and pass it the top cell's coordinates. For practical reasons, I made all arrays base-0. So the top cell is row[0][0].
printf("Optimal weight: %d\n", getWeight(0, 0));
Putting it all together:
#include <stdio.h>
#define n 5
int pathColumns[n] = {0};
int row[n][n] =
{
{4},
{2, 9},
{15, 1, 3},
{16, 92, 41, 44},
{8, 142, 6, 4, 8}
};
int getWeight(int i, int j)
{
int remaining = 0;
if (i < n-1) /* with base-0, the last row is n-1 */
{
int weightLeft = getWeight(i + 1, j);
int weightRight = getWeight(i + 1, j + 1);
int best_j = weightLeft > weightRight ? j : j + 1;
remaining = getWeight(i + 1, best_j);
}
pathColumns[i] = j;
return row[i][j] + remaining;
}
int main()
{
int i;
printf("Optimal weight: %d\n", getWeight(0, 0));
for (i = 0; i < n; i++)
{
int j = pathColumns[i];
printf("(%d, %d) = %d\n", i+1, j+1, row[i][j]);
/* NOTE: +1 is a correction to bring the output back to base-1 */
}
return 0;
}
Output:
Optimal weight: 255
(1, 1) = 4
(2, 1) = 2
(3, 1) = 15
(4, 2) = 92
(5, 2) = 142
How it works
We want getWeight(0, 0) to return the heaviest path for this pyramid.
4 <---- (0, 0) is our starting point
/ \
2 9
/ \ / \
15 1 3
/ \ / \ / \
16 92 41 44
/ \ / \ / \ / \
8 142 6 4 8
The recursive algorithm makes two recursive calls.
getWeight(1, 0) must get the heaviest path for the sub-pyramid below and to the left of our starting point.
getWeight(1, 1) must get the heaviest path for the sub-pyramid below and to the right of our starting point.
The two sub-pyramids:
2 <--- (1, 0) 9 <--- (1, 1)
/ \ / \
15 1 1 3
/ \ / \ / \ / \
16 92 41 92 41 44
/ \ / \ / \ / \ / \ / \
8 142 6 4 142 6 4 8
Assuming getWeight(1, 0) and getWeight(1, 1) return the correct weights (251 and 244, respectively), all there is left to do is pick the highest one (251) and add the top value of the big pyramid to it (4). The result is 255.
What we did is reduce a problem (calculate the maximum weight for a pyramid of height 5) so that we are left with two smaller problems to solve (calculate the maximum weight for pyramids of height 4). In the same way, we can reduce the problem for height 4 to solving the same problem for height 3. For example, getWeight(1, 1) will make two recursive calls getWeight(2, 1) and getWeight(2, 2):
1 <--- (2, 1) 3 <--- (2, 2)
/ \ / \
92 41 41 44
/ \ / \ / \ / \
142 6 4 6 4 8
getWeight(1, 1) should return 244 = 9 + max(235, 55).
Continuing this way, we eventually end up with solving the problem for pyramids of height 1. These are the values at the base of the original pyramid (8, 142, 6, 4 and 8). Here the recursion ends; a pyramid of height 1 is nothing more than a single node. The value of that node is the weight of the (only) path through that pyramid.

Related

Make an array multiply only the columns behind it, going one at a time until the last one and save the answer in c

I'm making a program in C that factors any number using primes and saves these primes, multiplying them you find all the divisors of a number.
But I can't make an array that multiplies the previous columns and saves the results. follow the example
60 / 2
30 / 2
15 / 3
5 / 5
divisors = 2, 2, 3, 5
now i need`add 1 to array array {1, 2, 2, 3, 5}
i need this now start colune 2 {1, 2} 2 * 1 = 2 save.
next colune 3 {1, 2, 2} 2 * 1 = 2 but we already have 2 so don't save it.
continue 2 * 2 = 4 save.
colune 4 {1, 2, 2, 3} 3 * 1 = 3 save, 3 * 2 = 6 save, 3 * 4 = 12 save.
colune 5 {1, 2, 2, 3, 5} 5 * 1 = 5 save, 5* 2 = 10, 5 * 4 = 20 save, 5 * 3= 15 save, 5 * 6 = 30 save, 5 * 12 = 60 save.
now we found all divisors of 60 = 1, 2, 3, 4, 5, 6, 10 ,12 , 15,20, 30, 60.
It is important to mention that I need the program to be like this, I know there are other ways... but I only need this one, I have been unable to complete it for 1 week
video to help https://www.youtube.com/watch?v=p0v5FpONddU&t=1s&ab_channel=MATEM%C3%81TICAFORALLLUISCARLOS
my program so far
#include <stdlib.h>
#include <stdio.h>
int N = 1;
int verificarPrimo(int numero);
int main()
{
int num = 60, i, primo = 1, resultados[N], j = 1;
for (i = 0; i < 60; i++)
{
if (primo == 1)
{
resultados[N - 1] = primo;
i = 2;
primo = i;
}
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
for (i = 1; i < N; i++)
{
printf("%d \n", resultados[i]);
}
}
int verificarPrimo(int primo)
{
int i;
if (primo <= 1)
return 0;
for (i = 2; i <= primo / 2; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
I tried out your code and ran into some issues with how the results were being stored. First off, the results array is being initially defined as an array with a size of "1", and that it not what you probably want.
int num = 60, i, primo = 1, resultados[N], j = 1;
With that in mind and determining the spirit of this project, following is tweaked version of the code to test for one or more values and their factors.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int verificarPrimo(int primo)
{
int sq = sqrt(primo) + 1; /* Usual checking for a prime number is from '2' to the square root of the number being evaluated */
if (primo <= 1)
return 0;
for (int i = 2; i < sq; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
int main()
{
int N = 0;
int num = 0, entry = 0, resultados[100]; /* The results array needs to be defined with some value large enough to contain the assorted factors a number might have */
printf("Enter a number to evaluate for factors: "); /* Using a prompt to allow various values to be tested */
scanf("%d", &entry);
num = entry;
if (verificarPrimo(num)) /* Catchall in case the entered number is a prime number */
{
printf("This number is a prime number and has no factors other than one and itself\n");
return 0;
}
resultados[0] = 1; /* Normally the value '1' is implied in a list of factors, so these lines could be omitted */
N = 1;
for (int i = 2; i < entry; i++)
{
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
printf("Factors for %d\n", entry);
for (int i = 0; i < N; i++)
{
printf("%d ", resultados[i]);
}
printf("\n");
return 0;
}
Some items to point out in this tweaked code.
In the prime number verification function, it is usually customary to set up a for loop in testing for prime numbers to go from the value of "2" to the square root of the number being tested. There usually is no need travel to one half of the number being tested. For that, the #include <math.h> statement was added (FYI, "-lm" would need to be added to link in the math library).
Instead of defining the results array with a value of one element, an arbitrary value of "60" was chosen for the holding the possible number of results when evaluating factors for a given value. Your original code had the potential of storing data past the end of the array and causing a "smashing" error.
The value of "1" is usually left out of the list of factors for a number, but was left in as the initial result value. This might be left out of the completed code.
An additional entry field was added to allow for user entry to be tested to give the code some flexibility in testing numbers.
A test was also added to see if the entered number is itself a prime number, which would only have factors of "1" and itself.
Following is some sample terminal output testing out your original value of "60" along with some other values.
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 60
Factors for 60
1 2 2 3 5
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 63
Factors for 63
1 3 3 7
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 29
This number is a prime number and has no factors other than one and itself
Give that a try to see if it meets the spirit of your project.

How do I solve the Coin Row problem using dynamic programming?

Coin-row problem: There is a row of n coins whose values are some positive integers C0, C2, . . . , Cn-1, not necessarily distinct. The goal is to pick up the maximum amount of money subject to the constraint that no two coins adjacent in the initial row can be picked up.
In the below code, n is the size of my array C(or number of coins), and this code returned the right result for the values [10, 2, 4, 6, 3, 9, 5] (the right result being 25). But when I run the same code for the values [3, 12, 10] or [3, 12, 10, 2], I got the wrong result. (The result should be 13 and 14 respectively for the set of values).
Please help me fix my code.
int max(int a, int b) {
if(a > b) return a;
return b;
}
int coin_row(int[] C, int n) {
if(n==1) return C[0];
if(n==2) return max(C[0],C[1];
int F[n], i;
F[0] = 0; F[1] = C[0];
for(i = 2;i < n;i++) {
F[i] = max(C[i] + F[i-2], F[i-1]);
}
return F[n-1];
}
The statement that all numbers will be positive makes things a little easier. From that information we can determine that we never want to skip over two consecutive numbers. We just have to calculate the best sequence possible using the first number and compare it with the best sequence possible using the 2nd number. This is ideal for recursion.
int coin_row(int *C, int n)
{
int first_total;
int second_total;
if (n == 0) return 0;
if (n == 1) return *C;
if (n == 2) return max(*C, *(C+1));
first_total = *C + coin_row(C+2, n-2);
second_total = *(C+1) + coin_row(C+3, n-3);
return(max(first_total, second_total));
}
By breaking down the problem into a sequence of pairs we treat the list as a large binary tree. At every pair you can choose either the first or second number. Calculate the total for each sub-tree and return the greatest value. For example with {10, 2, 4, 6, 3, 9, 5} your paths are:
10 2
/\ /\
4 6 6 3
/\ /\ /\ /\
3 9 9 5 9 5 5 -
Your algorithm is right but there are some bugs in implementation.
You are skipping the value at C[1] as your loop starts from i=2.
Since you are including 0 coin case in your F array, it needs to be of size n+1 for F[n] to exist. With the above corrections we arrive at:
int max(int a, int b) {
if(a > b) return a;
return b;
}
int coin_row(int* C, int n) {
if(n==1) return C[0];
if(n==2) return max(C[0],C[1]);
int F[n+1], i;
F[0] = 0; F[1] = C[0];
for(i = 2 ; i <= n + 1 ; i++) {
F[i] = max(C[i-1] + F[i-2], F[i-1]);
}
return F[n];
}

Count ones in a segment (binary)

There is a problem which i am working on it right now and it's as the following :
there are two numbers x1 and x2 and x2 > x1.
for example x1 = 5; and x2 = 10;
and I must find the sum of ones between x1 and x2 in binary representations.
5 = 101 => 2 ones
6 = 110 => 2 ones
7 = 111 => 3 ones
8 = 1000 => 1 one
9 = 1001 => 2 ones
10= 1010 => 2 ones
so the sum will be
sum = 2 + 2 + 3 + 1 + 2 + 2 = 12 ones;
so I have managed to make a code without even transfer the numbers to binary and wasting execution time.
I noticed that the numbers of ones in every 2^n with n >= 1 is 1
Ex : 2^1 => num of ones is 1
2^2 => 1 2^15 => 1
you can test it here if you want: https://www.rapidtables.com/convert/number/decimal-to-binary.html?x=191
and between each 2^n and 2^(n+1) there are Consecutive numbers as you will see in this example :
num number of ones
2^4 = 16 1
17 2
18 2
19 3
20 2
21 3
22 3
23 4
24 2
25 3
26 3
27 4
28 3
29 4
30 4
31 5
2^5 = 32 1
so I write a code that can find how many ones between 2^n and 2^(n+1)
int t; ////turns
int bin = 1; //// numbers of ones in the binary format ,,, and 1 for 2^5
int n1 = 32; //// 2^5 this is just for clarification
int n2 = 64; //// 2^6
int *keep = malloc(sizeof(int) * (n2 - n1); ///this is to keep numbers because
/// i'll need it later in my consecutive numbers
int i = 0;
int a = 0;
n1 = 33 //// I'll start from 33 cause "bin" of 32 is "1";
while (n1 < n2) /// try to understand it now by yourself
{
t = 0;
while (t <= 3)
{
if (t == 0 || t == 2)
bin = bin + 1;
else if (t == 1)
bin = bin;
else if (t == 3)
{
bin = keep[i];
i++;
}
keep[a] = bin;
a++;
t++;
}
n1++;
}
anyway as you see I am close to solve the problem but they give me huge numbers and I must find the ones between them, unfortunately I have tried a lot of methods to calculate the "sum" using this above code and I ended up with time execution problem.
Ex: 1, 1000000000 the numbers of ones is >>> 14846928141
so can you give me a little hint what to do next, thanks in advance.
I'm doing this for CodeWar challenge: https://www.codewars.com/kata/596d34df24a04ee1e3000a25/train/c
You can solve this problem by computing the number of bits in the range 1 to n and use a simple subtraction for any subrange:
#include <stdio.h>
#include <stdlib.h>
/* compute the number of bits set in all numbers between 0 and n excluded */
unsigned long long bitpop(unsigned long long n) {
unsigned long long count = 0, p = 1;
while (p < n) {
p += p;
/* half the numbers in complete slices of p values have the n-th bit set */
count += n / p * p / 2;
if (n % p >= p / 2) {
/* all the numbers above p / 2 in the last partial slice have it */
count += n % p - p / 2;
}
}
return count;
}
int main(int argc, char *argv[]) {
unsigned long long from = 1000, to = 2000;
if (argc > 1) {
to = from = strtoull(argv[1], NULL, 0);
if (argc > 2) {
to = strtoull(argv[1], NULL, 0);
}
}
printf("bitpop from %llu to %llu: %llu\n", from, to, bitpop(to + 1) - bitpop(from));
return 0;
}
Here is a proposal for a speedup:
Find smallest y1 such that y1 >= x1 and that y1 is a power of 2
Find largest y2 such that y2 <= x2 and that y2 is a power of 2
Find p1 and p2 such that 2^p1=y1 and 2^p2=y2
Calculate the amount of 1:s between y1 and y2
Deal with x1 to y1 and y2 to x2 separately
Sum the results from 4 and 5
Let's focus on step 4. Let f(n) be the sum of ones up to (2^n)-1. We can quickly realize that f(n) = 2*f(n-1) + 2^(n-1) and that f(1)=1. This can be even further refined so that you don't have to deal with recursive calls, but I highly doubt it will be of any importance. Anyway, f(n) = n*2^(n-1)
To get the result between y1 and y2, just use f(p2)-f(p1)
For step 5, you can likely use a modified version of step 4.
EDIT:
Maybe I was to quick to say "quickly realize". Here is a way to understand it. The amounts of ones up to 2¹-1 is easy to see. The only two binary numbers below 2¹ are 0 and 1. To get the number of ones up to 2² we take the numbers below 2¹ and make a column:
0
1
Clone it:
0
1
0
1
And put 0:s before the first half and 1:s before the second half:
00
01
10
11
To get 2³ we do the same. Clone it:
00
01
10
11
00
01
10
11
And add 0 and 1:
000
001
010
011
100
101
110
111
Now it should be easy to see why f(n) = 2*f(n-1) + 2^(n-1). The cloning gives 2f(n-1) and adding the 0:s and 1:s gives 2^(n-1). If 2^(n-1) is hard to understand, remember that 2^(n-1)=(2^n)/2. In each step we have 2^n rows and half of them get an extra 1.
EDIT2:
When I looked at these columns, I got an idea for how to do step 5. Let's say that you want to find the amounts of 1:s from 10 to 15. Binary table for this would be:
10: 1010
11: 1011
12: 1100
13: 1101
14: 1110
15: 1111
Look at the interval 12-15. The last two digits in binary is a copy of the corresponding table for 0-3. That could be utilized, but I leave that to you.
EDIT 3:
This was a fun problem. I wrote some python code that does this. I get some problems with too many recursive calls, but that could be solved pretty easily, and it should not be too complicated to convert this to C:
def f(n):
return n*2**(n-1)
def numberOfOnes(x):
if(x==0):
return 0
p = floor(log(x,2))
a = f(p)
b = numberOfOnes(x-2**p)
c = x - 2**p +1
return a+b+c
I made an image so that you easier can understand what a, b and c does in the function numberOfOnes if we call it with numberOfOnes(12):
I have finally converted it to C. Of course I have used some code I found here on Stack overflow. I borrowed code for integer versions of log2 and pow, and made some small modifications.
This code is probably possible to optimize further, but it is not necessary. It is lighting fast, and I was not able to measure it's performance.
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
typedef uint64_t T;
// https://stackoverflow.com/a/11398748/6699433
const int tab64[64] = {
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5};
T log2_64 (T value) {
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
return tab64[((T)((value - (value >> 1))*0x07EDD5E59A4E28C2)) >> 58];
}
// https://stackoverflow.com/a/101613/6699433
T ipow(T base, T exp) {
T result = 1;
for (;;) {
if (exp & 1) result *= base;
exp >>= 1;
if (!exp) break;
base *= base;
}
return result;
}
T f(T n) { return ipow(2,n-1)*n; }
T numberOfOnes(T x) {
if(x==0) return 0;
T p = floor(log2(x));
T a = f(p);
T e = ipow(2,p);
T b = numberOfOnes(x-e);
T c = x - e + 1;
return a+b+c;
}
void test(T u, T v) {
assert(numberOfOnes(u) == v);
}
int main() {
// Sanity checks
test(0,0);
test(1,1);
test(2,2);
test(3,4);
test(4,5);
test(5,7);
test(6,9);
// Test case provided in question
test(1000000000,14846928141);
}
int x1 = 5;
int x2 = 10;
int i=0;
int looper = 0;
unsigned long long ones_count = 0;
for(i=x1; i<=x2; i++){
looper = i;
while(looper){
if(looper & 0x01){
ones_count++;
}
looper >>= 1;
}
}
printf("ones_count is %llu\n", ones_count);
return 0;
OUTPUT: ones_count is 12
Here is a way to count every single bit for every value in between the two values. The shift/mask will be faster than your arithmetic operators most likely, but will still probably time out. You need a clever algorithm like the other answer suggests i think, but heres the stupid brute force way :)
This was my solution to the problem:
** = exponentiation
/ = whole number division
Consider the numbers from 1 to 16:
00001
00010
00011
00100
00101
00110
00111
01000
01001
01010
01011
01100
01101
01110
01111
10000
If you pay attention to each column, you'll notice a pattern. The bit at column index i (0,1,2 ...) from the right runs through a cycle of length 2**(i+1), that is every 2**(i+1) rows, the pattern in column i repeats itself. Notice also that the first cycle starts at the first occurrence of a 1 in a given column. The number of ones in a pattern is half of the patterns length.
Example:
i pattern
0 10
1 1100
2 11110000
3 1111111100000000
...
So, given the task of summing all ones up to n, we have to keep track of how many times each pattern repeats itself and also if a pattern fails to complete itself.
Solution:
Let x be the biggest exponent of a binary number n and let s be the sum of all ones up to n. Then, for i = (0, 1, 2, ... , x) add (n / 2**(i+1)*(2**i) to s. If the remainder is bigger than 2**i, add 2**i to s, else add the remainder. Then subtract 2**i from n and repeat the process.
Example:
n = 7 -> x = 2
(7 / 2**1)*(2**0) = 3
7 % 2**1 = 1 !> 2**0
s = 1 + 3 (4)
n = n - 2**0 (6)
(6 / 2**2)*(2**1) = 2
6 % 2**2 = 2 !> 2**1
s = s + 2 + 2 (8)
n = n - 2**1 (4)
(4 / 2**3)*(2**2) = 0
4 % 2**3 = 4 !> 2**2
s = s + 4 (12)
n = n - 2**2 (0)
s = 12
Maybe not the best explanation or the most beautiful solution, but it works fine.
In python:
def cnt_bin(n):
bits = n.bit_length()
s = 0
for i in range(bits):
s += (n // 2**(i+1))*2**i
if n % 2**(i+1) > 2**i:
s += 2**i
else:
s += (n % 2**(i+1))
n -= 2**i
return s
Then, for a range [a, b] you just compute cnt_bin(b) - cnt_bin(a-1)

Need help for find the logic of a heuristic sequence

I'm developing a system that can explore entirely a simple heuristic map of this gender (which can have different numbers of branches, and different depths) :
Simple heuristic map
So, I'm saving the positions explored in an int array of the size of the depth of the map. The goal is to explore all nodes of the map, so to have this output : 0 2 6, 0 2 7, 0 3 8, 0 3 9, 1 4 10 etc.. But actually with my code (which needs to be called several times because it can update just one time the array), i have this : 0 2 6, 0 2 7, 0 3 8, **1** 3 9, 1 4 10 etc..
This is my code, I don't know how to solve this problem..
void get_next_branch(int *s, int nbr_branch, int size)
{
int a;
a = 0;
while (a < size)
{
condition = (size - a)/(nbr_branch - 1);
if (condition)
{
if (s[size - 1] % (condition) + 1 == condition)
s[a]++;
}
a++;
}
}
And this is the main example who call this function.
int main(void)
{
int id[3] = {0, 2, 6};
while (id[2] < 13)
{
printf("%d %d %d\n", id[0], id[1], id[2]);
get_next_branch(id, 2, 3);
}
return (0);
}
I thank you in advance!
You might want to use a closed formula for this problem
b being the number of branches
d the depth you want to find the numbers in (d >= 0)
we get immediately
Number of nodes at depth d = bd+1
(since at depth 0 we have already two nodes, there is no "root" node used).
The number of the first node at depth d is the sum of the number of nodes of the lower levels. Basically,
first node number at depth 0 = 0
first node number at depth d > 0 = b1 + b2 + b3 + ... + bd
This is the sum of a geometric series having a ratio of b. Thanks to the formula (Wolfram)
first node number at depth d = b * (1 - bd) / (1 - b)
E.g. with b == 2 and d == 2 (3rd level)
Number of nodes: 2 ^ 3 = 8
Starting at number: 2 * (1 - 2^2) / (1 - 2) = 6
A program to show the tree at any level can be done from the formulas above.
To print a number of levels of a tree with b branches:
Utility power function
int power(int n, int e) {
if (e < 1) return 1;
int p=n;
while (--e) p *= n;
return p;
}
The two formulas above
int nodes_at_depth(int branches, int depth) {
return power(branches, depth+1);
}
int first_at_depth(int branches, int depth) {
return (branches * (1 - power(branches, depth))) / (1 - branches);
}
Sample main program, to be called
./heuristic nb_of_branches nb_of_levels
that calls the two functions
int main(int argc, char **argv)
{
if (argc != 3) return 1;
int b = atoi(*++argv);
int d = atoi(*++argv);
if (b < 2) return 2;
int i,j;
for (i=0 ; i<d ; i++) {
int n = nodes_at_depth(b, i); // number of nodes at level i
int s = first_at_depth(b, i); // first number at that level
for (j=0 ; j<n ; j++) printf(" %d", s+j);
printf("\n");
}
return 0;
}
Calling
./heuristic 2 4
gives
0 1
2 3 4 5
6 7 8 9 10 11 12 13
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

How to find Number of Factors of "product of numbers"

I m trying to find number of factors of product of big numbers.
The problem statement is this : Suppose you are given N numbers(let say N = 10), each number <= 1000000.
How to find the number of factors of the product of such numbers.
Can someone please provide an efficient algorithm for doing this.
Example :
1) N = 3 and Numbers are 3, 5, 7
Ans = 8 (1, 3, 5, 7, 15, 21, 35, 105)
2) N = 2 and Numbers are 5, 5
Ans = 3 (1, 5 and 25)
Editorial for the problem is here
http://discuss.codechef.com/questions/15943/numfact-editorial
int total = 0, N = 0, Number;
scanf ("%d", &total);
while (total--)
{
scanf ("%d", &N);
map<int, int> Counter;
for (int i = 0; i < N; i++)
{
scanf ("%d", &Number);
for (int j = 2; j * j <= Number; j++)
{
while (Number % j == 0)
{
Counter[j]++;
Number /= j;
}
}
if (Number > 1) Counter[Number]++;
}
int Answer = 1;
for (map<int, int>::iterator it = Counter.begin(); it != Counter.end(); it++)
Answer *= (it->second + 1);
printf ("%d\n", Answer);
}
This got Accepted.
Sample Inputs and Outputs:
7
3
3 5 7
3
2 4 6
2
5 5
10
2 2 2 2 2 2 2 2 2 2
1
100
10
10000 10000 10000 10000 10000 10000 10000 10000 10000 10000
10
1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000
8
10
3
11
9
1681
3721
Factorize each number into list of prime factors and their multiplicities, L(n) = { p_i , k_i }, for a number n = Π piki. Numer of divisors for such n is ND( L(n) ) = Π (ki+1) a product of all coefficients, each incremented by 1 (this includes 1 and n itself as divisors of n). This corresponds to picking none, one, ... ki of each of them to multiply.
To calculate the ND of a product of arbitrary number of numbers, factorize each and merge their factorizations, where in case of matching primes their coefficients are added together. Then calculate the ND of the merged factorization.
To merge many factorizations together, start by merging two of them; then merge the result and the next one; then merge the last result and the next factorization, and so on. This is called folding. Or better merge them pairwise, then merge the results in same pairwise fashion, and so on util only one merged result is left. That's similar to how a bottom-up mergesort is done.
Multiply all the numbers, factorize the result, count all divisors:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[])
{
int p = 1;
for (int i = 1; i < argc; i++)
p *= strtol(argv[i], NULL, 10);
int n = 0;
int s = sqrt(p) + 1;
for (int i = 1; i <= s; i++)
if (p % i == 0)
n += 2 - (p / i == i); // obfuscation ;)
printf("%d\n", n);
return 0;
}

Resources