The output of the below program is 24. But I could not understand the behaviour of the function f1(parameters).
There is a recursive call of f1 in m1 nad m2. Considering m1 and m2 holding the function f1's stack. m1 stack will contain:
1]0,12,a 2]0,6,a 3]0,3,a 4]0,1,a 5]0,0,a
And m2 stack will contain:
1]13,12,a 2]20,6,a 3]24,3,a 4]26,1,a 5]27,0,a
What m1 and m2 values hold? please explain this behaviour of the recursive function.
#include <stdio.h>
main()
{
int i, n, m, b, x[25];
int f1(int, int, int j[25]);
for(i=0;i<25;i++) x[i] = i;
i=0; m = 24;
b=f1(i, m, x);
printf("res %d\n",b);
}
int f1( int p, int q, int a[25])
{
int m1,m2;
if (q==0)
return(a[p]);
else
{
m1 = f1 (p, q/2, a);
m2 = f1(p+q/2+1,q/2,a);
if(m1<m2)
return (m2);
else
return(m1);
}
}
Well, there are two points to understanding the code:
Uncovering the actual algorithm among the heaps of terrible C and
understanding the recursive function itself.
What always helped me when trying to understand such code was to:
Clean up the C code. In this case it means:
Mentally tracing the initialization and rewriting to static initialization, so you see what the values look like:
int x[25] = { 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 };
Getting rid of the useless assignment to i and x so you have the initial call in plain sight.
Rewrite the function to mathematical notation, pseudocode or even human laguage.
f(p, q, array) = larger of f(p, q/2, array) and f(p+q/2+1, q/2, array)
if you continue a little bit further in using human language, you'll clearly see what is was supposed to do.
Now I said "was supposed to do" on purpose. The (p, q/2) and (p+q/2+1, q/2) look like the first and second half... except they are not.
The code is supposed to return 24, but it's totally wrong and the stacks quoted in the question actually prove it. The m2 stack contains as last point "f1(27, 0, a)" and that invocation is going to do a[27], but the array only has 25 elements! (by pure chance the memory above was probably 0-initialized, so it did return the 24, but if it was initialized by some debug pattern instead (I've seen 0xdeadbeef, 0xa5a5a5a5 and 0xcccccccc), it would return that).
In C it's by design (and C++ uses them everywhere) easiest to use half-open intervals. [start, one-past-end) or start+length, which convert to each other nicely. However here the function gets (start, length-1) and treats it inconsistently inside.
As a student, you have to be able to understand such code, because you'll meet lots of crappy unreadable bug ridden code that only works by accident in the wild. But if you ever present something like this, you will rightfully fail the exam.
Here you can't think of an m1 stack and an m2 stack as non-terminating calls to f1 result in an m1 and an m2 recursive call.
To analyze what's happening try it for a small value of p and q.
f1( 0, 1, a)
m1 = f1( 0, 0, a); /* q/2 == 1/2 == 0 */
/* q now 0 so return a[0] */
m2 = f1( 1, 0, a);
/* q now 0 so return a[1] */
overall result the larger of a[0] and a[1].
Now try it for f1( 0, 2, a) and so on, till you see what's happening.
Related
Looking at this code which passes values to functions the usual way (by value, not by reference/pointer):
funky(x)
{
if (x > 0) {
x -= 1
funky(x)
}
printf("%d," x)
}
int tester()
{
funky(x passed in as 5)
return 0
}
What will the displayed output be?
Is int tester being passed in as the value for x at the top, the funky(x) -= 1 code? If it is then would that just print 4? Nothing is being declared as an int or string so I am not sure what will print.
I decided to help you with your learning by providing you with actually compilable code which, I am convinced, will further exactly the same learning goals as what you are currently studying. I will of course not provide you with the output of the shown code (or the shown code changed to be compilable). For two reasons. One: I don't want to do the quiz for you. Two: I want to help you learn, not hinder you.
So this code, if compiled and run:
#include <stdio.h>
int funky(int x)
{
printf("in %d, ", x);
if (x > 0)
{
x -= 1;
printf("mid %d, ", x);
funky(x);
}
printf("out %d, ", x);
}
int main()
{
funky(/* x passed in as */ 5);
return 0;
}
will get you the hopefully enlightening output:
in 5, mid 4, in 4, mid 3, in 3, mid 2, in 2, mid 1, in 1, mid 0, in 0,
out 0, out 0, out 1, out 2, out 3, out 4,
It supports your understanding by making obvious which output is caused by which code part. I added a second and third output to help you understand the recursion trickery used in the quiz code. And I added a newline to the output, simply for readability here. (Side effect of intentionally not giving the character precise output here...)
With the syntax fixes in the code I intend to answer the side questions in your post, while the real puzzle is clarified by the visualisation of the relevant values before and after the recursive call.
I am new to coding and am required to make a Mandelbrot function. For those of you who don't know, the Mandelbrot set is a set of complex numbers. Essentially, you take a complex number to start with, then square it and add it to the original complex number. For example, If I used the number 1, the set would be 0, 1, 2, 5, 26, ... I got this value from: 0, 1, (1^2) + 1 = 2, (2^2) + 1 = 5, (5^2) + 1 = 26.
Now, my recursive function is supposed to find the sum of this set using two inputs: a number n, which is how far we are going into the set. For example, if n is 3, then my first example the set would be (0, 1, 2). The second input is a complex number structure, which I have already defined as two parts, an imaginary number and a real number. The goal is to multiply two complex numbers and add the original complex number. I have already made the multiply and add functions for complex as well, so essentially I just need help with the recursion part. Here is what I have so far:
#include <math.h>
#include <stdio.h>
complex_t mandelbrot(doublen, complex_t c) {
if(n == 0) {
return c;
}
else {
complex_t first = mandelbrot(n-1, c);
complex_t multiplied;
complex_t multiplied = multiply_complex(first, first);
return mandelbrot(n-1, multiplied);
}
For this program, n is going to be set to 15, and if the absolute value of the real part of the complex number is less than 100, it is in the mandelbrot set. However, this is done later; here, I just need to find out why my recursion process is not processing correctly.
Yo are performing two recursive calls for some reason. But not performing the addition part. Your function's else part should look similar to this:
complex_t first = mandelbrot(n-1, c);
return add_complex(c, multiply_complex(first, first));
Update:
The n should be integer, not double. You are risking not to terminate with comparing double to zero in the base case since due to floating point rounding specifics the exact equality comparison won't work most likely.
I am very new to C, and I was just playing around and seeing if I could recreate a simple subarray adding program (finds the largest continuous subarray in an array). I ran in to an odd issue where if I defined n as an integer and used it as a condition in my for loop I would get absolute junk back.
Forgive this weird code, I pretty much just copied and pasted a file I was monkeying around with (lots of extra printfs etc). If I run this, I get an output of "4196053", or something similar to that, for each printf call in the for loop. Even in the first printf call (before entering the loop) it seems to be messed up.
#include <stdio.h>
int maxI (int a, int b)
{
int max = (a >= b) ? a : b;
return max;
}
int main (void)
{
int array[] = { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
int n = 11;
int maxSoFar, i = 0;
int maxHere = 0;
printf ("%i\n", maxSoFar); //why is it screwing up here?
for (i = 0; i < n; i++) {
printf ("%i\n", maxSoFar);
maxHere = maxI(maxHere + array[i], 0);
maxSoFar = maxI(maxSoFar, maxHere);
}
printf ("The max is %i.\n", maxSoFar);
return 0;
}
If I just use 11 in the conditional instead of a variable it works fine. Anyone know what is going on here?
maxSoFar is having some arbitrary data, so you need to initialize it first
int maxSoFar = 0, i = 0;
^^Initialize to zero
Your error is here
int maxSoFar, i = 0
You never declared maxSoFar so it's using garbage data.
Initialize it to 0, and you should be good.
It gives you a garbage value because you never initialize maxSoFar. This means that it will have the value of whatever was left in memory at that point.
You main issue is that maxSoFar is a local(automatic) variable and is therefore if it is not initialized it will have an indeterminate value, so the results of this program are also indeterminate. The fix would be to properly initialize maxSoFar, probably to the first element of array.
For completeness sake, the relevant section of the C99 draft standard is 6.7.8 Initialization paragraph 10 which says:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate.[...]
I need to write a function which finds the longest, not necessarily contiguous, ascending sub-sequence in a list of numbers. The function needs to be recursive.
I have a problem with my algorithm and I cannot figure out how to fix it. Here's an example starting list:
[88, 1, 22, 3, 34, 6, 54, 9, 19]
The correct result is:
[1, 3, 6, 9, 19]
and I want to print on the screen the length of this sub-sequence, in this case, 5.
My function:
int subseires(int arraysub[], int small, int i, int j, int coun){
if( i==size ) return 0;
if( arraysub[i]>arraysub[j] )
subseires(arraysub, small, i+1, j+1, coun);
if( arraysub[i]<arraysub[j] )
subseires(arraysub, small, i, j+1, coun+1);
return coun;
}
Can anyone help by pointing out the problems with my procedure?
Your algorithm is probablly wrong.
What you need to do is for each member of the aray-if you can select it(it's not less than the previous one you have selected) then check two options recursivelly: to select it or not to select it. This way you go until the end of the array and return the total length. In the end you print the longest length.
Try to implement this algorithm in a C function.
So you only need to print the length of the list, not the list itself? That helps, because it simplifies memory management (which is an issue for c).
This is really just a glorified search. At each point you need to know (1) the current value (if any); (2) the current length (if any); (3) the position in the list; (4) the largest length known. Using a length of zero helps track when you have no current value (so you don't need a "magic" initial value). The return value should be the largest length.
On each recursion you can either skip the current number or include it in the list (but only if it is less than the current value).
so the code is just:
#include <stdio.h>
int max(int a, int b) {
return a > b ? a : b;
}
int find(int* data, int total_length, int offset, int previous,
int run_length, int max_length) {
// update max length if it has improved
if (run_length > max_length) max_length = run_length;
// if we are at the end, return max
if (offset == total_length) return max_length;
// if the current value is too small, we cannot include it
if (run_length && data[offset] <= previous)
return find(data, total_length, offset+1, previous, run_length, max_length);
// otherwise, we want the best of either including it or not
return max(
// try including it
find(data, total_length, offset+1, data[offset], run_length+1, max_length),
// try excluding it
find(data, total_length, offset+1, previous, run_length, max_length));
}
// test
int main(int argc, char *argv) {
int data[] = { 88, 1, 22, 3, 34, 6, 54, 9, 19 };
printf("%d\n", find(data, 9, 0, 0, 0, 0));
return 0;
}
obviously this is terrible c code (not because I didn't use array initialization, which someone "kindly" fixed (although they didn't bother to vote this answer - I guess they think I am motivated to post here by learning from their deep knowledge of C syntax) but because it uses the call stack where it would be more efficient to use a separate memory structure).
(also, I have to say, writing something like this is much easier as a recursive function than as doing it in a loop, because you just write down what you want to happen - if you had a loop then you would need to worry about changing values and resetting them and all that mess. The problem is that it abuses the stack horribly).
The recursive function you need will look like this
void dfs (int curr, int length){
if (length > max )max = length;
if (curr >= index)
return ;
for (int I=curr+1;I <= index; I++){
if (array[I] >= array[curr]){
dfs (I, length+1);
}
}
}
Here array[] is integer array. Numbers are filled with index 1 to index n. 'curr' is current index and 'length' is the length of maximum sub-sequence with ascending numbers. 'max' is maximum such length. To compute the length you should call
dfs(0, 0);
For full working Java code : http://pastebin.com/H315si0K
Question's Background:
void dash(int *n, char c) is to draw characters c separated by '+'.
Parameter n is an array of ints, e.g. {1, 3, 2} and '-' for c should give "+-+---+--+", which works fine.
To use dash I do {int f={1, 3, 2}; dash(f, '-');}, which makes the construct copy&pastable.
The question itself:
To avoid copy&pasting I wanted to do #define F(X, Y) {int f=X; dash(f, Y);},
resulting in a nicely usable F({1, 3, 2}, '-').
Unfortunately the compiler complains about F getting 4 (array's length + 1) arguments instead of 2.
So how can you give {1, 3, 2} as parameter to a macro?
Variadic macros are a feature of C99.
#define F(Y,...) dash((int[]){__VA_ARGS__},Y)
So how can you give {1, 3, 2} as
parameter to a macro?
F('-',1,3,2);
Here is my version:
#include <stdio.h>
void dash(int len, int *n, char c){
int i;
printf("dash( %i, {", len );
for( i=0; i<len-1; i++ )
printf(" %i,", n[i] );
printf(" %i }, '%c')\n", n[i], c );
}
#define NOPAREN(...) __VA_ARGS__
#define F1(arr,char) { int f[]={NOPAREN arr}; dash(sizeof(f)/sizeof(f[0]),f,char); }
#define F2(char,...) { int f[]=__VA_ARGS__; dash(sizeof(f)/sizeof(f[0]),f,char); }
int main(void){
F1( (1,3,2), '-' );
F2( '-', {4,6,5} );
}
Result:
dash( 3, { 1, 3, 2 }, '-')
dash( 3, { 4, 6, 5 }, '-')
Instead of trying to use a macro to set up and make these calls, I'd probably consider changing the interface to dash() to use varargs:
#include <stdarg.h>
void dash( char c, ...)
{
// ...
}
int main() {
dash( '+', 1, 3, 2, -1); // note: negative number indicates
// the end of the list of numbers
return 0;
}
Using varargs isn't the best thing in the world (they're difficult to use and aren't typesafe), but I think it would be better than the macro concoction you're trying to gen up.
Also, remember that even if you stick with your current interface for dash() and come up with a macro that does what you want, you still need to have a way to indicate the end of the sequence of numbers to be passed into dash(). Otherwise there's no way for dash to know when it has reached the end of the array. You have several choices:
use a sentinel value, such as 0, -1, or any negative number (like in the vararg example above)
pass the number of elements in the array as another argument
set the size of the array as a part of dash()'s interface. In your example, dash() might require that an array of 3 ints be passed in. No more, no less (actually more would be OK - they just wouldn't be used). If you did this, fixing your macro would be much easier, but I suspect it's not how you want dash to behave.
You can pass { 1, 3, 2 } as an argument to a macro if you define { 1, 3, 2 } as another macro
#define PARAMS { 1, 3, 2 }
F(PARAMS, '-')
#undef PARAMS
Unfortunately, there seems to be no direct way to do literally what you ask, i.e. pass specifically { 1, 3, 2 } in this specific form. It might be worth switching to alternative methods, including the C99-specific ones suggested in other answers.