I've been looking at examples of recursion (in C) online in an attempt to get a better understanding of it and how it works. Generally speaking, I can trace some basic recursion problems without issue (such as a factorial problem), but I found this one and am completely lost on how to trace it.
The idea is that you have the user enter an amount of change, and by using recursion, you print out the number of ways that amount of change can be made. The code is as follows:
#include <stdio.h>
#define NUM_DENOMS 4
int ways(int amount, int denomination);
int main()
{
//Declarations & initializations
int userChange = 0;
//Get user input
printf("Enter an amount you wish to get change for (in cents):\n");// get the amount of change in from the user
scanf("%d", &userChange);
//Function call... pass user's input and denomination values (ints) as parameters
printf("%d cents can be made in %d different ways\n", userChange, ways(userChange, NUM_DENOMS));
return 0;
}
//Function to find # of ways to make change for user's amount
int ways(int amount, int denomination)
{
static int validAmounts[NUM_DENOMS] = {1, 5, 10, 25};
if(denomination<=0) //if denomination is invalid
{
return 0;
}
if((amount == 1) || (amount == 0)) //base case: only 1 combination
{
return 1;
}
else if(amount < 0) //can't have negative amount of money
{
return 0;
}
else //if denomination is valid and user's change > 1
{
return ways(amount, denomination-1) + ways(amount-validAmounts[denomination-1], denomination);
}
}
Apparently this is a common application of recursion. I can't wrap my head around how this recursion works though. What stands out to me the most is the fact that there are 2 recursive calls on the same line. I have never seen recursion applied in this way.
I did attempt to trace it but my results are definitely wrong:
Say I enter 25 as the amount of change. When I go into the ways function, none of the base cases are satisfied and so the recursion comes into play. For the first call, amount stays the same and denomination is decreased by 1, so we go back into the function with 25 and 3 (4-1) as our new arguments. None of the base cases are met until denomination is reduced to 0 (since amount never changes). At this point, we are returning 0. This is the point where I get lost. I see it that 0 gets sent back through all the previous calls and so the end result is 0, but that doesn't sound right to me. I run into the same problem when trying to trace the second call except instead of 0 getting sent back through the calls, it is 1. Obviously my perception of this recursion is horridly wrong. Can someone explain to me how this instance of recursion actually works?
One way to trace a recursive algorithm is to put a printf at the top of the recursive function. The printf should print out the arguments to the function. It's also a good idea to temporarily add more parameters to give yourself additional information about what the recursion is doing. The most common additional parameter is a depth parameter that shows how many nested calls have been made. And for this particular question (where you have two recursive calls) I would add an additional parameter to identify which call is being traced.
With that in mind, here's the modified code. I suggest starting with a simple input, like 5, to get a feel for how the recursion works.
#include <stdio.h>
#define NUM_DENOMS 4
int ways(int amount, int denomination, int left, int depth);
int main( void )
{
int userChange = 0;
printf("Enter an amount you wish to get change for (in cents):\n");
scanf("%d", &userChange);
printf("%d cents can be made in %d different ways\n", userChange, ways(userChange, NUM_DENOMS, 'M', 0));
return 0;
}
int ways(int amount, int denomination, int left, int depth)
{
static int validAmounts[NUM_DENOMS] = {1, 5, 10, 25};
printf( "%2d %d %c %2d\n", amount, denomination, left, depth );
if(denomination <= 0 || amount < 0)
return 0;
if((amount == 1) || (amount == 0))
return 1;
return ways(amount, denomination-1, 'L', depth+1) + ways(amount-validAmounts[denomination-1], denomination, 'R', depth+1);
}
The code makes two calls because it breaks the problem into two parts and each part is solved the same way. Each part is in some sense simpler than the original problem and the same method is used to solve each individual problem. As pointed out by others, there may be situations in which there are more than two parts.
You have likely seen examples with one call where one part of the problem is solved and the single recursive call solves the 'remainder' of the problem.
Related
My professor wants use to ONLY use while loops and call 2 different functions, which I have done. I am really stuck on how to tweak this so that if I put in, say, 16, that it will list 16 to 0 on separate lines, as well as 0 to 16 again on separate lines. I can do this with recursion very well for some reason, but without being able to do that, I am lost on how to make this work.
My computing class is learning with C language, so that is what my code is written in.We are also not required to validate input and are under the assumption that the user is entering valid input (a positive integer). Any tips are well appreciated! Thank you.
#include <stdio.h>
void loop_down_to_zero(int number);
void loop_up_to_int(int number);
int main(int argc, char* argv[])
{
printf("please enter a positive integer:");
int number;
number = ("%d" >= 0);
loop_down_to_zero(number);
loop_up_to_int(number);
scanf("%d", &number);
printf("****\n");
return 0;
}
void loop_down_to_zero(int number)
{
while ( number > 0 )
{
loop_down_to_zero(number - 1);
printf("\n%d", number-1);
}
}
void loop_up_to_int(int number)
{
while ( number >= 0 )
{
loop_up_to_int(number+ 1);
printf("%d\n", number+1);
}
return;
}
This is not C
number = ("%d" >= 0);
At least not any meaningful C.
Replace it by the actual input-reading a few lines later,
scanf("%d", &number);
So that you have a meaningful number for the calls to the functions.
That should solve you immediate blocking point.
Then have a look at the hint at your next problem, provided as a comment by arvind:
"Also your number is positive and you're incrementing it so, while ( number >= 0 ) doesn't make any sense." You probably want something including (current_number <= number).
Then for a recursion solutin use if instead of while.
Then to get you started on a non-recursive solution, actually change within the loop body the variable you are testing inside the loop condition;
otherwise you have a guaranteed endless loop killing your programs functionality.
(I intentionally do not give a complete solution, according to the compromise described here, How do I ask and answer homework questions? The asker-side of which OP has well honored in my opinon.)
I want to get a variable from user and set it for my array size. But in C I cannot use variable for array size. Also I cannot use pointers and * signs for my project because i'm learning C and my teacher said it's forbidden.
Can someone tell me a way to take array size from user?
At last, I want to do this two projects:
1- Take n from user and get int numbers from user then reverse print entries.
2- Take n from user and get float numbers from user and calculate average.
The lone way is using array with variable size.
<3
EDIT (ANSWER THIS):
Let me tell full of story.
First Question of my teacher is:
Get entries (int) from user until user entered '-1', then type entry numbers from last to first. ( Teacher asked me to solve this project with recursive functions and with NO any array )
Second Question is:
Get n entries (float) from user and calculate their average. ( For this I must use arrays and functions or simple codes with NO any pointer )
Modern C has variable size arrays, as follows:
void example(int size)
{
int myArray[size];
//...
}
The size shouldn't be too large because the aray is allocated on the stack. If it is too large, the stack will overflow. Also, this aray only exists in the function (here: funtion example) and you cannot return it to a caller.
I think your task is to come up with a solution that does not use arrays.
For task 2 that is pretty simple. Just accumulate the input and divide by the number of inputs before printing. Like:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float result = 0;
float f;
int n = 0;
printf("How many numbers?\n");
if (scanf("%d", &n) != 1) exit(1);
for (int i=0; i < n; ++i)
{
if (scanf("%f", &f) != 1) exit(1);
result += f;
}
result /= n;
printf("average is %f\n", result);
return 0;
}
The first task is a bit more complicated but can be solved using recursion. Here is an algorithm in pseudo code.
void foo(int n) // where n is the number of inputs remaining
{
if (n == 0) return; // no input remaining so just return
int input = getInput; // get next user input
foo(n - 1); // call recursive
print input; // print the input received above
}
and call it like
foo(5); // To get 5 inputs and print them in reverse order
I'll leave for OP to turn this pseudo code into real code.
You can actually use variable sized arrays. They are allowed when compiling with -std=c99
Otherwise, you can over-allocate the array with an arbitrary size (like an upper bound of your actual size) then use it the actual n provided by the user.
I don't know if this helps you, if not please provide more info and possibly what you have already achieved.
My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?
Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.
int i,j,n,matrica[i][j],suma=0;
srand(time(NULL));
printf("\nunesi prirodan broj N[3,20] = \n");
scanf("%d",&n);
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
matrica[i][j]=rand()%100;
printf("%d, %d = %4d ",i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
printf("\n");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d, %d = %4d ", i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):
We need to use malloc to allocate the dynamic amount of memory.
After
scanf("%d",&n) // PS You should check the return value - read the manual page
Put
matrica = malloc(sizeof(int) * n * n);
And declare it as
int *matrica;
Then replace
matrica[i][j]
with
matrica[i * n + j]
And after you have finished with matrica - use free i.e.
free(matrica);
int i,j,n,matrica[i][j]
At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.
Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...
I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
printf("Enter n, please: ");
fflush(stdout);
if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) {
puts("Invalid input or arithmetic overflow...");
return -1;
}
int (*array)[n] = malloc(n * sizeof *array);
if (!array) {
puts("Allocation error...");
return -1;
}
/* now you can use array[0..(n-1)][0..(n-1)] as you might expect */
free(array);
}
This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...
... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.
I've been looking into this simple piece of code for 1.5 hrs now and do not find the mistake. I start going crazy ;)
Could anyone of you with a fresh mind and view give me a little hint, where I might have the mistake in? (I am relatively new to C)
The problem is: The code works fine for most of the numbers I entered and tested, but accidentically I found a number that does not work: 3486118 (or 55777888 which is a multiple of it) It goes right for the first loop(s), but after factor 2 it becomes an endless loop.
Here is my code: (any help is greatly appreciated)
// Program calculates prime factors of entered number and returns them
#include <stdio.h>
int main() {
long int num, num_cp;
long int product=1;
/*prime number array up to 100.000*/
long int prime[] = {2, 3, **[...cut out MANY numbers...]** 99971, 99989, 99991};
printf("Please enter a positive integer:\n");
scanf("%li", &num);//55777888 or 3486118 not working... why?
//copy the entered number to keep the original for comparison with "product" and "break;" if equal
num_cp=num;
printf("prime factorization of %li:\n\n", num);
for (int i=0; i<sizeof(prime); i++) {
if (num_cp%prime[i]==0) {
num_cp/=prime[i];
product*=prime[i];
if (product==num) {
printf("%li\n\n", prime[i]);
break;
}
printf("%li*", prime[i]);
//If prime factor found but "product" is still not equal to "num" reset loop counter "i" to -1 (==0 in next loop)
i=-1;
}
}
printf("END");
return 0;
}
"I've been looking into this simple piece of code for 1.5 hrs now and do not find the mistake. I start going crazy ;)"
Don't. Leave it. Go away and eat a pizza. Veg out in front of your favourite movie. Have a shower. Aim for a new high-score on 2048 (or whatever). Your brain gets stuck in a rut and you are no longer seeing your code. You are only seeing what you think your code is.
When you get your brain out of the rut, then -- and only then -- go back and actually read the code you wrote. Not the code you think you wrote, but the code you actually wrote. Yes, they are different.
The prime factors of 55777888 are 2·2·2·2·2·1743059, where the last factor is too large to be contained in your list.
You can fix this in your code: When the product is equal to the product of the prime factors you have found, num_cp is 1. If num_cp is greater than one after you have exhausted your prime list, it is a factor of num. If num/num_cp is smaller than the largest prime you have checked, you can assume that the remaining value of num_cp is a prime. If it wasn't you'd have found more factors earlier.
You can fix this by adding an additional check after your main loop:
if (num_cp > 1) printf("%li\n\n", num_cp);
(If long int is a 64-bit number on your system, you're still not safe: The remaining factor might be made up of several numbers that are not in your array.)
Finally: Resetting the for loop counter so that the loop starts over isn't a good idea. It always starts from the beginning and re-checks primes that you have already checked. And it just isn't natural program flow, which makes it hard to read. A while loop instead of the inner if block would be more natural in my opinion.
Edit: To illustrate:
#include <stdio.h>
int main() {
long int num;
/* prime number array up to 100.000 */
long int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int nprime = sizeof(prime) / sizeof(*prime);
num = 55;
printf("%li == ", num);
for (int i = 0; i < nprime; i++) {
long int p = prime[i];
if (num <= 1) break;
while (num % p == 0) {
num /= prime[i];
printf("%li", p);
if (num > 1) printf(" * ");
}
}
if (num > 1) printf("%li", num);
printf("\n");
return 0;
}
Things to note:
Instead of resetting the main loop counter i, a while loop is used, which consumes all repetitions of the same factor. If a prime p doesn't divide the number, the while loop isn't entered, just like an if clause.
I've removed the copy of num and used num throughout, mainly to remove clutter. I've also removed the product. Your logic that all prime factors should multiply to the original number, is good. But it also works the other way round: After dividing the number by all primes, we are left with 1. And we have to divide the number anyways. By removing the product, we have to keep track of only one variable instead of two.
I've moved the break condition to the front, so we catch negative numbers and 0 early.
That said, your way to code isn't wrong, just maybe a bit unusual in places.
Hello getting better at C everyday, this is a example problem out of my textbook that generates fibonacci numbers and shows recursive functions. The program works but I just don't understand how... Specifically in parts (looper % 5), the whole functionfib and what printf(", %8ld", fib(looper)); is doing. Is it like saying fib() do x amount of times. If this problem is not easy to explain then could someone show me a easier way to understand how recursive functions work other then "towers of hanoi" example. Thanks.
NOTE: program is meant to handle up to 30 numbers others wise it starts to look ugly.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
long fib (long num);
int main(void)
{
int seriesSize;
printf("This program will print out a Fibonacci series.\n");
printf("How many many numers do you wnat? ");
scanf_s("%d", &seriesSize);
printf("First %d Fib numbers: \n", seriesSize);
for (int looper = 0; looper < seriesSize; looper++)
{
if (looper % 5)
{
printf(", %8ld", fib(looper));
}
else
{
printf("\n%8ld", fib(looper));
}
}
printf("\n");
return 0;
}
long fib(long num)
{
if (num == 0 || num == 1)
{
return num;
}
return (fib(num - 1) + fib(num - 2));
}
The idea behind the long fib(long num) function is that it mirrors the natural definition of the fibonacci sequence in that it is defined in terms of itself. That is, fib(n) is defined by fib(n-1) and fib(n-2). For example, fib(5) is fib(4)+fib(3).
The textbook has written the function in a recursive manner as described above. Note that this is not the most efficient way to implement a fibonacci function but it does logically make sense.
To understand it, it pays to trace through its execution with an example input. Take fib(3) for example. The first if statement doesn't trigger because num is not 0 or 1. Thus, it works out what fib(2) and fib(1) are, and adds them together. We know what fib(1) does - it returns 1 in the first if statement. Trace through fib(2) in a similar manner and you'll see that it returns 1. Thus, fib(3) will return fib(2)+fib(1)=2. You can extend this further - take fib(4). It will return fib(3)+fib(2), which we know are 2 and 1, hence fib(4) = 3.
This approach can be taken for most recursive functions - think of it as creating new instances of the fib() function which continually creates until it "bottoms out" at an end case (num == 1 or num == 0, in this case), and returns back up, filling in the answers until you get back to the function you started with, with the answer.