Function fun(n) is defined as such:
fun(n) = 1 (if n <=1)
fun(n) = fun(n/2) (if n is even)
fun(n) = 2*fun((n-1)/3) (if n> and n is odd)
I'm trying to write a recursive function to compute and return the result. I just started learning recursion, I got kind of lost while doing this function. Can someone correct me and explain to me? Thanks!
Here's what I did:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
int fun(int n);
int main()
{
int num;
printf("\nEnter a number: ");
scanf("%d", num);
printf("Result = %d\n", fun(num));
return 0;
}
int fun(int n)
{
if (n <= 1)
{
return 1;
}
else if (n % 2 == 0)
{
return fun(n / 2);
}
else if ((n > 1) && (n % 2 == 0))
{
return 2 * fun((n - 1) / 3);
}
}
Expected output:
Enter a number: 13
Result = 2
Enter a number: 34
Result = 4
Output I'm getting instead:
Enter a number: 13
Result = 1
Enter a number: 34
Result = 1
scanf takes a pointer to int as argument for %d, i.e.,
scanf("%d", &num);
Also, your function fun does not handle all cases and may fall off the bottom:
if (n <= 1)
{
return 1;
}
else if (n % 2 == 0)
{
return fun(n / 2);
}
else if ((n > 1) && (n % 2 == 0))
{
return 2 * fun((n - 1) / 3);
}
The last else if condition is never met, because the previous check for n % 2 == 0 already returns in that case. Also the n > 1 is pointless because the first n <= 1 returns in all other cases.
You can simply make it:
else
{
return 2 * fun((n - 1) / 3);
}
The culprit is the last else if condition. Change it to:
else if ((n % 2) != 0)
The condition that n is odd is written wrong here. You wrote the same thing as for when n is even.
Its probably better to explicitly make the cases disjoint so you always return and there's no warning, like this:
int fun(int n)
{
if(n <= 1)
return 1;
if(n % 2 == 0)
return fun(n/2);
//No need for a condition, we know the last one must be satisfied
return 2 * fun((n-1)/3);
}
or, add another "default" case that indicates there was some error.
I think last if should be:
else if ((n > 1) && (n % 2 != 0))
Notice the != instead of ==.
The third condition
else if ((n > 1) && (n % 2 == 0))
is wrong, but instead of fixing it just you else no else if - because all other conditions were checked already.
Related
Here is the code:
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>
// choose(n,m) returns how many ways there are to choose m items from
// a set of n items
// requires: 0 <= m, 0 <= n
int choose(int n, int m)
{
if (m == 0 || m == n)
{
return 1;
} // base case
// recursive step
return (choose(n - 1, m) + choose(n - 1, m - 1)); // continues until we have exhausted the
// number of possibilities to choose from, base case then terminates it
// taken from the assignment sheet
}
// num_divisors_up_to_k(n,k) returns the number of positive divisors
// of n that are less than or equal to k
// requires: 1 <= k <= n
int num_divisors_up_to_k(int n, int k)
{
if (k == 0)
{
return 0;
} // base case
if (n % k == 0) // if divisible by k return 1 and call recursively
{
// call function again moving to next number
return 1 + num_divisors_up_to_k(n, k - 1);
}
else // otherwise return 0 and call recursively
{
return 0 + num_divisors_up_to_k(n, k - 1); // next number
}
}
// is_prime(n) returns true if n is a prime number and false otherwise
// requires: 1 <= n
bool is_prime(int n)
{
if (n < 2) // 2 is the lowest prime number
{
return false;
}
for (int i = 2; (i * i) <= n; i++) // loop through each element
{
if (n % i == 0) // if divisible by i its not prime so return false
{
return false;
}
}
return true; // num is prime
}
// collatz(n) returns the number of steps it takes to reach 1 by
// by repeatedly applying the Collatz mapping on n; prints each
// number in the sequence starting at n
// requires: 1 <= n
int collatz(int n)
{
if (n == 1) // base case
{
return 0;
}
// print n
printf("%d ", n);
// even
if (n % 2 == 0)
{
// adding 1 and calling collatz again with next value
return 1 + collatz(n / 2);
}
else
{
// same thing as even just with the method for odd
return 1 + collatz(3 * n + 1);
}
}
int main()
{
// collatz code
int n;
printf("enter number:\n");
scanf("%d", &n);
while (n == 1)
{
// cant be negative or 0
if (n < 1)
{
printf("wrong input");
}
else
{
// else printing collatz sequence for input
printf("collatz(%d): ", n);
int steps = collatz(n);
// print out number of steps
printf("it took %d steps\n", steps);
}
// next input
printf("enter number: \n");
}
// TESTS CASES
// choose function
assert(choose(2, 1) == 2);
assert(choose(4, 2) == 6);
assert(choose(10, 10) == 1);
assert(choose(8, 2) == 28);
assert(choose(0, 0) == 1);
// num_divisors_up_to_k function
assert(num_divisors_up_to_k(9, 9) == 3);
assert(num_divisors_up_to_k(1, 1) == 1);
assert(num_divisors_up_to_k(100, 100) == 9);
assert(num_divisors_up_to_k(0, 0) == 0);
// is_prime function
assert(is_prime(10) == false);
assert(is_prime(2) == true);
assert(is_prime(7919) == true);
assert(is_prime(479001599) == true);
// collatz
assert(collatz(5) == 5);
assert(collatz(13) == 9);
assert(collatz(1) == 0);
printf("PASSED\n");
}
Code does not work in visual studio code but works in repl.it or any online complier. I pretty much get a runtime error on vscode and am forced to end the program myself. im not very good with the technicality of IDE's and I know this code doesn't work as intended but I can't fix it unless I can properly compile it and see the output. if anyone can help me my discord tag is ansh#1234 or you can reply here. looking forward to making this work and thank you in advance
Here is the output on VSCode:
Here is the output on repl.it:
There is configuration issue inyour Visual Studio Code setup. You should just run the program manually in a shell window by typing:
cd /Users/ansh/Desktop/c
gcc assignment1.c -o assignment1
./assignment1
Task is to "Write a program to sum all the integers between 1 and 1000, that are divisible by 13, 15 or 17, but not by 30". Here is my code:
#include <stdio.h>
int main()
{
int number = 1;
int sum = 0;
while(number <= 1000) {
++number;
if(((number % 13 ==0) || (number % 15 ==0) || (number % 17 ==0)) && (number % 30 != 0)){
sum = sum + number;
}
}
printf("Sum equals to %d.\n", sum);
return (0);
}
Output in my case is "Sum equals to 77796."
While on one of the posts it has "sum = 76795".
I don't understand why is that, tried changing code in different ways, but couldn't get to that answer.
For an idea of the problem, start by looking at the difference in results. You get 77796, while you expect 76795. The difference between these is 1001, which is a very big hint.
The line ++number; adds one to number, and you have this line before the code that does the check. By doing this you remove 1 from your search domain, and add the value 1001 to it.
To fix this, you can move the increment below the main body of the loop, as it was in the original code:
#include <stdio.h>
int main()
{
int number = 1;
int sum = 0;
while (number <= 1000) {
if(((number % 13 == 0) || (number % 15 == 0) || (number % 17 == 0)) && (number % 30 != 0)){
sum = sum + number;
}
++number;
}
printf("Sum equals to %d.\n", sum);
return (0);
}
This could be better written using a for loop, which exist for this purpose:
#include <stdio.h>
int main()
{
int sum = 0;
for(int number = 1; number <= 1000; ++number) {
if(((number % 13 == 0) || (number % 15 == 0) || (number % 17 == 0)) && (number % 30 != 0)){
sum = sum + number;
}
}
printf("Sum equals to %d.\n", sum);
return (0);
}
Both of these output the desired result:
Sum equals to 76795.
I'm trying to make a function calculating x to the power n (where x could be a double, n must be an int). A recursive algorithm would be this one, but implementing it in C gave me the stack-overflow error.
I tried finding my answer here, but the closest I found was this, which didn't satisfy my needs.
Here is my code:
double power_adapted(double x, int n) {
if (n == 0)
return 1;
else if (n == 1)
return x;
else if (n % 2 == 0)
return power_adapted(power_adapted(x, n / 2), 2);
else
return x * power_adapted(power_adapted(x, (n - 1) / 2), 2);
}
The recursive calls always pass 2 as n, so they will always trigger another recursive call.
I think you misinterpreted the formula. I would interpret it as:
else if (n % 2 == 0) {
double v = power_adapted(x, n / 2);
return v * v;
}
else {
double v = power_adapted(x, (n - 1) / 2);
return x * (v * v);
}
I don't think what you're trying to accomplish makes sense.
If you take a look at this part of code,
else if (n % 2 == 0)
return power_adapted(power_adapted(x, n / 2), 2);
else
return power_adapted(power_adapted(x, (n - 1) / 2), 2);
While the nested calls may present no problem (as a statement), the call on the outside always has n = 2 and the base cases depend on n.
Solving the problem:
By taking a look at the formula provided, I think you should have a base case for n == 2 to return x * x (this is the simplest change to the algorithm). So, the algorithm could be stated as follows:
double power_adapted(double x, int n) {
if (n == 0)
return 1;
else if (n == 1)
return x;
else if (n == 2)
return x * x;
else if (n % 2 == 0)
return power_adapted(power_adapted(x, n / 2), 2);
else
return x * power_adapted(power_adapted(x, (n - 1) / 2), 2);
}
I'm a first time programmer trying to complete a simple command line program as part of the first assignment for an online course I am taking, but I seem to have hit a roadblock that I can't figure out with GDB or my own research.
After hours of rewrites, and hours of debugging, I finally got the code below to compile. The program is supposed to take a credit card number as an input, and then check whether it's valid per the specifications of the assignment. I used a test number from here: PayPal Test Credit Cards
The odd thing is, when I enter an AMEX card number, it correctly produces the text "AMEX", but when I try a Visa or a Master Card, it prints "INVALID".
In GDB I broke at the Verify function and it seems to incorrectly skip these two if/else if statements without proceeding to the Checksum function even though conditions appear to be met.
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
...
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
...
The AMEX line of code that correctly executes is:
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
The arguments for all three lines seem to be formatted exactly the same. That is far as I could get in GDB though. I would print totalDigits, firstDigit, and secondDigit in GDB right before stepping through the above two non-executing lines and everything looked correct. So I'm stumped, why is the AMEX line executing, but not the others?
Thanks in advance everyone. This is the first program after hello.c that I've tried to write, so I am open to absolutely any criticism or suggestions if it looks like I'm doing something weird/wrong.
Full code:
checker.c
#include <stdio.h>
#include <stdlib.h>
int MAX = 16;
int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);
int main (void)
{
int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;
do
{
printf("Please enter a credit card number:\n");
scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.
switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
case 1 :
printf("VISA\n");
break;
case 2 :
printf("MASTERCARD\n");
break;
case 3 :
printf("AMEX\n");
break;
case 0 :
printf("INVALID\n");
break;
default :
printf("INVALID\n");
}
free(output);
return 0;
}
int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{
int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;
while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
totalDigits = totalDigits + 1;
i++;
}
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
return 1;
}
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
return 2;
}
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
{
return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
return 0;
}
}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.
int i = 0;
arrayReversed[0] = 0;
if (i < (MAX - 1) && x >= 10)
{
do
{
arrayReversed[i] = x % 10;
x = x / 10;
i++;
}
while (i < (MAX -1) && x >= 10);
}
if (i < MAX && x >= 1 && x <= 9)
{
arrayReversed[i] = (int) x;
x = (x - x);
}
if (x == 0)
{
int j = 0;
do
{
array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
j++;
i--;
}
while (j < MAX && i >= 0);
array[j] = -1;
}
free(arrayReversed);
return array;
}
int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);
while (i >= 0)
{
sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
i -= 2;
}
while (j >= 0)
{
sum2 = (cardNumber[j] + sum2);
j -= 2;
}
if (((sum1 + sum2) % 10) == 0)
{
return 0;
}
else
{
return 1;
}
}
Your first problem is here:
if (firstDigit == 4 && totalDigits == (13 | 16) && ...
You need to write:
if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...
Your first check is looking for 0x1D == 29 as the number of digits (because, as paisanco points out in a comment, the | operator is the bitwise OR operator), and no credit card needs 29 digits (yet, and not for a long time to come). Note the extra parentheses for clarity and accuracy. Don't mess around risking removing them — the code won't work properly again. And in general, be explicit if your condition has both && and || operators and use parentheses to group terms explicitly.
You have similar problems elsewhere. As it happens, (4 | 7) is the same value as 7, so the condition works when the second digit is 7 (but not when it is 4). But it doesn't mean what you intended it to mean.
Computer languages don't work the same as human languages. Get used to writing out the condition somewhat more verbosely. Some other languages provide shorthands for these conditions; C is not such a language.
I was writing a function which checks if every digit in a number is odd. I came accross this weird behaviour. Why does the second function return different (incorrect) results, eventhough its basically the same? (implemented in an opposite way)
#include <stdio.h>
int all_odd_1(int n) {
if (n == 0) return 0;
if (n < 0) n = -n;
while (n > 0) {
if (n&1 == 1)
n /= 10;
else
return 0;
}
return 1;
}
int all_odd_2(int n) {
if (n == 0) return 0;
if (n < 0) n = -n;
while (n > 0) {
if (n&1 == 0)
return 0;
else
n /= 10;
}
return 1;
}
int main() {
printf("all_odd_1\n");
printf("%d\n", all_odd_1(-131));
printf("%d\n", all_odd_1(121));
printf("%d\n", all_odd_1(2242));
printf("-----------------\n");
printf("all_odd_2\n");
printf("%d\n", all_odd_2(131));
printf("%d\n", all_odd_2(121));
printf("%d\n", all_odd_2(2242));
return 0;
}
warning: suggest parentheses around comparison in operand of '&'
Well, how about adding them ? Change n&1 to (n&1). Always ask for warnings.
The == operator has higher precedence than the & operator, so your if (n&1 == 0) statement is not doing what you expect!
(and the if (n&1 == 1) statement works only by coincidence that 1 == 1 evaluates to 1 ;)
Operator precedence. n & 1 == 0 is equivalent to n & (1 == 0)
It is a problem related to the order of execution. Try to use if ((n&1) == 0) in all_odd_2 and everything will work.