Python return statement not running - python

I am creating a program to figure out the highest number of decimals in a list of numbers. Basically, a list with [123, 1233] would return 4 because 1233 has four numbers in it and it is the largest. Another example would be that [12, 4333, 5, 555555] would return 6 because 555555 has 6 numbers.
Here is my code.
def place(listy):
if len(listy) == 1:
decimal = len(str(listy[0]))
print(decimal)
else:
if len(str(listy[0])) >= len(str(listy[1])):
new_list = listy[0:1]
for i in listy[2:]:
new_list.append(i)
place(new_list)
else:
place(listy[1:])
Now, when I use print(decimal) it works, but if I change print(decimal) to return decimal, it doesn't return anything. Why is this? How do I fix this? I have come across these return statements which doing run a lot of times. Thanks in advance!

When you do a recursive call (i.e. when place calls place, and the called place returns a value, then the calling place must return it as well (i.e. the return value "bubbles up" to the initial caller).
So you need to replace every recursive call
place(...)
with
return place(...)
As others have said, there are easier solutions, such as using max(). If you want to keep a recursive approach, I would refactor your code as follows:
def place2(listy):
if len(listy) < 1:
return None
elif len(listy) == 1:
return len(str(listy[0]))
else:
v0, v1 = listy[0], listy[1]
if v1 > v0:
return place2(listy[1:])
else:
return place2([listy[0]]+listy[2:])
Although this is tail-recursive, Python does not really care so this approach will be inefficient. Using max(), or using a loop will be the better solution in Python.

It's not that the return doesn't do anything, it's that you don't propagate the return from your recursive call. You need a few more returns:
def place(listy):
if len(listy) == 1:
decimal = len(str(listy[0]))
return decimal
else:
if len(str(listy[0])) >= len(str(listy[1])):
new_list = listy[0:1]
for i in listy[2:]:
new_list.append(i)
return place(new_list) # <-- return added
else:
return place(listy[1:]) # <-- return added
You can see the print at any level, but to get it back to the caller it needs to be propagated.

The function does return the value, but it's not printing it out.
A simple way to solve this is, just call the function within a print statement.
That is:
print(place(listy))

If all you want is to find the maximum length of a list of integers, consider:
max([len(str(n)) for n in N])
For example
N = [1,22,333,4444]
max([len(str(n)) for n in N]) # Returns 4
N = [12, 4333, 5, 555555]
max([len(str(n)) for n in N]) # Returns 6
Note: This will only work for positive integers.
Or more simply:
len(str(max(N)))
Which will also only work for positive integers.

Use ''global variable'' (google it) to access and change a variable defined outside of your function.

Related

How to keep track the amount of even integers when looking through randomized list using recursion

Sorta newbie here. So in trying to wrap my head around using recursive functions I wanted to try to make a program that:
1: Generates a list containing 10 random integers ranging from 0 - 20
2: Using a recursive function goes trough the list and finds out what elements of the list are even integers
3: Prints out only the aformentioned even numbers
Where I have gotten stuck is in how to print out the result. I can't seem to figure out what value i want to put inside the function when calling it ( F(?) )
I tried to integrate a counter that kept track on how many times the program found a even number but it always resulted in an error that the variable is not defined no matter how hard I tried to make it global.
How could I go about this? Am I totally in the wrong?
import random
numL = []
for i in range(10):
x = random.randint(0,20)
numL.append(x)
print(numL)
def F(x):
if numL[x] % 2 == 0:
return numL[x]
else:
return F(x+1)
print(F( ??? ))
First question asked on this forum, hopefully I did okay, appreciate any help!
Assuming you want to return a list of the even numbers then you have 4 cases to consider
This is the last number in the list and its even so return this number
This is the last number in the list and its odd dont retrun this number
There are more numbers to check and this number is even so return
this plus the function result
There are more numbers to check and this number is odd to return
only the function result and not this num
So we can code this as
import random
def get_even_nums(nums):
num = nums[0]
#This is our terminating case we definitivly return a value here
if len(nums) == 1:
return [num] if num % 2 == 0 else []
else:
#If we got here we will be recursivly calling the function
#If its even number return that number plus the result of the function
#it its not even then just return the reult of the function and not this num
if num % 2 == 0:
return [num] + get_even_nums(nums[1:])
else:
return get_even_nums(nums[1:])
numL = [random.randint(0, 20) for _ in range(10)]
print(numL)
print(get_even_nums(numL))
OUTPUT
[3, 6, 5, 10, 20, 18, 5, 0, 3, 9]
[6, 10, 20, 18, 0]
So I took your function and changed it up slightly (using a slightly different approach). There's no need to a global list, though you could do that as well, if you wanted. The problem that you have is the lack of a base case or rather an incorrect one.
If you run your original function with an argument 0, which basically is the first element of your generated array, the fucntion will run until it hits one even number. At that point it'll exit recursion, because the base case basically stops recursive calls once you hit an even number.
Now, to fix this, you have to approach the problem differently. I would put your generated array as the input argument to your function, then ask myself "What would be a good base case?" Probably one that stops your recursive calls once you reach the end of the input list.
if len(numL) == 0:
return ...
Also, we need a way to return the even numbers that we found during our search through the list. For that reason I'd introduce a new acc list, where we would append the even numbers that we found. Thus the function input arguments would be
def F(numL, acc):
...
Now, in the recursive call we should check wether the current element is even or not. If it is, great, we add it to the acc list and continue into the recursive call. If it's not, we don't add anything to the acc but just continue with recursion.
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
Putting it all together, we get:
def F(numL, acc):
if len(numL) == 0:
return acc
else:
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
where numL represents your generated list and acc represents the resulting list we'll return after we traverse the list.
This is your function (as I understand it, you wanted this):
import random
def F(i):
r = random.randint(0,20)
if r % 2 == 0:
print(r)
i += 1
if i != 10:
F(i)
F(0)

recursive function to sum of first odd numbers python

I'm trying to convert below code to recursive function but seems i'm quite confusing how could i write below in recursive function. could help me to give some thoughts?
Basically, what I'm generating below is the sum of the first n odd numbers.
def sum_odd_n(n):
total=0
j=2*n-1
i=1
if i>j:
return 1
else:
total =((j+1)/2)**2
i+=2
return total
> >>> sum_odd_n(5)
> 25.0
> >>> sum_odd_n(4)
> 16.0
> >>> sum_odd_n(1)
> 1.0
This smells somewhat like homework so I'm going to offer some advice instead of a solution.
Recursion is about expressing a problem in terms of itself.
Suppose you know the sum of the odd numbers from N to N - 2.
Can you write the total sum in terms of this sum and the function itself (or a related helper function)?
Recursive functions have at least one base case and at least one recursive call. Here are some hints:
def f(n):
# Base case - for which
# n do we already know the answer
# and can return it without
# more function calls? (Clearly,
# this must also terminate any
# recursive sequence.)
if n == ???:
return ???
# Otherwise, lets say we know the answer
# to f(n - 1) and assign it to
# the variable, 'rest'
rest = f(n - 1)
# What do we need to do with 'rest'
# to return the complete result
return rest + ???
Fill out the question marks and you'll have the answer.
Try:
def sum_of_odd(n):
if n>0:
x=(n*2)-1
return x+sum_of_odd(n-1)
else:
return 0
The answer of this:
sum_of_odd(5)
will be:
25
Try :
def sum_odd_n(n):
if n>0:
if n==1:
return 1
else:
return 2*n-1 + sum_odd_n(n-1)

How to rewrite this function as a recursive function?

def digits(n):
res = []
while n > 0:
res.append(n % 10)
n /= 10
return res
I want to rewrite this function so it uses recursion. I'm currently lost as to what to do. Can anyone give me some direction?
To create a recursive function you need to determine two things:
1) The base case - the condition on which you want to stop recursion
2) The general case - what to do on every input but the base case
You have already found both of these things, the base case is the while loop condition and the general case is the inside of the while loop. Try to use this information to move forward.
Here's a possible solution:
def digits(n):
if n < 10:
return [n]
return digits(n/10) + [n%10]
digits(123)
> [1, 2, 3]
The above solution fixes a bug in your code, you were returning the digits in reverse order. Also notice that n must be an integer greater than or equal to zero for producing correct results.
Here's how it works:
If the number is less than 10, then return a list with the number, as there are no more digits to be processed
If the number is greater than 9, get the last digit in the current number and add it to the end of the list that results of recursively calling digits on a smaller number - namely, the number without the last digit that we just processed.
The call to digits(123) will look like this at each step of the recursion:
digits(123) = digits(123/10) + [3]
digits(12) = digits(12/10) + [2]
digits(1) = [1]
Now we go up the call stack:
[1]
[1] + [2]
[1, 2] + [3]
[1, 2, 3]
EDIT :
Accepting #thg435's challenge, here's a tail-recursive solution:
def digits(n):
def loop(i, acc):
if i < 10:
return [i] + acc
return loop(i/10, [i%10] + acc)
return loop(n, [])
When you use recursion, a good basis is to have two cases to check, a base case and a recursive case. The base case is the conditions and result under which the program returns, in your case, the base case would be when n > 0 (If you think of it like a while loop, it's the condition for the while loop exiting). The recursive case (there can be multiple of these) occur when the loop isn't done, if you compare to a while loop, this is basically the body of the loop. At the end of the recursive case, you need to call the function again with your changes to the input, in this case n/10.
So, your function definition would be something like:
def digits(n):
For the base case, you want to check if n is 0, and, if it is, return the empty list:
if n <= 0:
return []
Now, in the recursive case, you want to append n%10 to the list and call your function again, only you want to call it with a different n, changed as you had it in your while loop:
else:
return [n%10]+digits(n/10)
So, if you trace this through, for every recursive case, you get a list containing n%10, then it adds the result of the new call, which will be either (n/10)%10 or the empty list. For example, running this function with n=100 would break down like this:
newlist = digits(100)
newlist = [100%10]+digits(100/10)
newlist = [100%10]+([10%10] + digits(10/10))
newlist = [100%10]+([10%10] + ([1%10] + digits(10/10)))
newlist = [100%10]+([10%10] + ([1%10] + ([])))
newlist = [0,0,1]
Nested parens are used to show how the function digits gets rewritten inline.
def digits(n):
res = []
res.append(n%10)
n /= 10
if n != 0:
return res + digits(n)
else:
return res

How can I use recursion to find palindromes using Python?

I've just started exploring the wonders of programming. I'm trying to write a code to identify numeric palindromes. Just looking at numbers and not texts. I'm trying to learn to use recursion here. But I'm just not getting anywhere and I can't figure out what's wrong with it.
My idea was to check first string vs the last, then delete these two if they match, and repeat. Eventually there'll be nothing left (implying it is a palindrome) or there will be a couple that doesn't match (implying the reverse).
I know there are better codes to finding palindromes in but I just wanted to try my hand at recursion.
So what's wrong?
def f(n):
global li
li=list(str(n))
if (len(li)==(1 or 0)):
return True
elif li[len(li)-1]==li[0]:
del li[0]
del li[len(li)-1]
if len(li)==0:
return True
if len(li)>0:
global x
x=''.join(li)
str(x)
f(x)
else:
return False
Thanks in advance!
A few comments
Why are x and li globals? In recursion, all variables should be local.
Why are you converting back and forth between str and list? You can subscript both of them
You need to return the result of your recursive call: return f(x)
Try these suggestions, and see how it works out.
Before looking into it too much, if (len(li)==(1 or 0)): doesn't do what you're expecting it to do. (1 or 0) will always evaluate to 1.
You probably want:
if len(li) in (1, 0):
There are a couple of problems with your solution. Let me analyse them line by line.
You don't need global statements if you don't intend to change variables outside of function scope. Thus, I removed two lines with global from your code.
li=list(str(n)): casting a string to a list is unnecessary, as a string in Python has a similar interface to an immutable list. So a simple li = str(n) will suffice.
if (len(li)==(1 or 0)):: although it looks OK, it is in fact an incorrect way to compare a value to a few other values. The or operator returns the first "true" value from its left or right operand, so in this case it always returns 1. Instead, you can use the in operator, which checks whether the left operand is an element of a right operand. If we make the right operand a tuple (1, 0), all will be well. Furthermore, you don't need parentheses around the if statement. You should write: if len(li) in (1, 0):
elif li[len(li)-1]==li[0]: is fine, but we can write this shorter in Python, because it supports negative list indexing: elif li[-1] == li[0]:
Because we don't use lists (mutable sequences) because of point 2., we can't do del li[0] on them. And anyway, removing the first element of a list is very inefficient in Python (the whole list must be copied). From the very same reason, we can't do del li[len(li)-1]. Instead, we can use the "splicing" operator to extract a substring from the string: li = li[1:-1]
if len(li)==0: is unnecessary long. In Python, empty strings and lists resolve to False if tested by an if. So you can write if not li:
if len(li)>0:: You don't have to check again if li is not empty -- you checked it in point 6. So a simple else: would suffice. Or even better, remove this line completely and unindent the rest of the function, because the body of the if in 6. contains a return. So if we didn't enter the if, we are in the else without writing it at all.
x=''.join(li): We don't need to convert our string to a string, because of the decision made in 2. Remove this line.
str(x): This line didn't do anything useful in your code, because str() doesn't modify its argument in place, but returns a new value (so x = str(x) would have more sense). You can also remove it.
f(x): This is a valid way to call a recursive function in Python, but you have to do something with its value. Return it perhaps? We'll change it to: return f(li) (as we don't have an x variable any more).
We end up with the following code:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
if not li:
return True
return f(li)
else:
return False
It's almost what we need, but still a little refinement can be made. If you look at the lines if not li: return True, you'll see that they are not necessary. If we remove them, then f will be called with an empty string as the argument, len(li) will equal 0 and True will be returned anyway. So we'll go ahead and remove these lines:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
return f(li)
else:
return False
And that's it! Good luck on your way to becoming a successful programmer!
Split the whole show out into a list, then just:
def fun(yourList):
if yourList.pop(0) == yourList.pop(-1):
if len(yourList) < 2:
return True # We're a palindrome
else:
return fun(yourList)
else:
return False # We're not a palindrome
print "1234321"
print fun(list("1234321")) # True
print "6234321"
print fun(list("6234321")) # False
def palindrome(n):
return n == n[::-1]
It's hard to tell what you intend to do from your code, but I wrote a simpler (also recursive) example that might make it easier for you to understand:
def is_palindrome(num):
s = str(num)
if s[0] != s[-1]:
return False
elif not s[1:-1]:
return True
else:
return is_palindrome(int(s[1:-1]))
number = int(raw_input("Enter a number: "))
rev = 0
neg = number
original = number
if (number < 0):
number = number * -1
else:
number = number
while ( number > 0 ):
k = number % 10
number = number / 10
rev = k + ( rev * 10 )
if (number < 1):
break
if ( neg < 0 ):
rev = ( rev * -1)
else:
rev = (rev)
if ( rev == original):
print "The number you entered is a palindrome number"
else:
print "The number you entered is not a palindrome number"
This code even works for the negative numbers i am new to programming in case of any errors
dont mind.

recursive method returning original value

So I'm trying to learn python on my own, and am doing coding puzzles. I came across one that pretty much ask for the best position to stand in line to win a contest. The person running the contest gets rid of people standing in odd number positions.
So for example if 1, 2, 3, 4, 5
It would get rid of the odd positions leaving 2, 4
Would get rid of the remaining odd positions leaving 4 as the winner.
When I'm debugging the code seems to be working, but it's returning [1,2,3,4,5] instead of the expected [4]
Here is my code:
def findWinner(contestants):
if (len(contestants) != 1):
remainingContestants = []
for i, contestant in enumerate(contestants, 1):
if (isEven(i)):
remainingContestants.append(contestant)
findWinner(remainingContestants)
return contestants
Am I not seeing a logic error or is there something else that I'm not seeing?
You must return the value from the recurse function to the caller function:
return findWinner(remainingContestants)
else you would return just the original value without any changes.
def findWinner(contestants):
if (len(contestants) != 1):
remainingContestants = []
for i, contestant in enumerate(contestants, 1):
if (isEven(i)):
remainingContestants.append(contestant)
return findWinner(remainingContestants) # here the value must be return
return contestants # without the return above, it will just return this value(original)
How about this:
def findWinner(contestants):
return [contestants[2**int(math.log(len(contestants),2))-1]]
I know its not what the questions really about but I had to =P. I cant just look at all that work for finding the greatest power of 2 less than contestants and not point it out.
or if you don't like the 'artificial' solution and would like to actually perform the process:
def findWinner2(c):
while len(c) > 1:
c = [obj for index, obj in enumerate(c, 1) if index % 2 == 0] #or c = c[1::2] thanks desfido
return c
you shold use
return findWinner(remaingContestants)
otherwise, of course, your list will never be updated and so your func is gonna always return containts
however, see the PEP8 for style guide on python code: http://www.python.org/dev/peps/pep-0008/
the func isEven is probably an overkill...just write
if not num % 2
finally, recursion in python isn't recommended; make something like
def find_winner(alist):
while len(alist) > 1:
to_get_rid = []
for pos, obj in enumerate(alist, 1):
if pos % 2:
to_get_rid.append(obj)
alist = [x for x in alist if not (x in to_get_rid)]
return alist
Is there a reason you're iterating over the list instead of using a slice? Doesn't seem very python-y to not use them to me.
Additionally, you might want to do something sensible in the case of an empty list. You'll currently go into an infinite loop.
I'd write your function as
def findWinner(contestants):
if not contestants:
raise Exception
if len(contestants)==1:
return contestants[0]
return findWinner(contestants[1::2])
(much as #jon_darkstar's point, this is a bit tangential to the question you are explicitly asking, but still a good practice to engage in over what you're doing)
You are missing a return at the line where you call "findWinner"

Categories

Resources