Optimizing a recursive counting algorithm - c

I hate posting for homework help on here, but I've exhausted my abilities. I am faced with a Stack Overflow (at least thats what its called in Java) issue while writing a simple recursive function in C.
I need every r-permutation of n numbers, and I figured the best way to do that would be counting in base n to length r.
It works fine for smaller amounts of numbers, but the highest case (n=10, r=6) ends up running out of memory. I could easily have written this iteratively but its required to be recursion. Heres what I have so far:
int permute(int *tempArray, int amtNums, int goalLength, int totalMatches) {
totalMatches += 1; //Temporary, will be replaced by a function later
printArray(tempArray, goalLength);
tempArray[0]++;
int j = 0;
while(tempArray[j] >= amtNums) {
tempArray[j+1]++;
tempArray[j] = 0;
j++;
}
if(j+1 > goalLength) return totalMatches;
return permute(tempArray, amtNums, goalLength, totalMatches);
}
Being called as permute((int*)calloc(numSlots, sizeof(int)), 10, 6, 0); for the max case, n=10 r=6
I should Note: The counting isn't exactly intuitive, its a bit backwards but generates all the number combinations I wanted. As an example: n=4, r=3
0 0 0
1 0 0
2 0 0
3 0 0
0 1 0
1 1 0
2 1 0
3 1 0
.....
0 2 3
1 2 3
2 2 3
3 2 3
0 3 3
1 3 3
2 3 3
3 3 3

I belive that you have to modify your recursive function in order to have a maximum depth of the stack of function calls of goalLength. You can accomplish that adding a parameter depth like I did here:
int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches) {
int i;
if ( depth < goalLength - 1) {
for ( i = 0; i < amtNums; ++i ) {
tempArray[depth] = i;
totalMatches = permute(tempArray, amtNums, goalLength, depth + 1, totalMatches);
}
} else {
for ( i = 0; i < amtNums; ++i ) {
tempArray[depth] = i;
printArray(tempArray, goalLength);
++totalMatches;
}
}
return totalMatches;
}
You can of course rewrite it putting the for loop outside and the if inside. I tryed that code with this little test program:
#include <stdio.h>
#define NDIGIT 4
#define NLENGTH 3
void printArray( int *temp, int size ) {
int i;
for ( i = 0; i < size; ++i ) {
printf("%d ", temp[i]);
}
printf("\n");
}
int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches);
int main(void) {
int results[NLENGTH];
int n = permute(results, NDIGIT, NLENGTH, 0, 0);
printf("Total number of permutations: %d\n", n);
return 0;
}
Setting NDIGIT to 10, NLENGTH to 6 and commenting out the printing function (you can keep it if you want...) the program run fine and the output was:
Total number of permutations: 1000000

Your function uses a tail call to itself, the compiler should be able to turn this recursion into a loop. Enable optimisations with command line option -O3 or whatever your IDE provides. If the compiler implements the recursion, the function will recurse amtNumsgoalLength, which is a large number for n=10 and r=6: 1 000 000 recursion levels likely causes a Stack Overflow

Related

Is there any way to create loops based on user input?

I wanna create all possible 5 digit numbers that can be created from the numbers (0-7).
The code below achieves this, but is there any way to make this depend on user input?
The number of loops equals the number of digits I want and each individual loop must be:
for(1st number;condition<=last number;1st number++)
So, for five digits, I have:
for(i=0;i<8;i++){
for(j=0;j<8;j++){
for(k=0;k<8;k++){
for(m=0;m<8;m++){
for(n=0;n<8;n++){
printf("%d %d %d %d %d\n",i,j,k,m,n);
}
}
}
}
}
Keep iterators in an array and increment them manually.
#include <assert.h>
#include <stdio.h>
#include <string.h>
void callback(unsigned n, int i[n]) {
assert(n == 5);
printf("%d %d %d %d %d\n", i[0], i[1], i[2], i[3], i[4]);
}
void iterate(unsigned n, unsigned max, void (*callback)(unsigned n, int i[n])) {
// VLA, use *alloc in real code
int i[n];
memset(i, 0, sizeof(i));
while (1) {
for (int j = 0; j < n; ++j) {
// increment first number, from the back
++i[n - j - 1];
// if it didn't reach max, we end incrementing
if (i[n - j - 1] < max) {
break;
}
// if i[0] reached max, return
if (j == n - 1) {
return;
}
// if the number reaches max, it has to be zeroed
i[n - j - 1] = 0;
}
// call the callback
callback(n, i);
}
}
int main() {
// iterate with 5 numbers to max 8
iterate(5, 8, callback);
}
The beginning and ending of what the code prints:
0 0 0 0 0
0 0 0 0 1
...
...
7 7 7 7 6
7 7 7 7 7
If you want variable numbers of loops, you generally need to use recursion.
Say if you want n digits, with the ith digit be in the range of a[i],b[i], then you will do the following:
/* whatever */
int n;
int *a,*b,*number;
void recursion(int whichdigit){
if (whichdigit==n){
/* Say you managed to output number */
return;
}
for (int i=a[whichdigit];i<=b[whichdigit];i++){
number[whichdigit]=i;
recursion(whichdigit+1);
}
return;
}
int main(){
/* Say somehow you managed to obtain n */
a=malloc(n*sizeof(int));
b=malloc(n*sizeof(int));
number=malloc(n*sizeof(int))
if (!a||!b||!number){
/* unable to allocate memory */
}
/* Say somehow you managed to read a[i],b[i] for all i in 0..n-1 */
recursion(0);
return 0;
}
Warning: if you tries to have too many digits, you will likely get a segmentation fault or stack overflow error.

Base case of recursion function for Fibonacci sequence

I'm trying to write the function void fib(int arr[], int n), which would fill the array with Fibonacci numbers until index n.
I've tried to find base cases, and chose these:
void fib(int arr[], int num){
int arrLength = num + 1;
if(num<0){
return;
}else if(num == 0){
arr[num] = 1;
}else if(num == 1){
arr[num-1] = 1;
arr[num] = 1;
}
}
But, as you can see, I did not find recursive method itself.
Here's sample output, for example, for call fib(arr, 5):
0 1 2 3 4 5
1 1 2 3 5 8
My main function for testing case:
int main(){
int n = 10, i;
int arr[n+1];
fib(arr, n);
for(i=0;i<=10;i++){
printf("%i ", arr[i]);
}
return 0;
}
Is there any other way to make base cases more "elegant"? Also, I would truly appreciate hints using which I could fill the array with numbers starting from 2 with recursive option.
You question is asking for recursion but the program you write is just using function, because of this reason I am writing very basic code for your better understanding, you can improve this after understanding the flow and functionality or ask new question with some work.
Below one is a working code tested on TurboC, I am sharing complete test code.
#include <stdio.h>
#include<conio.h>
#define MAX 100
void fib(int *arr, int num, int a, int b, int term){
if(term == 0 && term <= num){
arr[term] = 1;
term++;
fib(arr,num,a,b,term);
}else if(term ==1 && term <= num){
arr[term] = 1;
term++;
fib(arr,num,a,b,term);
}else if(term <= num){
arr[term] = a+b;
term++;
fib(arr,num,b,a+b,term);
}
}
void main()
{
int firstTerm = 1;//First term of fibbo series
int secondTerm = 1;//Second term of fibbo series
int tracker = 0; // Tracker to track how much term we printed
int i;//To run loop here to check array after recursive function
int ar[MAX],n=5;// n is number of term we want to print
clrscr();
fib(ar,n,firstTerm,secondTerm,tracker);//recursive function call
// below is printing array to check
for(i=0;i<=n;i++){
printf("%d\t",ar[i]);
}
getch();
}
One thing I have to suggest is, if n is 5 then you just get 1 1 2 3 5, In code I did according to your requirement, so here it will print 1 1 2 3 5 8
I'd state that the "elegant" solution should be a simple loop, without any recursion, but let's see how it could be done in the less efficient and more error prone way.
// I'll assume that the function signature can't be changed
void fib(int arr[], int num)
{
// In the general case, use the well known recurrence relation.
if ( num > 1 )
{
// Use recursion here to calculate the previous elements of the array.
fib(arr, /* ... */);
// ^^^^^^^^^ Can you figure out what index should be passed here?
// Then, calculate the element at index num using the recurrence relation.
arr[num] = arr[num - 1] + arr[num - 2];
// ^^^^^^^ ^^^^^^^ Note the indices.
// Are those values alredy known?
}
// When num is 0 or 1, we can't use the general formula. Can you tell why?
else if ( num >= 0 )
{
fib(arr, /* ... */);
// ^^^^^^^^^ Same as before.
arr[num] = 1;
}
// If num is less than 0, it just do nothing.
}

C qsort strange behaviour

I'm trying to do the following:
Allocate memory for array of dimension 7
Write the first 4 positions
Sort those 4 positions.
Write the remaining 3 positions
Sort the entire array.
I have the array (1,6,2,3), which after sorting becomes (1,2,3,6)
Then I write the remaining positions, which are (1,2,3,6,1,5,1)
After sorting it, I should be getting (1,1,1,2,3,5,6), but instead I'm getting
(6,2,3,1,1,5,1).
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int comp(const void* a, const void* b);
typedef struct{
int peso;
}aresta_;
int main(int argc, const char * argv[]) {
aresta_* array /*struct array, has field peso of type int*/;
int dim=7;
int dim_aux=4;
int i;
array = (aresta_*) malloc(dim * sizeof(aresta_));
array[0].peso=1;
array[1].peso=6;
array[2].peso=2;
array[3].peso=3;
printf("First sort:\n");
for(i=0; i<dim_aux; i++)
printf("%d ",array[i].peso);
printf("\n");
qsort(array, dim_aux, sizeof(array[0]), comp);
for(i=0; i<dim_aux; i++)
printf("%d ",array[i].peso);
printf("\n\n");
array[4].peso=1;
array[5].peso=5;
array[6].peso=1;
printf("Second sort:\n");
for(i=0; i<dim; i++)
printf("%d ",array[i].peso);
printf("\n");
qsort(array, dim, sizeof(array[0]), comp);
for(i=0; i<dim; i++)
printf("%d ",array[i].peso);
printf("\n");
}
My comp function:
int comp(const void* a, const void* b)
{
aresta_* a1 = (aresta_*)a;
aresta_* b1 = (aresta_*)b;
return a1->peso > b1->peso;
}
The Output:
First sort:
1 6 2 3
1 2 3 6
Second sort:
1 2 3 6 1 5 1
6 2 3 1 1 5 1
Program ended with exit code: 0
Where did I go wrong? Any help would be greatly appreciated.
OP's function only returned 0 and 1. #Weather Vane
As this "worked" for OP for the first 4 values is "luck".
The compare function needs to return 1 of 3 results: negative, 0 or positive.
The function shall return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
C11dr ยง7.22.5.2 3
int comp(const void* a, const void* b)
{
const aresta_* a1 = (const aresta_*)a;
const aresta_* b1 = (const aresta_*)b;
// return a1->peso > b1->peso;
return (a1->peso > b1->peso) - (a1->peso < b1->peso);
}
return (a1->peso > b1->peso) - (a1->peso < b1->peso); has advantages over return a1->peso - b1->peso;. This answer does not overflow. It is valid and functionally correct for all pairs of int. Various compilers recognize this idiom and produce tight code. int - int can overflow which is undefined behavior, UB.
int comp(const void* a, const void* b)
{
aresta_* a1 = (aresta_*)a;
aresta_* b1 = (aresta_*)b;
----> return a1->peso > b1->peso; <---- Watch carefully out! What it does!
}
The return line just checks merely greater or not. If,
a1->peso is greater, it returns 1
b1->peso is greater, it returns 0 (It is also not right result because zero must mean equal)
What about equality case that the values equal each other?
You didn't check the last case. To do you can write with if-else cases like
if(a1->peso > b1->peso) {
// ....
} else if (a1->peso < b1->peso) {
// ....
} else {
// equality case....
}
or simply do return a1->peso - b1->peso giving expected result that
> 0 so positive
< 0 so negative
== 0 so equal each other
According to chux nicely drawing attention to overflow point, it can be handled for overflow case.
#include <limits.h>
if ((b1->peso > 0 && a1->peso < INT_MIN + b1->peso) ||
(b1->peso < 0 && a1->peso > INT_MAX + b1->peso)) {
/* Handle error */
} else {
return a1->peso - b1->peso;
}

Finding odd integer's middle number

OK, so to be clear I'm counting the distance. If the number is even it's easy to calculate, however if it's odd hmm I have an idea but I can't apply it. The task sounds like so: I need to find the distance between objects. As for example given data:
4 // how many objects (n)
4 10 0 12 every object's distance
After sorting the numbers ( im using arrays ) the answer is: (4-0)+(12-10)=6;
So my code after sorting even numbers appears to be correct, however when the number is odd calculations are like so:
5 (n)
4 10 0 12 2
Answer= (2-0)+(4-2)+(12-10)=6;
All I need to do (I think) is for function to stop when there is half of odd number and do a certain function;Here's my code:
if(n%2!=0){
for(i=0;i<n;i++){
if(i==((n/2)+1)){ // THIS PART
length+=mas[(n/2)+1]-mas[n/2];
i++;
break;
}
length+=mas[i+1]-mas[i];
i++;
}
}
#include <stdio.h>
int sum_distance(int n, int a[n]){
if(n < 2)
return 0;
int sum = 0;
int i=0;
if(n & 1){//n is odd
sum = a[1] - a[0];
++i;
}
for(;i<n; i+=2){
sum += a[i+1] - a[i];
}
return sum;
}
int main(){
int a[4] = { 0, 4, 10, 12};
int b[5] = { 0, 2, 4, 10, 12};//they are sorted
printf("%d\n", sum_distance(4, a));//6
printf("%d\n", sum_distance(5, b));//6
return 0;
}

Prints out the first eight autmorphic numbers

Create a program that prints out the first eight[8] automorphic numbers. Output must be done
in the main() function.
Here's the code I worked on:
#include <stdio.h>
#include <conio.h>
main() {
int automorphic[8];
int n;
printf("\t\t\tAUTOMORPHIC\n\n\n");
for(n=1; n<8; n++ ){
if (n*n%10==n || n*n%100==n || n*n%1000==n);
}
printf("\t%d\n\n", automorphic [n]);
getch();
return 0;
}
I don't get why it only prints out 0? Is there something missing on my code? Or am I not doing the right thing at all?
Because:
You are examining only numbers 1 to 7 (only numbers 1, 5 and 6 in this range are automorphic).
You are not storing the number in the array.
You are printing only element 7 of the array (which is always 0).
You need to expect numbers bigger than that.
Additionally, automorphic numbers start at 0, not 1.
int main() {
long automorphic [8];
long i;
int n;
printf("\t\t\tAUTOMORPHIC\n\n\n");
i= 0 ;
n= 0 ;
while( n < 8 ) {
if( i*i%10==i || i*i%100==i || i*i%1000==i || i*i%10000==i || i*i%100000==i ) {
automorphic[n]= i ;
n++;
}
i++;
}
for(n= 0 ; n < 8 ; n++ ) {
printf("\t%d\n\n", automorphic[n] );
}
getch();
return 0;
}
Result should be:
0
1
5
6
25
76
376
625
You're close, but not quite there.
You are only testing the integers from 1 through 8 for the automorphic property. The question asks for the first 8 automorphic numbers, not which numbers less than 8 are automorphic.
Your if statement doesn't do anything if the condition is true.
You are printing the value of automorphic[n] but do not set any values in the automorphic array. Also, at the point the printf executes, n will be 8 because the for loop has already finished.

Resources