Recursive function in C (to print a piramid of #) - c

I´m following the famous course cs50.
During a class, the teacher showed a program that printed out a pyramid of a height given as an input from the user:
#include <cs50.h>
#include <stdio.h>
void pyramid(int n);
int main (void)
{
int height = get_int("height:");
pyramid(height);
return 0;
}
void pyramid(int n)
{
if (n==0)
{
return;
}
pyramid(n-1);
for (int i=0; i<n;i++)
{
printf("#");
}
printf("\n");
}
Can please someone explain me, what the recursive function pyramid does?
I debug it and I see that given the input is checking if it is equalto 0, then it calls itself until n==0 and returns. After that the debugger goes to the loop for and does it n time.
Following a liner path, it is not supposed to go to the for loop.
Why it does it?
Thank you very much for your help!

After some value of height is set, then a function piramid is called. If the value of height is 0, then the function finishes. Otherwise it calls itself with decreased argument height, which allows you to print each level of the pyramide. As you can see in the body of void piramid(int n), it calls itself first, then prints n "blocks".
Let's say we are working with height = n and try to analyze what happens (each dot is another step):
piramid(n) calls:
piramid(n-1) calls:
piramid(n-2) calls:
...
piramid(1) calls:
piramid(0) - that returns nothing, it is the last recursive call of piramid, so we start going back: in our case it means we print hashes in the order from top to bottom:
# is printed, as piramid(1) is on top of the stack and after we print it, then we pop it, so piramid(2) becomes the first element on top
## are printed, piramid(2) is on top of the stack, we pop it and continue working with other calls the same way,
...
(n-1) # are printed, we pop it from the stack,
n # are printed, our stack is now empty.

To make it understandable, let's take an example with a small number :
#include <stdio.h>
void piramid (int n);
int
main (void)
{
piramid (2);
}
void
piramid (int n)
{
if (n == 0)
{
return;
}
piramid (n - 1);
for (int i = 0; i < n; i++)
{
printf ("#");
}
printf ("\n");
}
What it does:
main calls piramid(2)
piramid(2) calls piramid(1) however piramid(2) didn't finish as you stated
piramid(1) calls piramid(0)
piramid(0) does nothing as it returns immediately
piramid(1) finishes and prints #
piramid(2) finishes and prints ##
If n was bigger it would follow this but with more steps
Hope it could help and sorry if my answer isn't great as it's my first try answering on stackoverflow (if you have suggestions of how I should answer don't hesitate to tell me)

Related

Is it necessary to put return in a void recursion?

Feel free to make this post as a duplicate if the question asked already, I haven't found a post same as this
As far as I know that there's no need to return in a void function, e.g:
void ex () {printf ("Hi\n");}
But, is it fine if there's no return in a void recursion? What I'm thinking is, the program will keep calling func (num-1) until it reaches 0 and it returns so it doesn't print 0 to the output, and I need return at the end of the function so after the recursion call is done, you go back to the previous func () immediate caller.
Here's the code,
#include <stdio.h>
void func (int num)
{
if (!num) return;
func (num-1);
printf ("%d\n", num);
return; //Is it necessary to put return here?
}
int main ()
{
func (10);
return 0;
}
Output,
1
2
3
4
5
6
7
8
9
10
Without the last return, it works just fine too, or am I missing something?
A function with return type void doesn't need an explicit return. Simply reaching the end of the function will properly return.
It is no different for void functions that are also recursive. The first return in your function is required because you want it to return before reaching the end of the function, but the second isn't required.
A function returning void doesn't have to explicitly return. A program has 1 entry point, but might have multiple exit points. Consider the following example:
void print(int var)
{
if (var)
return; // first exit point
/*
* do stuff
*/
// second exit point
}
It has 2 exit points. Second one is without a return;.
try this :
#include <stdio.h>
void func (int num)
{
if (!num){
printf("0\n");//print 0 before you stop
return;
}
func (num-1);
printf ("%d\n", num);
}
int main ()
{
func (10);
return 0;
}

Using a for-loop in C to test the return value of a function

I'm pretty new to coding and especially to C, so I decided to take the CS50 course as an introduction to the language. I just finished watching the first lecture on C and, as a means to test my knowledge on the subject, I attempted to write a short little program. Also I am using the course's library for the get_int() function.
The goal is to test the user's input and check if it's less or equal to ten. If it matches the parameters, the program should print the "Success!" message and exit; otherwise, it should ask for input again. If the input value is over 10, the program responds just as expected, but if you input a value of 10 or less, it ends up asking you for input one more time before actually exiting. I think it's probably something with the "for" loop, but I just can't figure it out.
My code:
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
int check_for_value();
int main()
{
for(check_for_value(); check_for_value() != 1; check_for_value())
{
printf("Failed!\n");
}
exit(0);
}
int check_for_value()
{
int i = get_int("Your value: \n");
if(i <= 10)
{
printf("Success!\n");
return 1;
}
else
{
printf("Try again!\n");
return 0;
}
}
That isn't doing exactly what you think it is. In your for loop, each time you write check_for_value(), it is going to call that function. So it will call it the first time and the return value will not matter. It will call it again for the middle statement and then the value will matter because you are comparing the output to not equal to 1. And then again it will call the function in the third statement, where again it won't matter. Usually for something like this, you would use a while loop instead. An example below:
int ret = check_for_value();
while(ret != 1) {
printf("Failed\n");
ret = check_for_value();
}
printf("Success\n");
Technically a for loop can work too as the following:
for(int ret = check_for_value(); ret != 1; ret = check_for_value()) {
printf("Failed\n");
}
The for loop can look very simply
for ( ; !check_for_value(); )
{
printf("Failed!\n");
}
In such a case it is better to use the while loop
while ( !check_for_value() )
{
printf("Failed!\n");
}
As for your for loop
for(check_for_value(); check_for_value() != 1; check_for_value())
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
then the underlined calls of the function are not tested.
Also bear in mind that such a definition of a for loop
for(int ret = check_for_value(); ret != 1; ret = check_for_value()) {
printf("Failed\n");
}
is a very bad style of programming. There is redundant records of the function calls. The intermediate variable ret is not used in the body of the loop. So its declaration is also redundant. Never use such a style of programming.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
and the statement
exit( 0 );
is redundant.

Stack implemented as an array defaulting first value to 0 in C

I have an assignment where I am supposed to use this very very simple (or so I thought) stack that my teacher wrote in C, just using an array. From this, I have to implement reverse polish notation from a text file.
In order for me to implement this, I am using a stack, pushing values on until I hit an operation. I then do the operation and push the result back onto the stack until the user hits p to print the value.
The problem is, for some reason, my professor's implementation of the stack array defaults the first (index 0) value to 0. Printing the stack without pushing anything onto it should result in null but it appears the output is 0.
Here is my professor's implementation of the stack:
#define STK_MAX 1024
#define ELE int
ELE _stk[STK_MAX];
int _top = 0;
void stk_error(char *msg)
{
fprintf(stderr, "Error: %s\n", msg);
exit(-1);
}
int stk_is_full()
{
return _top >= STK_MAX;
}
int stk_is_empty()
{
return _top == 0;
}
void stk_push(ELE v)
{
if ( stk_is_full() )
stk_error("Push on full stack");
_stk[_top++] = v;
}
ELE stk_pop()
{
if ( stk_is_empty() )
stk_error("pop on empty stack");
return _stk[--_top];
}
void print()
{
for(int i = 0; i <= _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
I realize that the print statement will print a value that has not been pushed yet, but the problem is, is that when I don't print it, it still ends up there and it ends up screwing up my rpn calculator. Here is what happens when I do this:
// input
stk_push(2);
print();
stk_push(4);
print();
// output
2 0
2 4 0
How do I get rid of the 0 value that is affecting my calculator? Doing stk_pop() after the pushing the first value onto the stack didn't seem to work, and checking that top == 0, then directly inserting that element before incrementing _top didn't work.
When you are printing, loop from 0 to (_top - 1), since your top most element is actually at _top - 1. Hint : Look at your pop/push method.
void print()
{
for(int i = 0; i < _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
"The problem is, is that the rpn calculator relies on the TOS being accurate. When I do pop() though, it will pop 0 and not the real TOS."
Sounds like a problem with your calculator implementation. You assumed the top of the stack would be null, but that's not the case for your professors stack implementation. Simply a invalid assumption.
Instead he's provided a stk_is_empty() method to help determine when you've pop everything.
If you need to pop all elements, you'll need to break on the condition of stk_is_empty().
stk_push(2);
stk_push(4);
while( stk_is_empty() == false)
{
stk_pop();
}
Of course in reality you'd be setting the pop return to a variable and doing something with it. The key point is leveraging stk_is_empty().
I haven't written C++ in few years so hopefully I didn't make a minor syntax error.

Simple Recursion output calling recursion twice

This is how I tried it. The main part uses fun(9). So 9 does not equal or less than one. And it calls fun(9/3) two times and prints n which is 9. Where am I wrong here?
#include <stdio.h>
void fun(int n){
if(n<=1) printf("*");
else{
fun(n/3);
fun(n/3);
printf("%d",n);
}
}
int main(void){
fun(9);
return 0;
}
When called as fun(9), the code shown does print **3**39.
The first call has n == 9.
Consequently, if calls fun(3), then fun(3) again, and then prints 9.
The first of the two calls fun(3) calls fun(1), which prints a *, then calls fun(1) again and prints another *, and then prints 3.
The second of the two calls does the same.
Your output should be
* * 3 * * 3 9
If you can't see how it works, then do it by hand and fill in the values instead of the variable name:
Pass 1:
void fun(9){ // first pass n=9
if(9<=1) printf("*"); // nope, that's not true
else{
fun(9/3); // call the function again with n = 9/3 = 3
Pass 2:
void fun(3){ // second pass n=3
if(3<=1) printf("*"); // nope, that's not true
else{
fun(3/3); // call the function again with n = 3/3 = 1
Pass 3:
void fun(1){ // third pass n=1
if(1<=1) printf("*"); // yes! so print first *
else{ // this function is only an if and an else, we hit the if
// so it just drops out now
So pass #3 and we hit the lowest level of the recursive call, now Pass 2 will continue execution where it left off:
Pass 2b:
void fun(3){ // second pass n=3 (did this already)
if(3<=1) printf("*"); // nope, that's not true (did this already)
else{
fun(3/3); // call the function with n = 1 (did this already)
fun(3/3); // next recursive call, again with n = 1
Now this will repeat the "pass #3" code, again printing a second *, then it will return and continue execution where it left off:
Pass 2c:
void fun(3){ // second pass n=3 (did this already)
if(3<=1) printf("*"); // nope, that's not true (did this already)
else{
fun(3/3); // call the function with n = 1 (did this already)
fun(3/3); // call again with n = 1 (did this already)
printf("%d", 3); // print 3
At this point the output is: **3 Pass #2 is now complete so we go all the way back up and resume Pass #1 where it left off:
Pass 1b:
void fun(9){ // first pass n=9 (did this already)
if(9<=1) printf("*"); // nope, that's not true (did this already)
else{
fun(9/3); // call the function again with n = 3 (did this already)
fun(9/3); // now call the function again with n = 9/3 = 3
From here you can see that we're going to repeat the Pass 2 logic producing another **3 then we'll return to Pass1 a final time to print the 9
A final output of: **3**39

Deciding the base condition in backtracking recursive algorithm

I was solving the N Queen problem where we need to place 4 queens on a 4 X 4 chess board such that no two queens can attack each other. I tried this earlier but my approach did not involve backtracking, so I was trying again. The code snippets are
int size=4,i,j;
int arr[4][4];
int lastjindex[4]; // to store the last location which we may need to backtrack
void placeQueen(int i,int j)
{
int availableornot=0;
for(j=0;j<size;j++)
{
if(isAvailable(i,j)==1)
{
availableornot=1;
break;
}
}
if(availableornot==1)
{
arr[i][j]=1;
lastjindex[i]=j;
if((i+1)!=size)
{
placeQueen(i+1,0);
}
}
else
{
// no column was availabe so we backtrack
arr[i-1][lastjindex[i-1]]=0;
placeQueen(i-1,lastjindex[i-1]+1);
}
}
The isAvailable() method returns 1 if arr[i][j] is not under attack, else it returns 0.
int isAvailable(int i,int j)
{
int m,n,flag=0;
for(m=0;m<i;m++)
{
for(n=0;n<size;n++)
{
int k=abs(i-m);
int l=abs(j-n);
if(arr[m][j]==0 || arr[k][l]==0)
{
flag=1;
break;
// means that spot is available
}
}
}
return flag;
}
I call the above method from main as
placeQueen(0,0);
My program compiles successfully but it prints all zeroes.
Is there any problem with my recursion? Please help me correct my code as I am trying to learn how to implement backtracking algorithms!
Also I am not able to decide the base condition to end recursion. How do I choose it here?
There's no printing in the code you posted. If you print after you have backtracked, you will be back to the initial condition of no queens on the board. Print after you have placed N queens, which is also the end condition for recursion. If you only want to print one solution, exit after printing, or set a flag that tells the caller that you're done so you pop all the way out. If you print all solutions, that will include reflections and rotations. You can eliminate one axis of reflection by only placing queens within size/2 in the first level.
Also, there are some clear logic errors in you code, such as
arr[m][j]==0 || arr[k][l]==0
A queen can only be placed if it isn't attacked on the file and it isn't attacked along a diagonal. Use a debugger or add printfs to your code to trace where it is trying to place queens -- that will help you figure out what it is doing wrong.
And aside from being wrong, your isAvailable is very inefficient. You want to know if the [i,j] square is attacked along the file or a diagonal. For that you should have a single loop over the rows of the previous queens for (m = 0; m < i; m++), but you only need three tests, not a loop, to check the file and the diagonals. As soon as you find any previous queen on a file or diagonal, you're done, and the square isn't available -- return false. (And ignore people who tell you that a function should only have one return -- they are wrong, and there are lengthly discussions here at SO and even scientific studies of error rates in code that bear this out.) Only if no previous queen is found is the square available.
Your placeQueen is also wrong. For each available square on a row, you need to place a queen and then recurse, but you're just finding the first available square. And backtracking is achieved simply by removing the queen you placed and then returning ... the previous level of placeQueen will try the next available spot.
Again, trace the code to see what it's doing. And, even more importantly, think through the logic of what is needed. Write your algorithm in words, convince yourself that it will solve the problem, then write the code to carry out the algorithm.
#include <stdio.h>
#define SIZE 4
int size=SIZE;
int arr[SIZE][SIZE] = { 0 };
void placeQueen(int col){
int r,c;
if(col == size){//all queen put!
//print out
for(r = 0;r<size;++r){
for(c = 0;c<size;++c)
printf("%d", arr[c][r]);
printf("\n");
}
printf("\n");
return ;
}
for(r=0;r<size;++r){
if(isAvailable(col, r)==1){
arr[col][r]=1;
placeQueen(col+1);
arr[col][r]=0;//reset
}
}
}
int isAvailable(int col,int row){
int c;
for(c=0;c<col;++c){
int d = col - c;
if(arr[c][row]==1)
return 0;//queen already same row
if(row+d < size && arr[c][row+d]==1 || row-d >= 0 && arr[c][row-d]==1)
return 0;//queen already same slanting position
}
return 1;
}
int main(){
placeQueen(0);
return 0;
}

Resources