Recursive search through an integer - c

I was having some problem when trying to do a recursive in C programming. Here is the expected output:
Enter a number: 1234567
Enter the digit position: 3
rDigitValue1(): 5
rDigitvalue2(): 5
And here is my code:
int rdigitValue1(int num, int k)
{
int count = 0, output;
if (count != k) {
rdigitValue1(num / 10, k);
count++;
}
else {
output = (num % 10);
}
return output;
}
The parameter num is the number whereas the parameter k is the position. With these code, when I try to run the program, it just crashed without prompting any error message. Any idea?
Modified
void rdigitValue2(int num, int k, int *result)
{
if (k != 1) {
rdigitValue2(num / 10, k - 1, result);
*result = num;
}
else {
*result = num % 10;
}
}

You are getting a stack overflow! You are never decrementing digit position and keep looping. Your current code can be simplified to:
int rdigitValue1(int num, int k)
{
if (k != 0) {
rdigitValue1(num / 10, k);
}
}

You should use k - 1 for your recursive call, you keep testing if k == 0 and of course it never is since you keep using the same value for k. You also need to store the value returned from the recursive call so that you can return it:
output = rdigitValue1(num / 10, k - 1);

Expected output :
rDigitvalue2(): 5
Current output :
rDigitvalue2(): 1234567
The function you wrote is :
void rdigitValue2(int num, int k, int *result)
{
if (k != 1) {
rdigitValue2(num / 10, k - 1, result);
*result = num;
}
else {
*result = num % 10;
}
}
The above function works well in my g++ compiler. The value for *result in the end is 1234567 for your function because your recursive call ends in the line *result = num.
You need to remove this line and modify your function to :
void rdigitValue2(int num, int k, int *result)
{
if (k != 1) {
rdigitValue2(num / 10, k - 1, result);
}
else {
*result = num % 10;
}
}
Output : rDigitvalue2(): 5

Related

Recursion for even array in C

I understand there are a lot of questions around even recursion here, but I don't know in C wether its my logic or my syntax that's wrong (or presumably both) because from what I know I may need pointers. Especially when I'm using function in C, so I can harldy find any question that I can understand as a freshman in cs undergrads.
So my assignment was to simply create an array with even numbers in range determined in input, if input n = 10, then the array needs to contain [0, 2, 4, 6, 8, 10], if n = 9 then the array would simply be [0, 2, 4, 6, 8]. But I have to do it with recursion and I don't know what's wrong with my code since the output is somewhat weird.
#include <stdio.h>
int even(int x, int arrEven[]) {
if (x == 0) {
arrEven[0] = 0;
return 0;
}
else if (x > 0) {
arrEven[x - 1] = even(x - 2, arrEven) + 1;
return arrEven[x - 1];
}
}
int main(void) {
printf("n = ");
int n;
scanf("%d", &n);
n = (n / 2) + 1;
int arrEven[n];
even(n, arrEven);
for (int i = 0; i < (n - 1); i++) {
printf("%d, ", arrEven[i]);
}
printf("%d", arrEven[n - 1]);
}
When I input 10 the output was
0, 1, -731908444, 2, 781232032, 3
instead of
0, 2, 4, 6, 8, 10
Your recursive function only initializes half the destination array because in arrEven[x - 1] = even(x - 2, arrEven) + 1; you decrement x by 2 instead of incrementing the value by 2. You can fix your code this way:
int even(int x, int arrEven[]) {
if (x == 0) {
arrEven[0] = 0;
return 0;
} else
if (x > 0) {
arrEven[x - 1] = even(x - 1, arrEven) + 2;
return arrEven[x - 1];
}
}
Note however that the above code does not use tail recursion and will require a stack depth proportional to x. Here is an alternative where the recursion only happens just before returning from the function:
void even(int n, int arrEven[]) {
if (n > 0) {
errEven[n - 1] = 2 * (n - 1);
even(n - 1, arrEven);
}
}
The above function should compile to similar executable code as the equivalent iterative version:
void even(int n, int arrEven[]) {
while (n > 0) {
n = n - 1;
errEven[n] = 2 * n;
}
}
You mix the usage of one variable for two purposes.
In your code, n is used as index in the array and as value to be put into the array at the same time.
There are tons of options to do this. One could looke like this:
#include <stdio.h>
void even(int *arrEven, int value, int limit) {
*arrEven = value;
if (value < limit) {
even(arrEven+1, value+2, limit);
}
}
int main (void) {
int limit;
int count;
printf("n = ");
scanf("%d", &limit);
// TODO: Check return value.
if (limit < 0)
{
fprintf(stderr, "Only non-negative limits are allowed.\n");
exit(-1);
}
count = (limit / 2) + 1;
int arrEven[count];
even(arrEven, 0, limit);
for (int i = 0; i < count-1; i++){
printf("%d, ", arrEven[i]);
}
printf("%d\n", arrEven[count-1]);
}
I think what you want is something like this:
int even(int x, int arrEven[])
{
if (x == 0)
return 0;
arrEven[x - 1] = even(x - 1, arrEven);
return arrEven[x - 1] + 2;
}
Here x is purely the array index, and the fact that only even values go into the array is handled by the fact that 2 is added to the value returned by even along with the terminal condition returning 0.

inverse number using function - how to solve this output problem?

As a new learner of C, I managed to go this far in this little exercice, the code works (kind of). It doesn't work for the second time, the output just adds up.
int i = 0;
void inverse(unsigned int n) {
int reste;
if (n != 0) {
reste = n % 10;
i = (i * 10) + reste;
inverse(n / 10);
} else {
printf("%d \n", i);
}
}
void main() {
inverse(1589);
inverse(42);
}
Output:
9851
985124
Your approach fails because i is not cleared before each new case. You could clear i after the printf, but a better approach is to avoid global variables. You can modify inverse for this purpose by removing the recursion:
#include <stdio.h>
void inverse(unsigned int n) {
unsigned int i = 0;
while (n != 0) {
unsigned int reste = n % 10;
i = i * 10 + reste;
n = n / 10;
}
printf("%u\n", i);
}
int main() {
inverse(1589);
inverse(42);
return 0;
}
Note these remarks:
you must include <stdio.h> to use printf()
main return type is int.
for consistency, i should have type unsigned int.
Some numbers will produce incorrect output as their inverse exceeds the range of unsigned int eg: 1000000009. You can remove this shortcoming by printing the digits instead of combining them as a number:
void inverse(unsigned int n) {
while (n > 9) {
putchar('0' + n % 10);
n = n / 10;
}
putchar('0' + n);
putchar('\n');
}
You need to reset i at some point. The most straight forward and horrible way is to simply do it after the printf().
But you should better redesign the recursion to work without global variables. Which is not easily done with any similarity to the shown code.
This is (I realised a little late) more or less what luk2302 recommended in a comment on a deleted answer.
#include <stdio.h>
int i = 0;
void inverse(unsigned int n){
int reste;
if (n != 0) {
reste = n % 10;
i = (i * 10) + reste;
inverse(n / 10);
}
else {
printf("%d \n", i);
i=0;
}
}
void inverse2(int number, int reversed)
{
if (number < 1)
{
printf("%d \n",reversed);
} else
{
inverse2(number/10, reversed*10+number%10);
}
}
void main(){
inverse(1589);
inverse(42);
inverse(123);
inverse2(1589,0);
inverse2(42,0);
inverse2(123,0);
}
Output:
9851
24
321
9851
24
321

I'm not getting any output in recursive function

// this is a recursive function for finding the sum of digits in C language
//I'm not getting any output in my IDE.
int dsum(int n)
{
int a, r;
r = n % 10;
a = r + dsum(n / 10);
return a;
}
int main()
{
int a;
a= dsum(12345);
printf("%d",a);
return 0;
}
A recursion function should always have a base case as a final return, in this case it's when n equals 0, which means all digits were summed (when msb digit is divided by 10 the result is 0).
Then you'll have the return which will call the function with the result of the current lsb digit (or right most digit) + the result of the function with the input of n/10
int dsum(int n)
{
if (n == 0) {
return 0;
}
return n % 10 + dsum(n / 10);
}
int main()
{
int a;
a = dsum(12345);
printf("%d",a);
return 0;
}
BTW, I also suggest looking into tail recursion:
https://en.wikipedia.org/wiki/Tail_call
In this scenario, it might look like that:
int dsum_tail_recursion(int n, int sum)
{
if (n == 0) {
return sum;
}
return dsum_tail_recursion(n/10, n%10 + sum)
}
int main()
{
int a;
a = dsum_tail_recursion(12345, 0); // 0 is the sum start value
printf("%d",a);
return 0;
}

Why is the code throwing segmentation fault?

The problem is to find the number i<=n, n<=500000 for which the longest collatz series exists.
Collatz series for a number n terminates at 1, and the conditions are
if n is even, next term = n/2
if n is odd, next term = 3*n + 1
Well as a matter of fact, the collatz series always terminates at 1 for all numbers.
Hence any number won't repeat in its collatz series. Using this fact, I have written the following code
LOGIC:
I start a while loop, that goes till n and for each iteration, I store the length of the series for that i.
If i occurs in the series of some n >= r > i, then i terminate the loop and add the length of i to r.
For example, say series of 3 is 3, 10, 5, 16, 8, 4, 2, 1. Now the length corresponding to 2 will already be stored in the series_length array, so I use that value.
Then the for loop next to that, finds the longest series and displays the answer.
The code works fine for n <= 1818 to be precise, but shows segmentation fault onwards (dunno why :(). Please help
CODE :
#include <stdio.h>
int length = 0, series_length[500000], maxlength = 0;
void store_length(int n) {
while(n > 1 && series_length[n] == 0) {
length++;
if(n%2 == 0) {
n = n/2;
}
else {
n = 3*n + 1;
}
}
length += series_length[n];
}
int main() {
int n, i = 1, result;
scanf("%d", &n);
series_length[1] = 1;//redundant statement
while(i <= n) {
store_length(i);
series_length[i] = length;
length = 0;
i++;
}
for(int i = 1;i <= n; i++) {
if(maxlength <= series_length[i]) {
maxlength = series_length[i];
result = i;
}
}
printf("%d %d\n", result, maxlength);
return 0;
}
INPUT-
10
OUTPUT-
9 20 (AS Expected)
INPUT-
100000
OUTPUT-
Segmentation Fault
Expected-
77031 351
Your value for n goes outside the range.
You have a line n = 3*n + 1; in the function store_length
Running this with the gdb with input as 100000 gives
Thread 1 received signal SIGSEGV, Segmentation fault.
0x0000000000401545 in store_length (n=532060) at 29_01.c:6
6 while(n > 1 && series_length[n] == 0) {
(gdb) p n
$1 = 532060
only store it if it fits
... and use it if it already has been computed
avoid global variables
prefer unsigned values
[use descriptive variable names]
#include <stdio.h>
#define THE_SIZE 500000
unsigned series_length[THE_SIZE]= {0,};
unsigned get_length(unsigned val) {
unsigned steps;
for (steps=0; val > 1 ; steps++) {
if (val < THE_SIZE && series_length[val]) { steps += series_length[val]; break; }
if(val %2 ) val = 3*val + 1;
else val /= 2;
}
return steps;
}
int main( int argc, char **argv) {
unsigned top, val , result;
unsigned best,maxlength ;
sscanf(argv[1], "%u", &top);
series_length[1] = 1;//redundant statement
best = maxlength = 0;
for(val=1;val <= top; val++) {
result = get_length(val);
// store it if it fits;
if(val<THE_SIZE) series_length[val] = result;
if (result < maxlength) continue;
best = val; maxlength = result;
}
printf("%u %u\n", best, maxlength);
return 0;
}
Finally, just for fun, make the array smaller
#define THE_SIZE 500
, and the program should give the same result for a given value. (it does)
You get the maximum value 24,648,077,896 with n = 487039.
You must thus use the type long long int for n and you should use an array of 24,648,077,896 integers to avoid a segmentation fault. Unfortunately I never succeeded in allocating a block of 100GB. Your optimization is thus not viable.
Without the array optimization I can scan all 500000 n values in 265ms.
Here is my code:
#include <stdio.h>
int collatz_length(int n) {
int length = 0;
long long int v = (long long int)n;
while (v > 1) {
if ((v&1) == 0)
v = v / 2;
else
v = v*3 + 1;
length++;
}
return length;
}
int main() {
int max_i, max_l = 0;
for (int i = 500000; i > 0; i--) {
int l = collatz_length(i);
if (l > max_l){
max_l = l;
max_i = i;
}
}
printf("i: %d l: %d\n", max_i, max_l);
return 0;
}

3n+1 wrong answer according to uva onlinejudge [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am trying to solve the "3n+1" question and submit it on uva onlinejudge but every time it says that my code gives the wrong answer and unfortunately i can't find it's problem
here is the question: Problem 100
My Code:
#include <stdio.h>
int main()
{
unsigned long int n, m;
int max = 0;
scanf("%d %d", &n, &m);
int i;
for (i = n; i <m + 1; i++)
{
int ter = i;
int counter = 1;
while (ter != 1)
{
counter++;
if (ter % 2 == 1) { ter = 3 * ter + 1; }
else
ter = ter / 2;
if (ter == 1)
if (counter>max) { max = counter; }
}
}
printf("%d %d %d\n", n, m, max);
return 0;
}
The problem is clear. You are not following the instructions from the problem statement
For any two numbers i and j you are to determine the maximum cycle
length over all numbers between i and j.
The input will consist of a series of pairs of integers i and j, one
pair of integers per line. All integers will be less than 1,000,000
and greater than 0.
You only read one line of input and print that answer
You assume that i is less than j
Correct Solution:
#include <stdio.h>
int cycleSize(int x) {
int cycle = 1;
while (x != 1) {
if (x % 2 == 0) { //if even
x = x / 2;
} else { //if odd
x = x * 3 + 1;
}
++cycle;
}
return cycle;
}
int maxCycleSizeBetween(int a, int b) {
if (a > b) { //if b > a, swap them
int temp = a;
a = b;
b = temp;
}
int maxCycle = 0;
for (; a <= b; a++) {
int thisCycleSize = cycleSize(a);
if (thisCycleSize > maxCycle) {
maxCycle = thisCycleSize;
}
}
return maxCycle;
}
int main() {
int a, b; //input vars
while (scanf("%d %d", &a, &b) != EOF) {
printf("%d %d %d\n", a, b, maxCycleSizeBetween(a, b));
}
return 0;
}
The following function performs the requested calculation:
void n3plus1(int min, int max)
{
int i, n, len, lenmax=0;
for (i=min; i<=max; i++)
{
n= i; len= 1;
while (n!=1) {
if (n&1)
n= 3*n + 1;
else n= n/2;
len++;
}
if (len>lenmax) lenmax= len;
}
printf("Answer: %d %d %d\n", min,max,lenmax);
}
With the following tests:
void test(void)
{
n3plus1(22, 22);
n3plus1(1, 10);
n3plus1(100, 200);
n3plus1(201, 210);
n3plus1(900, 1000);
}
the output is:
Answer: 22 22 16
Answer: 1 10 20
Answer: 100 200 125
Answer: 201 210 89
Answer: 900 1000 174
Note: the "the maximum cycle length over all numbers between i and j" in the problem statement must be interpreted as including i and j.
The code assumes i<=j on input. The code excludes reading the input.
the following code implements the requirements
However, some online code contests expect a final blank line. You will need to determine those kinds of details.
#include <stdio.h>
int main( void )
{
size_t n1;
size_t m1;
char buffer[1024];
while( fgets( buffer, sizeof(buffer), stdin ) )
{
if( 2 != sscanf(buffer, "%lu %lu", &n1, &m1) )
{
break;
}
size_t n = n1;
size_t m = m1;
if( n1 > m1 )
{ // then first number greater than second so reverse for calculations
size_t temp = n;
n = m;
m = temp;
}
size_t maxCount = 0;
for (size_t i = n; i <= m; i++)
{
size_t ter = i;
size_t counter = 1;
while (ter != 1)
{
counter++;
if ( (ter & 0x01) == 1)
{ // then odd
ter = 3 * ter + 1;
}
else
{ // else even
ter = ter / 2;
}
// for testing only
// printf( "%lu: %lu, %lu\n", counter, i, ter );
}
if( maxCount < counter )
{
maxCount = counter;
}
}
printf("%lu %lu %lu\n", n1, m1, maxCount);
}
}
Note:
this code will exit if non numeric value entered
this code will exit if a EOF encountered -- this is expected
this code will fail if a negative number entered, however; the contest stipulation says that the numbers will be in the range 1...1000000 so no need to check for negative numbers
this code will exit if only one number on input line
this code will exit if only a <cr> is entered

Resources