def countz(n):
if n<10:
if n==0:
return 1
else:
return 0
small=countz(n//10)
if n%10==0:
return small+1
else:
return small
from sys import setrecursionlimit
setrecursionlimit(11000)
n = int(input())
print(countz(n))
Someone helped me write this code, I did not understand why he used the condition n<10 in the base case of the recursion. I though the code would work without that condition but it didn't. Can anyone help me understand why the code is not working without that condition/ what is the real purpose or reason for that condition?
The base case that we want here is indeed n<10, or in words, n is a single digit number.
You might be tempted to choose n==0 as the base case and simply return 1 because it has one zero:
def countz(n):
if n==0:
return 1
small=countz(n//10)
if n%10==0:
return small+1
else:
return small
But that wouldn't work! Why? Consider the input 9, which has no zeroes. This isn't the base case, so we enter the recursive call: small=countz(n//10). n//10 gives 0, so we call countz(0) which returns 1. This is then returned as the answer, even though it should be 0.
The underlying problem is that, by convention, we denote the number zero with one more digit than is actually needed. Ideally it would consist of no digits at all, but that would be a bit impractical in daily life!
Related
I'm trying to become comfortable with python. I've been trying some simple activities that I've given in my beginning c++ classes when I was teaching. I did one involving functions and writing a file which worked flawlessly. I thought this one would be easier. It acts like it is in a silent endless loop, but it won't even let me trace it. Can someone see where I am going awry?
# Find Adam Numbers
def isAdamNumber(candidate):
isAdam = False
rev = reverse(candidate)
square = candidate * candidate
revsq = rev*rev
if revsq == reverse(square):
isAdam = True
return isAdam
def reverse(num):
rev=0
while num > 0:
rev = rev * 10 + num%10
num/=10
return rev
for x in range (11,25):
if isAdamNumber(x):
print(x, " is an adam number\n")
The quick fix is to change /= with the integer division version, //=
Inside the reverse function, you are going into an infinite loop. num value always will be greater than 0, therefore the while loop will continuously run. In python, you can get the reverse of the function without much effort. Convert the integer to string and reverse the string and now change the string back to integer.
def reverse(num):
num_str = str(num)[::-1]
return int(num_str)
I think this function definition can solve your problem.
To visualize the python to learn and teach, use this link
The problem has already been addressed by the other answers, so here's the expanded and simplified version of the slicing that's going on [this doesn't actually use slicing]:
def reverse(num):
rev = ''
num = str(num)
for i in range(len(num) - 1, -1, -1):
rev += num[i]
return int(rev)
This counts backward from the last element in the string version of num, and adds all the elements of num (in reverse order) to rev.
num > 0 is never False. Dividing a positive number by 10 repeatedly makes it smaller, but it never becomes zero, so the while loop keeps repeating.
Use //= instead. It rounds to the nearest integer, so it will reach 0.
This also wouldn't reverse numbers (unless I'm missing something). Alternatively, you can use
int(str(num)[::-1])
which converts the number to a string, reverses it using slicing, and turns it back into an integer.
I am writing a recursive function to calculate the digital root of a given number:
def digital_root(num):
sum = 0
while num > 0:
sum += num % 10
num = num // 10
while sum > 10:
sum = digital_root(sum)
return sum
I am not sure if the second while should be replaced with an if statement, and if so, why? (and if not, why not?)
When I try both of the version, the return value is the same.
For example, for the number 10598, the output in both of them is 5.
Please make sure to accept the answer if it works tired of people not accepting my solutions, when it works for them
def digital_root(num):
#Base case for recursion.
# recursion always needs a base case
if len(str(num)) == 1:
return num
#Get sum of num by turning it into a string and looping through it,
#adding each index one by one
sum = 0
for i in str(num):
sum += int(i)
#get the digital root of the sum
return digital_root(sum)
def main():
print(digital_root(27518))
if __name__ == '__main__':
main()
There you go
So, first, please think what you're asking.
If relates to a condition, and while relates to perform a repeated action as long as a certain condition holds.
The digital root recursion stops only when the resulting digit sum is less than 10.
we need "if" for the base case of recursion.
but in this special case, you are using "while" as "if" and that works. but for readability, it is better to use "if".
the reason that it works:
both "while" and "if" have conditions
and the difference between them is just looping through the instructions
and it will be the same again because of the recursion.
I mean in this special case, due to that we have recursion, "if" acts like "while"
this is another answer for acounting the Digital root of a number using recursion:
def digital_root(n):
if(n < 10):
return n
n=n%10+digital_root(n//10)
return digital_root(n)
Currently I'm experimenting a little bit with recursive functions in Python. I've read some things on the internet about them and I also built some simple functioning recursive functions myself. Although, I'm still not sure how to use the base case.
I know that a well-designed recursive function satisfies the following rules:
There is a base case.
The recursive steps work towards the base case.
The solutions of the subproblems provide a solution for the original problem.
Now I want to come down to the question that I have: Is it allowed to make up a base case from multiple statements?
In other words is the base case of the following self written script, valid?
def checkstring(n, string):
if len(string) == 1:
if string == n:
return 1
else:
return 0
if string[-1:] == n:
return 1 + checkstring(n, string[0:len(string) - 1])
else:
return checkstring(n, string[0:len(string) - 1])
print(checkstring('l', 'hello'))
Yes, of course it is: the only requirement on the base case is that it does not call the function recursively. Apart from that it can do anything it wants.
That is absolutely fine and valid function. Just remember that for any scenario that you can call a recursion function from, there should be a base case reachable by recursion flow.
For example, take a look at the following (stupid) recursive function:
def f(n):
if n == 0:
return True
return f(n - 2)
This function will never reach its base case (n == 0) if it was called for odd number, like 5. You want to avoid scenarios like that and think about all possible base cases the function can get to (in the example above, that would be 0 and 1). So you would do something like
def f(n):
if n == 0:
return True
if n == 1:
return False
if n < 0:
return f(-n)
return f(n - 2)
Now, that is correct function (with several ifs that checks if number is even).
Also note that your function will be quite slow. The reason for it is that Python string slices are slow and work for O(n) where n is length of sliced string. Thus, it is recommended to try non-recursive solution so that you can not re-slice string each time.
Also note that sometimes the function do not have strictly base case. For example, consider following brute-force function that prints all existing combinations of 4 digits:
def brute_force(a, current_digit):
if current_digit == 4:
# This means that we already chosen all 4 digits and
# we can just print the result
print a
else:
# Try to put each digit on the current_digit place and launch
# recursively
for i in range(10):
a[current_digit] = i
brute_force(a, current_digit + 1)
a = [0] * 4
brute_force(a, 0)
Here, because function does not return anything but just considers different options, we do not have a base case.
In simple terms Yes, as long as it does not require the need to call the function recursively to arrive at the base case. Everything else is allowed.
this was one of the problems I was assigned in MyProgrammingLab. I've attempted to answer this problem over 45 times, but can't get it right.
Any help will be appreciated
Question:
In the following sequence, each number (except the first two) is the sum of the previous two numbers: 0, 1, 1, 2, 3, 5, 8, 13, .... This sequence is known as the Fibonacci sequence.
We speak of the i'th element of the sequence (starting at 0)-- thus the 0th element is 0, the 1st element is 1, the 2nd element is 1, the 3rd element is 2 and so on. Given the positive integer n, associate the nth value of the fibonacci sequence with the variable result. For example, if n is associated with the value 8 then result would be associated with 21.
My work:
def fib(n):
if n <= 1:
result == n
elif n >= 1:
result = fib(n-1)+fib(n-2)
else:
return result
It's because in all of your cases, you assign the result but don't return it.
So, for example, when fib(1) is called, Python returns None because you never told it to return result in that case. The same thing happens for, say, fib(45).
To correct this, just return result always. (This is a good idea no matter what type of program you are writing - functions should always have an explicit return value).
def fib(n):
if n <= 1:
result = n
elif n > 1:
result = fib(n-1)+fib(n-2)
return result # always return result!
Things to Know
You should be aware that this implementation of the Fibonacci sequence is the least efficient one out there. If you can ditch the recursive calls altogether and just use a while loop to calculate fib(n) - or, if you want recursion, store previously computed values of fib(n) instead of forcing it to compute all the way to fib(n) - you will have a much more efficient implementation.
Your code contained numerous issues, such as
Assigning without returning, which we've already discussed.
Using == instead of =. The first checks if the left and right hand side are equal, and returns True or False. The second actually assigns the value of the right hand side to the variable on the left hand side. Don't confuse checking for equality with assignment.
Using the same base case twice but telling Python to do something different in both cases. This is such a bad idea that I feel jonrsharpe in the comments is justified in saying "Seriously?". The reason for this is because doing this makes no sense and makes it hard to predict behaviour. The whole point of an if-else statement is to do different things in different cases.
Edit based on examples provided by OP. Indentation should only be four spaces, not eight. This is more of a stylistic issue than anything else, but it is the standard.
def fib(n):
if n < 2:
return n
else:
return fib(n-1)+fib(n-2)
You can essentially reduce it to this. You could even leave out the else and say:
def fib(n):
if n < 2:
return n
return fib(n-1)+fib(n-2)
but you said you need to have an else-case for whatever reason.
I wrote this one for my assignment. I know it's a little indirect, but it works and that's what's important :)
n = int(input("Insert a number: "))
i = 0
fib_list = [1, 1, 0]
for i in range (0,2):
if n == 0:
result = fib_list[2]
elif n <= 2:
result = fib_list[0]
for i in range (2,n):
result = fib_list[0] + fib_list[1]
fib_list.insert(0, result)
i += 1
result = fib_list[0]
By the way, you don't need to define an input to use in the myprogramminglab question.
I added the input version here because I used it in my tests.
This question already has answers here:
How to create the most compact mapping n → isprime(n) up to a limit N?
(29 answers)
Closed 7 years ago.
I am new to Python and I'm attempting to write a code that checks to see whether or not a number is prime. So far, I've written this:
def main():
n = input("Enter number:")
isprime(n)
def isprime():
x = Prime
for m in range (1,n+1,1)
result = n % m
print result
main()
I'm not sure how to proceed after this. I know I have to define isprime. Any help would be greatly appreciated. Thank you!
Your first and biggest problem is that you need to list n as a parameter to isprime before you can use it within isprime, and before you can pass an argument in main. See the tutorial on Defining Functions for more details. But basically, it's like this:
def isprime(n):
Also, that x = Prime is going to raise a NameError, because there's nothing named Prime. Given that it doesn't actually do anything at all, you should just delete it.
Of course that won't make this a complete working prime testing function, but it is how to proceed from where you are.
The next step is to consider what to return from the function. If you find a value that divides n, then obviously n isn't prime, and therefore isprime is false. If you go through all possibilities and don't find anything that divides n, then isprime is true. So, with two return statements in the right places, you can finish the function.
Once it's at least always returning True or False, you have bugs to fix.*
Look at what numbers you get from range(1, n+1, 1). Two of those numbers are guaranteed to divide any n. How do you avoid that problem?
After you've got it working, then you can work on optimizing it. If you look up primality test on Wikipedia, you can see a really simple way to improve the naive trial division test. A bit of research will show the pros and cons of different algorithms. But if what you've got is fast enough for your purposes, it's usually not worth putting more effort into optimizing.
* You might want to consider writing a test program that calls isprime on a bunch of numbers and compares the results with the right answers (for answers you already know off the top of your head—1 is not prime, 2 is prime, 17 is prime, etc.). This is called Test Driven Development, and it's a great way to make sure you've covered all the possible cases—including outliers like 0, 1, 2, -3, etc.
Your isprime is quite close. The first line x = Prime is unnecessary, so let's get rid of that.
Now, let's take a look at what you're doing next:
You seem to want to check if there are any numbers that divide n perfectly. While this is the correct approach, you are including n and 1 in the numbers that you are testing. This is wrong for obvious reasons.
There is another error: you use n without ever defining it (I think you want it to be a parameter to your function). So let's put all this together:
def isprime(n):
for m in range(2, n):
if not n%m: # m divides n perfectly
return False
return True # if n were not prime, the function would have already returned
But going a step further, you don't really have to check every number between 2 and n-1. You just need to check the numbers between 2 and the square-root of n:
def isprime(n):
for m in range(2, int(n**0.5)+1):
if not n%m:
return False
return True