Hi i wanted to tranform this code into a recursive function:
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
My approach is :
int rec_help(int*a, int length);
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
else{
return rec_help(a,length) + rec_help(a+1,length-1) ;
}
}
int rec_help(int*a, int length){
if(a == 0 || length <= 0) return 0;
else{
int tmp = a[0];
return tmp + a3(a+1,length-1);
}
}
But i'm not getting it right.
With a3() i wanted to simulate the first for loop, and i think there is my problem :D
And with rec_help() the second loop and the body, but im mixing things here.
I would appreciate any kind of help :)
Because you have 2 loop, if you want your function to be recursive, you will need 2 recursive functions, one which will do the job of the first loop and a second to do the job of your second loop...
Something like that should work :
int a3_rec(int *a, int length)
{
if (length == 0)
return (0);
return (*a + a3_rec(a + 1, length - 1));
}
int a3_rec_hat(int *a, int length)
{
if (a == 0 || length == 0)
return (0);
return (a3_rec(a, length) + a3_rec_hat(a + 1, length - 1));
}
I hope I've helped you :)
As a general rule, when you transform loops into recursion, every loop becomes a function and any non-local variables it uses become arguments.
Your original code is
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
for(int j = i; j < length; j++) {
sum += a[j];
}
}
return sum;
}
Let's start with the innermost loop. It uses j, i, length, sum, and a from the surrounding scope.
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pjj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
for(int i = 0; i < length; i++) {
int j = i;
a3_loop0(&j, length, &sum, a);
}
return sum;
}
This is a very literal and mechanical translation. Every mutable variable has become a pointer (in C++ you'd use references for this), which leads to somewhat ugly and non-functional code (well, code that doesn't use idiomatic functional style). But it works, and we can proceed to the next loop in the same way:
void a3_loop0(int *pj, int length, int *psum, int *a) {
if (*pj < length) {
*psum += a[*pj];
(*pj)++;
a3_loop0(pj, length, psum, a);
}
}
void a3_loop1(int *pi, int length, int *psum, int *a) {
if (*pi < length) {
int j = *pi;
a3_loop0(&j, length, psum, a);
(*pi)++;
a3_loop1(pi, length, psum, a);
}
}
int a3(int* a, int length) {
if(a == 0 || length <= 0) return 0;
int sum = 0;
int i = 0;
a3_loop1(&i, length, &sum, a);
return sum;
}
Technically we're done now, but there's a number of things we can clean up.
The first thing I'd do is to change the type of a to const int * because a3 never modifies any of its elements.
The second thing I'd do is to hoist the loop variables *pi / *pj into their functions; they don't really need to be pointers to mutable objects elsewhere.
void a3_loop0(int j, int length, int *psum, const int *a) {
if (j < length) {
*psum += a[j];
a3_loop0(j + 1, length, psum, a);
}
}
void a3_loop1(int i, int length, int *psum, const int *a) {
if (i < length) {
a3_loop0(i, length, psum, a);
a3_loop1(i + 1, length, psum, a);
}
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
int sum = 0;
a3_loop1(0, length, &sum, a);
return sum;
}
This already simplifies and shortens the code a bit.
The next step is to actually return something from these helper functions. Currently they use *psum as an accumulator and return void. We can keep the use of an accumulator but return the result directly (instead of through an output parameter) as follows:
void a3_loop0(int j, int length, int sum, const int *a) {
if (j < length) {
return a3_loop0(j + 1, length, sum + a[j], a);
}
return sum; // this was implicit before; "return sum unchanged"
}
void a3_loop1(int i, int length, int sum, const int *a) {
if (i < length) {
return a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a);
}
return sum; // ditto
}
int a3(const int *a, int length) {
if (a == 0 || length <= 0) return 0;
return a3_loop1(0, length, 0, a);
}
This version of the code is "purely functional" in that it never modifies any variables; it only passes and returns values to and from functions, respectively.
If we wanted to, we could get rid of all if statements and write everything as expressions:
void a3_loop0(int j, int length, int sum, const int *a) {
return j < length
? a3_loop0(j + 1, length, sum + a[j], a)
: sum;
}
void a3_loop1(int i, int length, int sum, const int *a) {
return i < length
? a3_loop1(i + 1, length, a3_loop0(i, length, sum, a), a)
: sum;
}
int a3(const int *a, int length) {
return a == 0 || length <= 0
? 0
: a3_loop1(0, length, 0, a);
}
I'll post this because I see the other answers use 1 function per loop which isn't necessary.
You can have just 1 recursive function:
int a3_impl(int* a, int length, int i, int j)
{
if (i >= length)
return 0;
if (j >= length)
return a3_impl(a, length, i + 1, i + 1);
return a[j] + a3_impl(a, length, i, j + 1);
}
int a3(int* a, int length)
{
if(a == 0 || length <= 0)
return 0;
return a3_impl(a, length, 0, 0);
}
Related
#include<stdio.h>
#include<assert.h>
const char *authour ="Alexandre Santos";
int ints_get(int *a)
{
int result = 0;
int x;
while (scanf("%d", &x) !=EOF)
{
a[result++] = x;
}
return result;
}
int sum_odd(const int *a, int n)
{
int sum = 0;
for(int i = 0; i < n; i++)
if(i%2 != 0)
sum += a[i];
return sum;
}
int sum_all(const int *a, int n)
{
int sum = 0;
for(int i = 0; i < n; i++)
sum = sum + a[i];
return sum;
}
int final(const int *a, int n)
{
return sum_all(a,n) - sum_odd(a,n);
}
void unit_test_even_values_minus_odd_values(void){
int a1[8] = {1,2,3,4,5,6,7,8};
assert(final(a1, 8) == 4);
assert(final(a1, 6) == 3);
assert(final(a1, 4) == 2);
assert(final(a1, 2) == 1);
}
void unit_tests(void){
unit_test_even_values_minus_odd_values();
}
void test_sum(void)
{
int a[100];
int n = ints_get(a);
int total = final(a,n);
printf("%d\n", total);
}
int main()
{
test_sum();
return 0;
}
I have this program but I don't understand how the assertions work here, my main question is what the second number represents. For example I understand that assert(final(a1, 8) == 4) I understand that a1 is the array determined in the line above but I can't understand the second number (8).... Can anyone explain to me how this works? I tried to search a little bit but I still don't understand...
The second argument to final is the number of values to work on from that array, starting from the beginning.
final(a1, 8) sums all eight values. final(a1, 6) only sums the first six values.
I'm really newbie to c programing, and I have no idea how can I make it work.
I want to make sort function that sorting array of integers by using 2 argument.
I want to use recursive on sort function. and sorting from end of array to first. by ascending order.
void ft_sorting(int *arr, int size);
but I don't know what went wrong. It totally out of my understanding with pointer and array. right now I really have no idea. Can some one pointing what I did wrong. And what I need to learn and fix. Thank you!
void ft_recure(int *a, int *b, int j, int k)
{
if (--j >= 0)
{
if (a[k] < b[j])
{
a[k] = b[j];
}
else
{
ft_recure(a[k], b[j], j, k);
}
}
else
return a[k];
}
void ft_sort(int *tab, int size)
{
int i;
int h;
while (size > 0)
{
i = size;
h = i;
tab[size] = ft_recure(tab, tab, i, h);
size--;
}
}
and also I try this.
int ft_recurs(int x, int y, int a, int b)
{
int j;
j = a;
if( a > 0)
{
if(*x < *(y - 1);)
{
b = *(y - 1);
*x = b;
}
ft_recurs(*x,*(y - 1),a - 1, b);
}
else
{
return *x;
}
}
void ft_sort_int_tab(int *tab, int size)
{
int memo;
int i;
while(--size >= 0)
{
i = size;
tab[size] = ft_recurs(tab[i], tab[size], i, memo);
}
}
In the first approach, you did improper when calling API again:
void ft_recure(int *a, int *b, int j, int k)
{
if (--j >= 0)
{
if (a[k] < b[j])
{
a[k] = b[j];
}
else
{
ft_recure(a[k], b[j], j, k);
}
}
else
return a[k];
}
a and b input to API ft_recure is a pointer but in ft_recure(a[k], b[j], j, k); it is value. You should correct this as: ft_recure(&a[k], &b[j], j, k); if you expect to input the address of k and j elements.
In your alternative usage:
int ft_recurs(int x, int y, int a, int b)
{
int j;
j = a;
if( a > 0)
{
if(*x < *(y - 1);)
{
b = *(y - 1);
*x = b;
}
ft_recurs(*x,*(y - 1),a - 1, b);
}
else
{
return *x;
}
}
The input is value but in the function you are using *x andn *(y-1) is not really a proper way. May be you could try int ft_recurs(int x[], int y[], int a, int b). But if so, you also need to provide pointer address at ft_recurs(*x,*(y - 1),a - 1, b); and then the issue come back to similar to first approach.
So I have been tasked from school with writing a function that gets an int size parameter, an array of integers and an int flag, and returns an array of pointers, that holds pointers to the cells of the original int array in a sorted manner (ascending if flag==1, else descending).
I wrote it basically on the principle of merge sort, but for some reason I am getting a runtime error that occurs when the program tries to execute line 123 (free a temp int** array)
any idea why it happens and if its fixable?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 100
int **pointerSort(int *arr, unsigned int size, int ascend_flag);
void ptrMerge(int arr[], int start, int mid, int end, int *ptrArr[], int flag);
void pmergeSort(int arr[], int start, int end, int *ptrArr[], int flag);
void main() {
unsigned int size, i;
int arr[SIZE];
int **pointers;
int ascend_flag;
printf("Please enter the number of items:\n");
scanf("%u", &size);
for (i = 0; i < size; i++)
scanf("%d", &arr[i]);
scanf("%d", &ascend_flag);
pointers = pointerSort(arr, size, ascend_flag);
printf("The sorted array:\n"); //Print the sorted array
//printPointers(pointers, size);
for (i = 0; i < size; i++)
printf("d%\t%d", *pointers[i], pointers[i]);
free(pointers);
}
int **pointerSort(int *arr, unsigned int size, int ascend_flag) {
int **sortedArr;
sortedArr = (int**)malloc(size * sizeof(int*));
pmergeSort(arr, 0, size - 1, sortedArr, ascend_flag);
return sortedArr;
}
void pmergeSort(int arr[], int start, int end, int *ptrArr[], int flag) {
if (start < end) {
int mid = (start + end) / 2;
pmergeSort(arr, start, mid, ptrArr, flag);
pmergeSort(arr, mid + 1, end, ptrArr, flag);
ptrMerge(arr, start, mid, end, ptrArr, flag);
}
}
void ptrMerge(int arr[], int start, int mid, int end, int *ptrArr[], int flag) {
int i, k = 0;
int p = start, q = mid + 1;
int **tempArr;
tempArr = (int**)malloc((end - start + 1) * sizeof(int*));
for (i = start; i <= end; i++) {
if (arr[p] < arr[q]) {
tempArr[k] = &arr[p];
k++;
p++;
} else { //(arr[p] > arr[q])
tempArr[k] = &arr[q];
k++;
q++;
}
}
while (p <= mid) {
tempArr[k] = &arr[p];
k++;
p++;
}
while (q <= end) {
tempArr[k] = &arr[q];
k++;
p++;
}
if (flag == 1) {
for (i = 0; i < k; i++)
ptrArr[start] = tempArr[i];
start++;
}
} else {
for (i = k - 1; i >= start; i--) {
ptrArr[start] = tempArr[i];
start++;
}
}
for (i = 0; i < k; i++)
printf("%x\t%d\n", ptrArr[i], *ptrArr[i]);
printf("\n");
free(tempArr);
}
You get a segmentation fault because the ptrMerge function corrupts the memory by writing past the end of the tempArr allocated array.
The first loop iterates end - start + 1 times, potentially accessing arr beyond the end of the slices.
The loop continues until p >= mid and q >= end, writing to tempArr[k] with k greater or equal to the number of elements allocated with malloc().
The logic is flawed: you compare the elements of arr at offsets p and q instead of indirecting through the array ptrArr.
Here is a modified version:
int **pointerSort(int *arr, int size, int ascend_flag) {
int **sortedArr = (int**)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
sortedArr[i] = &arr[i];
}
pmergeSort(sortedArr, 0, size - 1, ascend_flag);
return sortedArr;
}
void pmergeSort(int *ptrArr[], int start, int end, int flag) {
if (start < end) {
int mid = start + (end - start) / 2;
pmergeSort(ptrArr, start, mid, flag);
pmergeSort(ptrArr, mid + 1, end, flag);
ptrMerge(ptrArr, start, mid, end, flag);
}
}
void ptrMerge(int *ptrArr[], int start, int mid, int end, int flag) {
int i, k, n = end - start + 1;
int p = start, q = mid + 1;
int **tempArr = (int**)malloc(n * sizeof(int*));
for (k = 0; k < n; k++) {
if (p <= mid && (q >= end || *ptrArr[p] <= *ptrArr[q])) {
tempArr[k] = ptrArr[p++];
} else {
tempArr[k] = ptrArr[q++];
}
}
if (flag == 1) {
for (k = 0; k < n; k++)
ptrArr[start + k] = tempArr[k];
}
} else {
for (k = 0; k < n; k++) {
ptrArr[end - k] = tempArr[k];
}
}
free(tempArr);
}
Also note that main() must be defined with a return type int and the loop that prints the values is broken. It should read:
for (i = 0; i < size; i++)
printf("%d\t", *pointers[i]);
printf("\n");
So you should use :
int main(void)
In this while q is never updated so i guess infinite loop?
while (q <= end)
{
tempArr[k] = &arr[q];
k++;
p++;
}
Can you provide me your inputs and output you want?
I have tried your code and i'm not getting your error.
Is is possible to find the largest sum contiguous sub array using recursion such that the function would directly return the output.
Below is my solution where I store the max subarray ending at each index and then find the largest among those in the print() function. However, I want the following
Use recursion
Use the recursive function to directly output the final result.
My code which uses a recursive function and a helper print() function to find the largest among those numbers
#include <stdio.h>
//int a[] = {-6,60,-10,20};
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int main(void)
{
fun(len-1);
printf("max sub array == %d\n",print(maxherearray));
printf("\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[n];
maxherearray[n] = max(a[n], a[n]+fun(n-1));
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
EDIT : Posting the print() function which I somehow missed out
//Please make sure that #include <limits.h> is added
int print(int a[])
{
int i = 0;
int largest = INT_MIN;
printf("largest == %d\n",largest);
for(i=0;i<len;i++)
{
if(a[i] > largest)
largest = a[i];
}
return largest;
}
Generally, your algorithm logic is OK. It's like,
f(0) = a(i);
f(i) = max(f(i-1) + a(i), a(i));, get the middle result array
max(0, f(1), f(2), ... , f(n-1)), get the final max_sub result
And you designed a function namedfun for #2, and a helper print() for #3.
Now, (I guess ) what you'd like is to combine #2 and #3 together, i.e., to utilise the middle results of #2 to avoid extra computing/memory space. In terms of your original algorithm logic, here are some possible ways, such as
Add a parameter in your fun to keep max_sub result
int fun(int n, int *result)// add int *result to return max_sub
{
int max_here = 0;
if(n==0){
return a[n];
}
max_here = max(a[n],a[n]+fun(n-1, result));
*result = max(*result, max_here);
return max_here;
}
//...
int main(void)
{
int result = 0;
fun(len-1, &result);
printf("max sub : %d\n", result);
}
Use a global variable (Oh!) to get max_sub in time
int g_maxhere = 0;
int fun2(int n)
{
if(n==0){
return a[n];
}
g_maxhere = max(g_maxhere, max(a[n],a[n]+fun2(n-1)));
return max(a[n], a[n]+fun2(n-1));
}
//...
int main(void)
{
fun2(len-1);
printf("max sub:%d\n",g_maxhere)
}
In fact, your original solution of using a helper function can make your algorithm more clear.
Introduce two global variables, start_idx and end_idx to track the start and end indices of the largest contiguous subarray. Update these variables accordingly in the recursive function.
#include <stdio.h>
/* int a[] = {-6,60,-10,20}; */
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int fun(int n);
int max(int a, int b);
int find_max(int a[], int len);
void print_array(int a[], int start_idx, int end_idx);
int start_idx = 0; // Start of contiguous subarray giving max sum
int end_idx = 0; // End of contiguous subarray giving max sum
#define NEG_INF (-100000)
int max_sum = NEG_INF; // The max cont sum seen so far.
int main(void)
{
start_idx = 0;
end_idx = len - 1;
maxherearray[0] = a[0];
printf("Array a[]: ");
print_array(a, 0, len-1);
printf("\n");
// Compute the necessary information to get max contiguous subarray
fun(len - 1);
printf("Max subarray value == %d\n", find_max(maxherearray, len));
printf("\n");
printf("Contiguous sums: ");
print_array(maxherearray, 0, len - 1);
printf("\n");
printf("Contiguous subarray giving max sum: ");
print_array(a, start_idx, end_idx);
printf("\n\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[0];
int max_till_j = fun(n - 1);
// Start of new contiguous sum
if (a[n] > a[n] + max_till_j)
{
maxherearray[n] = a[n];
if (maxherearray[n] > max_sum)
{
start_idx = end_idx = n;
max_sum = maxherearray[n];
}
}
// Add to current contiguous sum
else
{
maxherearray[n] = a[n] + max_till_j;
if (maxherearray[n] > max_sum)
{
end_idx = n;
max_sum = maxherearray[n];
}
}
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
// Print subarray a[i] to a[j], inclusive of end points.
void print_array(int a[], int i, int j)
{
for (; i <= j; ++i) {
printf("%d ", a[i]);
}
}
int find_max(int a[], int len)
{
int i;
int max_val = NEG_INF;
for (i = 0; i < len; ++i)
{
if (a[i] > max_val)
{
max_val = a[i];
}
}
return max_val;
}
I am writing a program to add two large numbers in C.
My integer array result holds the sum of the two numbers (which were also stored in arrays).
For example, if the result array is [0,0,3,2] (actual array size is 20)
If 32 is my actual result, how can I display the contents of the result array without the leading zeros ?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BASE 10
void align(int A[],int n);
void add(int A[],int B[], int C[]);
void Invert(int* a, int n);
int main(int argc, char** argv){
char input1[20];
char input2[20];
int size = 20;
int a;
int b;
int num1[20];
int num2[20];
int result[20];
int length1 = strlen(argv[1]);
int length2 = strlen(argv[2]);
int i = 0;
for (i=0;i<length1;i++){
input1[i] = argv[1][i];
}
for (i=0;i<length2;i++){
input2[i] = argv[2][i];
}
a=atoi(input1);
b=atoi(input2);
align(num1,a);
align(num2,b);
add(num1,num2,result);
Invert(result,size);
for (i=0;i<20;i++){
printf("%d",result[i]);
}
return 0;
}
void align (int A[], int n){
int i = 0;
while (n) {
A[i++] = n % BASE;
n /= BASE;
}
while (i < 20) A[i++] = 0;
}
void add (int A[], int B[], int C[]) {
int i, carry, sum;
carry = 0;
for (i=0; i<20; i++) {
sum = A[i] + B[i] + carry;
if (sum >= BASE) {
carry = 1;
sum -= BASE;
} else
carry = 0;
C[i] = sum;
}
if (carry) printf ("overflow in addition!\n");
}
void Invert(int* a, int n)
{
int i;
int b;
for(i=0; i<n/2; i++){
b = a[i];
a[i] = a[n-i-1];
a[n-i-1] = b;
}
}
`
To get the actual digits (I assume that each digit is stored as a byte in an array of 20 bytes, lowest digit at highest index), you do something like this:
int i;
int size = sizeof(thearray) / sizeof(thearray[0]);
/* find first non-0 byte, starting at the highest "digit" */
for (i = 0; i < size - 1; ++i)
if (thearray[i] != 0)
break;
/* output every byte as character */
for (; i < size; i++)
printf("%c", thearray[i] + '0'); /* 0 --> '0', 1 --> '1', etc. */
printf("\n");
You can do this by below code:-
int flag=1;
for(i=0;i<20;i++)
{
if(flag==1&&array[i]!=0)
flag=0;
if(flag!=1)
{
printf("%d",array[i]);
}
}
This will remove all leading zeros.
I propose a solution by using the pointer. The situation where only zero is stored in the array is also handled. I'm more comfortable with the pointer.
int test[20] = {0,0,0,0,1,2,3,4,5,6,7,8,9,0,0,1,2,3,4,5};
int test_bis[20] = {0};
int * ptr_test = test_bis;
int ii = 0;
while( *(ptr_test)== 0 && ii < 20 ) {
ptr_test++;
ii++;
}
if( ii < 20)
do {
printf("%d",*(ptr_test));
ptr_test++;
} while (++ii < 20);
else
printf("0");
Thats for integer array you can modify it accordingly.
for(i=0;i<20;i++){
if(flag==1&&array[i]==0)
{
// just skips until first nonzero
}
else if(flag==1&&array[i]!=0){
flag=0; // when first nonzero comes set flag to 0 and print it
printf("%d",array[i]);
}
else {
printf("%d",array[i]); // after first nonzero simply print it
}
}