Find a series with recursion - c

I'm trying to write a recursive function that gets an array by pointer and its size, and returns the length of the longest series of identical adjacent numbers in the array (assume that there is a series),
For example:
array: {1 2 3 3 4 5 6 6 6 6 7 8}
returns-->: 4
but I don't know what's wrong with my function; I think I got it all wrong.
Any ideas on how to fix it?
#include <stdio.h>
#include <stdlib.h>
int LongestSeries(int* arr, int size, int* count, int* maxcount);
int main()
{
int i, size, *arr, count=0, maxcount=0;
// allocation an array (unknow size)
{
printf("Enter Size of the Array-->:");
scanf("%d", &size);
arr = (int*)malloc(size * sizeof(int));
if (arr == NULL)
{
printf("Error!!");
exit(1);
}
printf("Enter Numbers for the Array:\n");
for (i = 0; i < size; i++)
{
printf("Enter a Number-->:");
scanf("%d", &arr[i]);
}
}
for (i = 0; i < size; i++)
printf(" %d ", arr[i]);
printf("\n");
printf(" %d \n", LongestSeries(arr, size, count, maxcount));
free(arr);
return 0;
}
int LongestSeries(int* arr, int size, int* count, int* maxcount)
{
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
LongestSeries(arr, size - 1, count, maxcount);
if (*arr==arr[0])
return maxcount;
}

There're some problems in your code:
1 - The function LongestSeries expects a pointer on count and maxcount arguments but you passed the variable's values instead. You need to change the function call to send the address reference, like this: printf(" %d \n", LongestSeries(arr, size, &count, &maxcount));
2 - Your recursion termination condition is placed below the recursion call, causing the recursion never ending. You need to place it above the recursion call, preferably be the first statement in your recursive function.
3 - Since your count and maxcount arguments are pointers, you must use the dereference operator to work with the values instead its addresses:
from this:
if (arr[size-1] == arr[size-2])
count++;
if (maxcount<count)
maxcount = count;
to this:
if (arr[size-1] == arr[size-2])
++*count;
if (*maxcount < *count)
*maxcount = *count;
4 - The same applies in your return statement: you're returing the pointer, but your function expects an int to be returned, so:
from this:
if (*arr==arr[0])
return maxcount;
to this:
if (*arr==arr[0])
return *maxcount;
5 - Since you need the longest series, your count variable needs to start at 1, not 0, since the lowest possible series in a number sequence is 1, and not 0.
Hope it helps.

There are many problems with the posted code, as pointed out by #MarcLaurent. But fundamentally, the approach seems flawed. The point of writing recursive functions is not to make things difficult, but to make things simple. Problems that lend themselves to recursion can be broken down into smaller subproblems.
For the problem at hand, finding the length of the longest sequence of repeated numbers in an array, one recursive approach would acknowledge that this length is either the length of the initial sequence of repeated numbers, or the length of the longest sequence of repeated numbers in the remainder of the array. In code, this might look like:
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
Here, if the array contains no elements (the base case), 0 is returned. Otherwise, the larger of the length of the initial sequence, or the longest sequence in the remainder of the array is returned. MAX is a macro here, easily defined, and we have only to write a function that finds the length of the initial sequence. This can also be recursive, though it need not be.
A recursive function that finds the length of the initial sequence could look like:
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Here, if the array contains no elements (the base case), then the length is obviously 0, otherwise the return value is 1 added to the length of the initial sequence of the remainder of the array (if there is a next element, and that element is the same as the first element), or 0.
By breaking the problem down in this way, the solution is simple and easy to understand. Here is a full program implementing the above ideas:
#include <stdio.h>
#define MAX(X, Y) (X) > (Y) ? (X) : (Y)
size_t longest_seq(size_t, int *);
size_t init_seq(size_t, int *);
int main(void)
{
size_t arr_sz;
printf("Enter number of elements: ");
scanf("%zu", &arr_sz);
int arr[arr_sz];
printf("Enter array values:\n");
for (size_t i = 0; i < arr_sz; i++) {
scanf("%d", &arr[i]);
}
printf("Longest sequence of repeats: %zu\n", longest_seq(arr_sz, arr));
return 0;
}
size_t longest_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
size_t count = init_seq(sz, a);
return MAX(count, longest_seq(sz - count, a + count));
}
size_t init_seq(size_t sz, int *a)
{
if (sz == 0) {
return 0;
}
return 1 + ((sz > 1 && a[0] == a[1]) ? init_seq(sz - 1, a + 1) : 0);
}
Sample program interaction:
Enter number of elements: 12
Enter array values:
1 2 3 3 4 5 6 6 6 6 7 8
Longest sequence of repeats: 4

int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0){
return LongestSeries(arr + 1, size - 1, 1, maxcount);
} else {
if(arr[-1] == *arr){
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
} else {
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
}
}
int main(void){
int arr[] = {1, 2, 3, 3, 4, 5, 6, 6, 6, 6, 7, 8};
int size = sizeof(arr)/sizeof(*arr);
printf("%d\n", LongestSeries(arr, size, 0, 0));
}
reduce code:
int LongestSeries(int* arr, int size, int count, int maxcount){
if(size == 0)
return maxcount < count ? count : maxcount;
if(count == 0 || arr[-1] != *arr){
if(count > maxcount)
maxcount = count;
return LongestSeries(arr + 1, size - 1, 1, maxcount);
}
return LongestSeries(arr + 1, size - 1, count + 1, maxcount);
}

Related

C/C++ Bitwise operation university problem

Problem
Given a sequence of N integer values(possible values of N: 3, 5, 7, 9, 11 ...). Using at most one conditional operator(or conditional ternary operation), the program must determine whether it is true that every three elements the sequence increases and then decreases(sine sequence). Loops in a program can only be used to enumerate elements of a sequence.
Example
* *
* * * *
* * *
What I think
int compare_num(int num1, int num2)
{
return (int)(((num1 + num2) - sqrt((num1 - num2) * (num1 - num2))) / 2);
}
bool_t is_increasing2(int arr[], int size)
{
int tmin = arr[0];
int res = 0;
for (int i = 0; i < size - 1; i++)
{
tmin = compare_num(arr[i + 1], tmin);
res = tmin ^ arr[i + 1];
}
return res;
}
int main(void)
{
int arr[] = {10, 9, 8, 7, 6, 5};
int arr2[] = {1, 2, 3, 4, 5};
int res = is_increasing2(arr2, N);
if (res == 0)
{
printf("Decreasing\n");
}
else
{
printf("Increasing\n");
}
return 0;
}
I use this code to check, that sequence is increasing or not. But now I need to use it to check, that my sine sequence is sine and I can't use more ternary or if/else operators
There is what I have to real problem
bool_t is_increasingSine2(int arr[], int size){
int tmax = 0;
int res = 0;
for(int i = 0; i < size; i += 3){
for(int j = i; j < i + 2 && j < size - 1; j++){
tmax = compare_num(arr[j], arr[j + 1]);
res = tmax ^ arr[j + 1];
}
//There if res == 0 part of sine is increasing otherwise not, but what to do next???
}
return 0;
}
You do not need any conditional operators for this problem, but we will use one in the printf since it is suggested.
Rephrasing the problem as a requirement that each of the first two elements must be less than the one that follows it and each of the next two must be greater than the one that follows it makes it fairly simple to test:
#include <stdio.h>
#include <stdlib.h>
/* Given array Array with N elements, return true iff each of the first two
elements is less than the one following it, each of the next two is greater
than the one following it, and then repeating in a cycle until the end of
the array.
*/
static _Bool TestCriterion(int Array[], size_t N)
{
/* Iterate through each element of the array except the last (the one
with index N-1), since there is no element following the last element
to compare it to.
*/
for (size_t i = 0; i < N-1; ++i)
{
/* Set phase to 0 for the first two elements, 1 for the next two,
then 0, 1, 0, 1… Note that while "i & 2" has the value 0 or 2,
assigning it to a Boolean produces a value of 0 or 1.
*/
_Bool Phase = i & 2;
/* For phase 0, test whether the element with index i is less than
the element with index i+1, and return false (0) if it is not. For
phase 1, compare element i+1 with element i.
*/
if (! (Array[i+Phase] < Array[i+1-Phase]))
return 0;
}
// All elements passed the test, so return true (1).
return 1;
}
/* Compute the number of elements in an array by dividing the size of the
array by the size of an element.
*/
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int main(void)
{
int Array[] = { 1, 2, 3, 2, 1, 2, 3, 2, 1 };
printf("%s.\n", TestCriterion(Array, NumberOf(Array)) ? "Passes" : "Fails");
}

a function that works with array elements

I need to write a function that subtracts digits.
If user inputs 2345, the output should be 111 (5-4, 4-3, 3-2); another example would be 683, where the output should be 25 (3-8(abs value is taken), 8-6).
I have wrote the following code which works only when the size of the array is declared.
int subtraction(int arr[], int size) {
int sub = 0;
for (int i = 0; i < size-1; i++) {
sub = sub * 10 + abs(arr[i] - arr[i+1]);
}
return sub;
}
However, the number that the user inputs is random and can have various digits, so I don't know what limit to put in the for loop.
For example:
int arr[] = {1, 2, 55, 56, 65, 135}, i;
subtraction(arr, 6);
for (i=0; i<6; i++)
printf("%d ", arr[i]);
expected output: 0 0 0 1 1 22
The function is supposed to subtract the second-to-last digit from the last one, by the way , / from right to left / from a random number that the user inputs ; for example if the input is 5789, the output is supposed to be 211 (9-8, 8-7, 7-5); if user inputs a negative number, the program should take it's absolute value and then do the subtracting. If user input is a one digit number the result should be 0.
The function I wrote only works when the size of the array is declared. I don't know how to make it work when the size is undeclared (pointers and malloc are required I believe, as that's what I managed to find out by googling for ages, but unfortunately, I don't know how to do it).
please help?
You are not actually changing any values, here is the line you need to look at.
sub = sub * 10 + abs(arr[i] - arr[i+1]);
As you are printing the array you actually need to store the calculated value in the array again.
#include <stdio.h>
#include <stdlib.h>
int subtract(int n)
{
int factor = 1;
int total = 0;
int lastPlace = n%10;
n /= 10;
while (n>0)
{
total += (factor * abs((n%10) - lastPlace));
factor *= 10;
lastPlace = n%10;
n /= 10;
}
return total;
}
void subtractArray(int* arr, unsigned int size)
{
for (int i=0; i<size; ++i)
{
if (arr[i] < 0)
arr[i] = abs(arr[i]);
arr[i] = subtract(arr[i]);
}
}
int main()
{
int arr[] = {1, 2, 55, 56, 65, 135};
int size = sizeof(arr)/ sizeof(arr[0]);
subtractArray(arr, size);
for (int i=0; i<size; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
Here is a simple code that solve your problem :)
#include <stdio.h>
#include <stdlib.h>
int *subtraction(int arr[], int size)
{
int *sub = calloc(sizeof(int*) , size), i = 0, rev; //allocating memory
for (i = 0; i < size; i++)
{
rev = 0;
arr[i] = abs(arr[i]);
for (int a = 0; arr[i] != 0; arr[i] /= 10)
rev = (rev * 10) + (arr[i] % 10);
for (i; (rev / 10) != 0; rev /= 10) //the loop ends when rev = 0
sub[i] = ((sub[i] * 10) + abs( (rev % 10) - ((rev / 10) % 10) )); //easy math => for example rev = 21 > sub[i] = (0 * 10) + ( (21 % 10) - ((21 / 10) %10)) = abs(1 - 2) = 1;
}
return sub;
}
int main()
{
int arr[] = {-9533, 7, -19173}, i;
int len = sizeof(arr)/sizeof(arr[0]); //size of arr
int *sub = subtraction(arr, len);
for(int i = 0; i < len; i++) //for test
printf("%d ", sub[i]);
return 0;
}
output for {1, 2, 55, 56, 65, 135}:
0 0 0 1 1 22
output for {987654321, 123456789, 111111111} :
11111111 11111111 0
output for {38279}:
5652
output for {-9533, 7, -19173}:
420 0 8864
Well as for the array of undefined size. What you probably want is a dynamically allocated array.
Here we get the number of array elements based on user input, within limits, of course.
first we're gonna get the number from the user using fgets() which will give us a string, then we'll use strtol() to convert the number part to scalar (int). you can use scanf("%d", &n) if you want.
Then we can count the digits from that number, and that value will be the number of elements of our array.
#include <stdio.h>
#include <stdlib.h> //for strtol(), malloc() and NULL guaranteed
//you may also want to add
#include <limits.h>
#include <errno.h>
#define MAX_STRLEN 12 // can hold all digits of INT_MAX plus '\0' and a posible, AND very likely, '\n'
#define DEC 10 // for strtol base argument
/*
* I'm lending you my old get_n_dits() function that I used to count decimal digits.
*/
int get_n_dits(int dnum) {
unsigned char stop_flag = 0; //we'll use to signal we're done with the loop.
int num_dits = 1, dpos_mult = 1; //num_dits start initialized as 1, cause we're pretty sure that we're getting a number with at least one digit
//dpos_mult stands for digital position multiplier.
int check_zresult; //we'll check if integer division yields zero.
/**
* Here we'll iterate everytime (dnum / dpost_mult) results in a non-zero value, we don't care for the remainder though, at least for this use.
* every iteration elevates dpost_mult to the next power of ten and every iteration yielding a non-zero result increments n_dits, once we get
* the zero result, we increment stop_flag, thus the loop condition is no longer true and we break from the loop.
*/
while(!stop_flag) {
dpos_mult *= 10;
check_zresult = dnum / dpos_mult;
(check_zresult) ? num_dits++ : stop_flag++;
}
return num_dits;
}
int main(void) {
int num, ndits; //we'll still using int as per your code. you can check against INT_MAX if you want (defined in limits.h)
int *num_array = NULL; //let's not unintentionally play with an unitialized pointer.
char *num_str = malloc(MAX_STRLEN); //or malloc(sizeof(char) * MAX_STRLEN); if there's any indication that (sizeof(char) != 1)
printf("please enter a number... please be reasonable... or ELSE!\n");
printf(">>> ");
if(!fgets(num_str, MAX_STRLEN, stdin)) {
fprintf(stderr, "Error while reading from STDIN stream.\n");
return -1;
}
num = (int)strtol(num_str, NULL, DEC); //convert the string from user input to scalar.
if(!num) {
fprintf(stderr, "Error: no number found on input.\n");
return -1;
}
ndits = get_n_dits(num);
if(ndits <= 0) {
fprintf(stderr, "Aw, crap!\n");
return -1;
}
printf("number of digits: %d\n", ndits);
num_array = malloc(sizeof(int) * ndits); //now we have our dynamically allocated array.
return 0;
}

Find subsets of size K in N set [closed]

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 4 years ago.
Improve this question
The question is.
There is a set An, and it consists of integers from 1 to n.
An={1, 2, 3, ..., n}
Print all subsets of An with given size K. And it must be generated in order like the example below.
So for example, n=5 k=3
{1, 2, 3} {1, 2, 4} {1, 2, 5} {1, 3, 4} {1, 3, 5} {1, 4, 5} {2, 3, 4} ... {3, 4, 5}
I am not sure about if there is other way not using recursion. I did this with recursion but the problem is all test cases should be done within 1 sec.
When N and K are like 5, 3 and 12, 6 it is okay but
When it comes to like 50, 48 or 100, 95, it takes too long.
All problem should be done within 1 second.
I am having real struggle with this problem.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void subset(int n, int k, int arr[], int pos[], int index, int start){
int i, j;
if(index == k){
for(j=0; j<k; j++){
if(j==k-1)
printf("%d\n", pos[j]);
else{
printf("%d ", pos[j]);
}
}
return;
}
for(i=start; i<n; i++){
pos[index] = arr[i];
subset(n, k, arr, pos, index+1, i+1);
}
}
int main(){
int n, k, arr[100], index=0, start=0;
scanf("%d %d", &n, &k);
// 1<=n<=100 ; 1<=k<=n
if(n>100||n<1 && k>n||k<1)
return 0;
int i;
for(i=0; i<n; i++)
arr[i]=i+1;
int *pos = (int*)malloc(sizeof(int)*k);
time_t clockstart=0, clockend=0;
float gap;
clockstart = clock();
subset(n, k, arr, pos, index, start);
clockend = clock();
gap = (float)(clockend-clockstart)/(CLOCKS_PER_SEC);
printf("%f\n", gap);
return 0;
}
I think i should use something like tail recursion or vector in C++.
But I cant figure out with those.
The only way to increase your "speed algorithm" without touching it is to manually bufferise printf.
printf is a function that will do a system call at some time.
Every system call is costly, that's why each function that do some kind of system call usually do "buffering".
For malloc, in reallity, you allocate much more that you think (malloc(1) will not end up by allocating 1 octet but much more under the hood) and when you free the memory, in reallity it's not really released (that way, if you do another malloc, you will not do a system call but reuse the memory freed). Of course, it's OS dependant AND inmplementation dependend (all is under the hood).
You can see some system call under linux by using "strace".
The same thing apply to "printf" : since it will do a system call, there a buffer that retain what you want to print and do the print only time to time.
So when the printf's buffer is really printed ?
We can't know, it's implementation defined (event the man page of printf doesn't say a word about the printf buffering), but usually, it can be at 3 occasion :
when the buffer is full
when you force the flush by using fflush
when you have the '\n' caracter in what you want to print.
Since you do an "\n" at each subnet, printf may have to do the system call every time : it's time consumming.
By using a buffer and print in the buffer instead of stdout, you can speed up your code :
#define BUF_LEN 2048
typedef struct mybuf {
char buffer[BUF_LEN];
size_t len;
} mybuf;
// For convenience, I use global varaible, but it's BAD
mybuf buf = {.buffer = "", .len = 0};
void MyBuf_PrintOnStdout(void)
{
write(1, buf.buffer, buf.len);
buf.len = 0;
}
void MyBuf_Flush(void)
{
MyBuf_PrintOnStdout();
fflush(stdout);
}
void MyBuf_PrintInteger(int integer)
{
int printedLen;
// An 64bit integer take 20digit + 1 char for potential "-"
// So 21 is the max len for an integer.
// Of course, if your int is bigger than 64bit, this if is false.
if (buf.len + 21 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
printedLen = sprintf(buf.buffer + buf.len, "%d", integer);
// Error check (printedLen < 0 == error)
buf.len += printedLen;
}
void MyBuf_PrintCharacter(char character)
{
if (buf.len + 1 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
buf.buffer[buf.len] = character;
++buf.len;
}
void subset(int n, int k, int arr[], int pos[], int index, int start)
{
if (index == k) {
for (int j = 0; j < k; ++j) {
MyBuf_PrintInteger(pos[j]);
MyBuf_PrintCharacter(j == k-1 ? '\n' : ' ');
}
return;
}
for(int i = start; i<n; i++){
pos[index] = arr[i];
subset(n, k, arr, pos, index+1, i+1);
}
}
Don't forget to call "MyBuf_Flush" at the end, because without it you will probably missing some printing.
Edit : With the complet code, I do some testing.
While it's true there is improvement (N = 30, k = 20 with your code take ~88s and with the write take ~78s), it really too poor to make that work on less than 1s.
Is it possible to resolve your problem without having a supercalculator ?
Another edit : Okay, I have confused the meaning of "should" and "must", sorry. English is not my motherlanguage. (I thinked that you must use recursion).
Since you are free to not use recursion, here something interesting :
I've implemented recursion and not recursion of n=30, k=20.
For each implementation, I have enable and disabled the printing.
The result are clear :
recursion, printing with printf : ~88s
recursion, printing buffered : ~78s
recursion, no printing : ~7s
--
no recursion, printing with printf : ~80s
no recursion, printing buffered : ~70s
no recursion, no printing : ~0,47s
So in conclusion, it's more the printing part that is really taking time than finding the solution itself.
Here the no recursive implementation :
#define BUF_LEN 4096
typedef struct mybuf {
char buffer[BUF_LEN];
size_t len;
} mybuf;
// For convenience, I use global varaible, but it's BAD
mybuf buf = {.buffer = "", .len = 0};
void MyBuf_PrintOnStdout(void)
{
/*buf.buffer[buf.len] = '\0';
printf("%s", buf.buffer);*/
write(1, buf.buffer, buf.len);
buf.len = 0;
}
void MyBuf_Flush(void)
{
MyBuf_PrintOnStdout();
fflush(stdout);
}
void MyBuf_PrintInteger(int integer)
{
int printedLen;
if (buf.len + 21 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
printedLen = sprintf(buf.buffer + buf.len, "%d", integer);
// Error check (printedLen < 0 == error)
buf.len += printedLen;
}
void MyBuf_PrintCharacter(char character)
{
if (buf.len + 1 >= BUF_LEN) {
MyBuf_PrintOnStdout();
}
buf.buffer[buf.len] = character;
++buf.len;
}
void subset_no_recursion(int n, int k)
{
int pos[k];
for (int i = 0; i < k; ++i) {
pos[i] = k - i;
}
for (;;) {
// Last digit incrementation
while (pos[0] <= n) {
/* print
for (int i = k - 1; i >= 0; --i) {
MyBuf_PrintInteger(pos[i]);
MyBuf_PrintCharacter(i == 0 ? '\n' : ' ');
}*/
++pos[0];
}
// We find where we can increment the digit without overflow N
int pivot = 1;
while (pos[pivot] == n - pivot) {
++pivot;
}
if (pivot == k) {
return;
}
++pos[pivot];
while (pivot) {
pos[pivot - 1] = pos[pivot] + 1;
--pivot;
}
}
}
void subset_recursion(int n, int k, int pos[], int index, int start)
{
if (index == k) {
for (int i = 0; i < k; ++i) {
MyBuf_PrintInteger(pos[i]);
MyBuf_PrintCharacter(i == k-1 ? '\n' : ' ');
}
return;
}
for (int i = start; i < n; i++) {
pos[index] = i + 1;
subset_recursion(n, k, pos, index + 1, i + 1);
}
}
#define N 30
#define K 20
int main(void)
{
int pos[K];
time_t clockstart;
time_t clockend;
clockstart = clock();
subset3(N, K);
clockend = clock();
printf("%f\n", ((float)(clockend - clockstart)) / CLOCKS_PER_SEC);
return 0;
}

Read an array recursively

I am learning how to apply recursion to arrays.
For example, I usually read arrays itiratively, this way:
void read_array(int *a, int n){
int i;
for(i = 0; i < n; ++i)
scanf("%d", &a[i]);
return;
}
I would like to read an array recursively. I wrote the following function:
void read_array(int *a, int n){
int i = n - 1;
if (n < 0)
return;
else{
if(scanf("%d", &a[n - 1 - i]) == 1){
read_array(a, n - 1);
return;
}
}
}
It compiles, but when running it trows a segmentation fault error. It confuses me since the function contemplates a base case 0 that should stop it.
Your calculation of the array index is wrong. This line:
if(scanf("%d", &a[n - 1 - i]) == 1){
assumes the initial value of n, but at the same time, you decrease n with every recursion step. That being said, it shouldn't crash but just repeatedly write the first element of a, because with i = n - 1, n - 1 - i is always zero.
The idiomatic way to write such a recursion would be to recurse on i:
void read_array(int *a, int n, int i)
{
if (i < n)
{
if(scanf("%d", &a[i]) == 1)
{
read_array(a, n, i+1);
}
}
}
and call it with the initial value for i, e.g. read_array(a, 10, 0) for reading a 10-element array.
In practice, recursion in C is to be avoided.*
* Functional languages can typically optimize recursion, C just uses the call stack with a lot of overhead.
In this example, the theoretical purpose of recursion for writing a pure function is somewhat defeated with a function returning void. If this is just about learning the principle, the functions actually should return something. You could for example create a functional "list builder":
#include <stdio.h>
#include <stdlib.h>
// place the side effect in a separate function
int getValue(void)
{
// could have `scanf()` here:
return rand();
}
typedef struct List
{
int a[10];
size_t length;
} List;
// non-functional helper to get around limitations of C:
// (if it could initialize result directly with the new values, it would
// be functional)
List listAppend(List list, int val)
{
List result = list;
result.a[result.length++] = val;
return result;
}
// recursive function without side effects:
List buildList(List list, int (*value)())
{
if (list.length >= 10) return list;
return buildList(listAppend(list, value()), value);
}
int main(void)
{
List myList = buildList((List){0}, &getValue);
for (size_t i = 0; i < myList.length; ++i)
{
printf("myList.a[%zu] is %d\n", i, myList.a[i]);
}
}
There is a bug in the function.
As the variable i is initialized the following way
int i = n - 1;
then the second argument in this call
scanf("%d", &a[n - 1 - i])
is evaluated like
scanf("%d", &a[n - 1 - (n - 1)])
that is it is always equal to zero
scanf("%d", &a[0])
As the recursive function is called with the same value of the pointer a then all entered values are assigned to a[0]. All other elements of the array are still uninitialized.
Though this does not serve as a reason for the abnormal execution of the function.
It is possible that there is used a big array and the stack is too small to call the function recursively.
In any case the function can be defined more simply and correctly the following way
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
Take into account as the input can be interrupted by the user. In this case the function returns the number of initialized elements of the array.
Here is a demonstrative program.
#include <stdio.h>
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
#define N 10
int main(void)
{
int a[N];
size_t n = read_array( a, N );
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
If to enter sequence of numbers
0 1 2 3 4 5 6 7 8 9
then the output will be
0 1 2 3 4 5 6 7 8 9
Example:
int read_array_aux(int *i, int *n) {
if (i == n) {
return 0;
}
if (scanf("%d", i) != 1) {
return -1;
}
return read_array_aux(i + 1, n);
}
int read_array_aux2(int *a, size_t i, size_t n) {
if (i == n) {
return 0;
}
if (scanf("%d", a + i) != 1) {
return -1;
}
return read_array_aux2(a, i + 1, n);
}
int read_array(int *a, size_t n) {
return read_array_aux(a, a + n);
// return read_array_aux2(a, 0, n);
}
First, condition n<0 is wrong. Probably this is the cause of segfault.
Also, why even bother about calculating the index? When processing any kind of list recursively it's worth to grasp the concept of head (first element of list) and tail (everything except head) of the list. So, filling an array recursively would be defined as (in pseudo code):
void read_array() {
read_head();
read_tail();
}
What is head? It's the first element of current array. What's the tail? The array starting from next element. So, read_tail is equivalent of read_array, but with the beginning moved forward by one element.
And, finally, to gather everything into one place:
void read_array(int *a, int n) {
if(n<=0) {
return;
} else {
if(scanf("%d", a) == 1) {
read_array(a+1,n-1);
}
}
}
As other answers have mentioned, your handling of n is leading to problems. You can return 0 from the base case of sz == 0, otherwise return the result of the next recursive call, or -1 if scanf() fails. At each recursive call, increment a and decrement sz. The value returned in the calling function should be checked for input errors: 0 on success, -1 on failure.
Note that this is a tail recursion, which should be optimized by most good compilers.
#include <stdio.h>
int read_array(int *a, size_t sz);
int main(void)
{
int arr[5];
puts("Enter array elements:");
if (read_array(arr, 5) != 0) {
fprintf(stderr, "Input error\n");
} else {
for (size_t i = 0; i < 5; i++) {
printf("%8d", arr[i]);
}
putchar('\n');
}
return 0;
}
int read_array(int *a, size_t sz)
{
if (sz == 0 ) {
return 0;
}
if (scanf("%d", a) == 1){
return read_array(a + 1, sz - 1);
} else {
return -1;
}
}
Sample interaction:
Enter array elements:
1 2 3 4 5
1 2 3 4 5
Enter array elements:
1 2 3 x 5
Input error

C - Recursion array checking

i would like to ask about the array recursion in C, Let say i have an array in float
float arr[] = {12.5, 5.5, 6.0, 18.0};
i want to count the number which is greater than 10, so the result should be 2. However, below is what i did
int cntArray(float arr[], int size)
{
int number = 0;
if((cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
int main()
{
float arr[] = {12.5, 5.5, 6.0, 18.0};
int result;
result = cntArray(arr, 4);
printf("The result is : %d", result);
}
But it returns 0 as result, any solutions for it? Thanks
Another example:
int cntArray(float arr[], int size) {
if (!size) return 0;
return (arr[0] > 10.0 ? 1 : 0) + cntArray(&arr[1], size - 1);
}
Edit #1 (in reply to comment):
This simply evaluate through a ternary operator (?:) if the first index of arr[] is greater than 10.0. If true, 1 will be the lvalue, otherwise will be 0. The lvalue of cntArray(&arr[1], size - 1) (which will process the next element on the array after decrementing size and if size is different than 0, which in this case will immediately return 0) will be added to the lvalue of the ternary operator. Applying this recurring logic, the aftermath will be the number of elements in the array that are greater than 10.0.
Your cntArray() function lacks a recursion base case, and also seems to hardcode the wrong value (5 instead of 10).
It should be something like:
int cntArray(const float *arr, size_t size)
{
if(size > 0)
{
/* Count the first element, then recurse. */
const int count = arr[0] >= 10.f;
return count + cntArray(arr + 1, size -1);
}
return 0;
}
Your logic is severely flawed: You don't actually check if a value in the array is larger than 10. you also always return number which will always be zero meaning the condition will always be false.
int cntArray(float arr[], int size){
int number = 0;
if((number = cntArray(&arr[1], size - 1))>=5)
number++;
return number;
}
You maybe want to change 5 to 10.
int cntArray(float arr[], int size) {
int number = 0;
if (size > 0) number = cntArray(&arr[1], size - 1);
if (arr[0] > 10) number += 1;
return number;
}
I'm not sure what does this portion of your code does.
if((cntArray(&arr[1], size - 1))>=5)
number++;
I would something like this instead:
int cntArray(float arr[], int index, int size){
if (index == size) return 0; // base case
int rest = cntArray(arr, index + 1, size); // how many elements are greater
// then 10 in rest of the array
if (arr[index] > 10)
return rest + 1;
else
return rest;
}
And call it in the main like this:
cntArray(arr, 0, 4);

Resources