getting Nth value of a linked list recursively - python

I want to be able to be able to recursively pass count or increment count and then pass it into my recursion. However, I know I must declare count = 0 to be able to use it when incrementing. I am still learning python and I am finding it hard to recursively increment count. Could someone help me with this please?
I know currently my code is wrong because each recursion i make, count will be resent to 0. I don't want to set count as a 3rd argument because I feel as though it is not necessary.
my code:
def getNth(head, n):
count = 0
if count == n:
count += 1
return head.value
else:
if head.next is not None:
getNth(head.next,n)
else:
print 'not in linked list'

Count backwards rather than up.
def getNth(head, n):
if n == 0:
return head.value
return getNth(head.next, n - 1)
This however will perform miserably in practice, and you'll get a stack overflow if your list is any reasonable length. Functional programming style is not usually good Python style (since, for example, tail recursion isn't a feature of Python).
I'd just write the loop out.
def getNth(head, n):
for _ in xrange(n):
head = head.next
return head.value

This is a common pattern in recursion that is cleanly executed in python, so it's worth mentioning.
Methods allow keyword arguments, which are useful for keeping track of recursion depth. The change to your method signature is trivial:
def getNth(head, n, count=0):
0 is the default argument to count. Just leave it out in your initial call (or explicitly call it with count=0) and you're good. You can then easily recursively call getNth with getNth(*args, count + 1).
I should note now that I've explained this that recursion is quite slow in python. If you care at all about performance you should favor iterative solutions (often involving generators) over recursive solutions.

Related

benefit of generators in fibonacci series

I just saw an example of Fibonacci series using a generator from a webpage.
This is the example I saw
def fibonacci(n):
curr = 1
prev = 0
counter = 0
while counter < n:
yield curr
prev, curr = curr, prev + curr
counter += 1
The user can input the limit 'n'.
My question is what's the use of using generator here?
how generator benefits the user here?
What advantage he gets instead of just using a normal print message here to print the series?
I am agreeing if the user has to store the value in a list and process it later, yield can do generate number on fly.
What could be the use of yield in this case?
By yielding the value, the caller of the function has access to the intermediate results, making this memory efficient.
For example, the following would give you all results up to n as well, but requires that you create a list first to hold those values:
def fibonacci(n):
results = []
curr = 1
prev = 0
counter = 0
while counter < n:
results.append(curr)
prev, curr = curr, prev + curr
counter += 1
return results
If my code then asked for fibonacci(10 ** 9), that would not only take a long time to produce, but would also require a significant amount of memory.
The generator option gives the caller access to the results immediately, which means they can use just that one intermediate result in another part of the program.)
This makes the generator function far more versatile and flexible. You could sum the fibonacci results, without having to rewrite the generator, for example:
sum_of_fibonacci_10 = sum(fibonacci(10))
This is still memory efficient, the summing takes place as the results are produced, at no point do all 10 results have to exist in memory. Just the current intermediate value, and the sum total up to now, are required.
If you wanted to just print the values instead, you can do so in a loop:
for next_value in fibonacci(10):
print(next_value)
and the code is still just as efficient, and we still did not have to change the generator function.
So generators let you maintain and share intermediate state, saving you memory. This can be done with a class too, but a generator is much more readable. The following would do the same, but is not nearly as easy to follow:
class FibonacciGenerator:
def __init__(self, n):
self.n = n
self.curr = 1
self.prev = 0
self.counter = 0
def __iter__(self):
return self
def __next__(self):
if self.counter >= self.n:
raise StopIteration
self.prev, self.curr = self.curr, self.prev + self.curr
self.counter += 1
return self.prev
The advantage of a generator instead of a function is that it can keep its state.
If you had used a recursive function, calculating the 5th fibonacci number would be equivalent to calculating the 1st, then calculating the 1st and 2nd, then calculating the 1st, 2nd and 3rd, and so on until the 5th.
You can see how this is the problem for large numbers; there's a lot of resources being wasted.
With a generator, you calculate the 1st, and remember what it is, so that you don't have to calculate it again in order to find the second. Unlike a function that stops when it reaches its return, the generator can keep state. So it calculates the 1st number, and when requested, calculates the 2nd, then the 3rd, without wasting processing power because it doesn't need to recalculate the whole thing each time; it remembers its previous state.
With regards to print vs yield, obviously you can't use the printed result if you want to use the fibonacci numbers you calculated for something else; it's just output on the screen. If you'd like to generate a graph, for example, print wouldn't do, you'd have to pass values to your plotting function.
Using a generator allows you to generate the 'tip' of the sequence one at a time, at your leisure. You can retrieve and print the result, but you don't need to.
A plain ol' loop in a function would run until the breaking condition was met - or forever - and without any special bells and whistles, would block the execution of your code until the loop terminated.
This means an unbounded loop would only stop once you killed the interpreter, and soon enough you'd have to kill it because it would start eating resources like crazy computing very high sums.
Yield pauses between calls and returns the value rather than just displaying it unlike print(). This means you can retrieve nth fibonacci number, do some other stuff for five minutes, then retrieve n+1th number.

Recursion function to find highest value returns 0s

#find highest number
def HighValue(arr, HighestValue=0):
if len(arr) > 0:
arrayValue = arr.pop()
if len(arr) == 0:
return HighestValue
elif HighestValue <= arrayValue:
HighestValue = arrayValue
return HighValue(arr, HighestValue)
else:
return HighValue(arr, HighestValue)
print HighValue([1,2,3,4,5,6,7,8,9])
This function returns the highest value of an array using recursion. It works, but I feel like I am writing more code than necessary. Does anyone have any advice as to whether I could have made this recursion algorithm simpler? I hope I am allowed to ask quesitons like that here. If not, let me know. I feel I will get better if I get feedback from more experienced programers.
Let me know what you think.
Since there are some programming design basics involved, I'll answer this instead of remanding it to CodeReview.
Yes, you're writing more code than needed. You don't need to force all of the mechanics yourself. Worry about the base case, the recursion step, and the return value. Everything else should be easy from there.
Don't pass the best value through the parameter list; just pass back the best value you have so far.
Don't pop things off the list; just call the routine with the tail of the list. Note that my solution strips elements off the beginning, instead of the end. You are welcome to reverse this logic.
If the list is only one element long, return it. When you get back to the parent call, return the higher of the end element or the returned value:
def HighValue(arr):
best = 0
if len(arr) > 0:
best = HighestValue(arr[1:])
return best if best > arr[0] else arr[0]
If you're not worried about execution time, you can elide best with an extra recursive call.

Python list slicing efficiency

In the following code:
def listSum(alist):
"""Get sum of numbers in a list recursively."""
sum = 0
if len(alist) == 1:
return alist[0]
else:
return alist[0] + listSum(alist[1:])
return sum
is a new list created every time when I do listSum(alist[1:])?
If yes, is this the recommended way or can I do something more efficient? (Not for the specific function -this serves as an example-, but rather when I want to process a specific part of a list in general.)
Edit:
Sorry if I confused anyone, I am not interested in an efficient sum implementation, this served as an example to use slicing this way.
Yes, it creates a new list every time. If you can get away with using an iterable, you can use itertools.islice, or juggle iter(list) (if you only need to skip some items at the start). But this gets messy when you need to determine if the argument is empty or only has one element - you have to use try and catch StopIteration. Edit: You could also add an extra argument that determines where to start. Unlike #marcadian's version, you should make it a default argument to not burden the caller with that and avoid bugs from the wrong index being passed in from the outside.
It's often better to not get in that sort of situation - either write your code such that you can let for deal with iteration (read: don't use recursion like that). Alternatively, if the slice is reasonably small (possibly because the list as a whole is small), bite the bullet and slice anyway - it's easier, and while slicing is linear time, the constant factor is really tiny.
I can think of some options:
use builtin function sum for this particular case
If you really need recursion (for some reason), pass in the same list to the function call and also index of current element, so you don't need to slice the list (which creates new list)
option 2 works like this:
def f_sum(alist, idx=0):
if idx >= len(alist):
return 0
return alist[idx] + f_sum(alist, idx + 1)
f_sum([1, 2, 3, 4])
a = range(5)
f_sum(a)
This is another way if you must use recursion (tail-recursive). In many other languages this is more efficient than regular recursions in terms of space complexity. Unfortunately this isn't the case in python because it does not have a built-in support for optimizing tail calls. It's a good practice to take note of if you are learning recursion nonetheless.
def helper(l, s, i):
if len(l) == 0:
return 0
elif i < len(l) - 1:
return helper(l, s + l[i], i + 1)
else:
return s + l[i]
def listSum(l):
return helper(l, 0, 0)

How to reset a variable assigned to function in Python 2.73?

so basically a guy helped me improve my code. The problem is, it's still dead disappointing and does not work. What I wanna do, is reset the lenRecur.number so I could use the function again, using other strings and getting correct answers (not too big answers)
I guess, the problem is with hasattr. But I can't remove it, because if I do, my string length calculator won't work.
Anyway, even if I add lenRecur.number = 0 after the function, it still doesn't work.
It's like impossible, because when the function hits "return", it's done, period. If I reset it before "return", it will return 0, not correct answer so yeah I'm in deep trouble here.
def lenRecur(aStr):
if not hasattr(lenRecur, 'number'):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return lenRecur(aStr[:-1])
P.s. the goal of my program(?) / script(?) is to measure the length of input string, without using input() method. As trying to re-create the length() method, with using more primitive means.
The script will have to have many different inputs, so it shall reset.
If you just want a recursive strength-length function, that's easy:
def len_recur(a_str):
if not a_str:
return 0
else:
return 1 + len_recur(a_str[1:])
Of course that's not tail-recursive, but then Python doesn't optimize tail recursion anyway, so it doesn't matter.
And if you want it to be tail recursive just for the hell of it—or because you've read Paul Butler's trick for Tail Recursion in Python and want to try it out—you still don't want to do that by storing the accumulator as an attribute of the function. Just use the usual trick of defining a local function (or using a mutable default parameter, if you prefer):
def len_tail_recur(a_str):
def tail(a_str, acc):
if not a_str:
return acc
else:
return tail(a_str[1:], acc+1)
return tail(a_str, 0)
If you want to convert this to a real tail-recursive function so it doesn't bomb on lists of 1001 elements, and don't understand the Paul Butler link above, see my answer to Get length of list in Python using recursion, which solves exactly this problem. (Another answer to that question also shows how to solve the problem with log N recursive calls instead of N, which is a different way of getting around the problem, unless you have impossibly long lists.)
All that being said, even though your implementation is the wrong way to do it, it actually works just fine. (So far, I've been PEP8-ifying your code to look more like idiomatic Python; from here on I'm just going to copy-paste as-is, but your real code should look like the above.)
def lenRecur(aStr):
if not hasattr(lenRecur, 'number'):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return lenRecur(aStr[:-1])
print lenRecur('abc')
lenRecur.number = 0
print lenRecur('abcd')
This prints 3, then 4. Of course you have to set lenRecur.number from outside the function, because inside the function you still need the value. But you can solve that with the same kind of wrapper:
def lenRecur(aStr):
lenRecur.number = 0
'''
aStr: a string
returns: int, the length of aStr
'''
def recur(aStr):
if aStr == '':
return lenRecur.number
else:
lenRecur.number += 1
return recur(aStr[:-1])
return recur(aStr)
You don't have to use a state variable inside the function. If you want to make a recursive length calculator, then just do
def lenRecur (aStr):
if (aStr == ""):
return 0
else
return lenRecur (aStr [:-1]) + 1
Also note that this style has no error checking etc, but for the purposes of learning about recursion, it works fine.
If you're trying to understand recursion by implementing the length function using recursion then you can use something like this:
#!python
def lenRecur(something, curlen=0):
if something:
return lenRecur(something[1:], curlen+1)
else:
return curlen
... I won't claim that this is particularly good code. But it should work with any sort of sequence (string, list, tuple) ... anything for which the [1:] slice operation will work so long as it doesn't exceed the maximum recursion limit in your running Python instance.
In your example you're trying to implement a similar concept by using hasattr to "monkey patch" your function's object with a "number" attribute. In my example I'm using a default parameter as a way of passing the variable down into the recursive calls.
So in the initial call curlen is zero (calling this with the "optional" extra argument would give bogus results). From that call the function calls itself with a slice of the original sequence (string) that lops off the head (making it one shorter) and with the optional (curlen) argument incremented. At the end the string/sequence is of zero length, the zero is returned up through each of the previous (recursive) calls.
It's a lame way to accomplish this, and it could be a starting point for a discussion on tail recursion elimination (Google for it). But it will work without monkey patching your function/object.

Failing to understand recursion

New to Python and trying to understand recursion. I'm trying to make a program that prints out the number of times string 'key' is found in string 'target' using a recursive function, as in Problem 1 of the MIT intro course problem set. I'm having a problem trying to figure out how the function will run. I've read the documentation and some tutorials on it, but does anyone have any tips on how to better comprehend recursion to help me fix this code?
from string import *
def countR(target,key):
numb = 0
if target.find(key) == -1:
print numb
else:
numb +=1
return countR(target[find(target,key):],key)
countR('ajdkhkfjsfkajslfajlfjsaiflaskfal','a')
By recursion you want to split the problem into smaller sub-problems that you can solve independently and then combine their solution together to get the final solution.
In your case you can split the task in two parts: Checking where (if) first occurence of key exists and then counting recursively for the rest.
Is there a key in there:
- No: Return 0.
- Yes: Remove key and say that the number of keys is 1 + number of key in the rest
In Code:
def countR(target,key):
if target.find(key) == -1:
return 0
else:
return 1+ countR(target[target.find(key)+len(key):],key)
Edit:
The following code then prints the desired result:
print(countR('ajdkhkfjsfkajslfajlfjsaiflaskfal','a'))
This is not how recursion works. numb is useless - every time you enter the recursion, numb is created again as 0, so it can only be 0 or 1 - never the actual result you seek.
Recursion works by finding the answer the a smaller problem, and using it to solve the big problem. In this case, you need to find the number of appearances of the key in a string that does not contain the first appearance, and add 1 to it.
Also, you need to actually advance the slice so the string you just found won't appear again.
from string import *
def countR(target,key):
if target.find(key) == -1:
return 0
else:
return 1+countR(target[target.find(key)+len(key):],key)
print(countR('ajdkhkfjsfkajslfajlfjsaiflaskfal','a'))
Most recursive functions that I've seen make a point of returning an interesting value upon which higher frames build. Your function doesn't do that, which is probably why it's confusing you. Here's a recursive function that gives you the factorial of an integer:
def factorial(n):
"""return the factorial of any positive integer n"""
if n > 1:
return n * factorial(n - 1)
else:
return 1 # Cheating a little bit by ignoring illegal values of n
The above function demonstrates what I'd call the "normal" kind of recursion – the value returned by inner frames is operated upon by outer frames.
Your function is a little unusual in that it:
Doesn't always return a value.
Outer frames don't do anything with the returned value of inner frames.
Let's see if we can refactor it to follow a more conventional recursion pattern. (Written as spoiler syntax so you can see if you can get it on your own, first):
def countR(target,key):
idx = target.find(key)`
if idx > -1:
return 1 + countR(target[idx + 1:], key)
else:
return 0
Here, countR adds 1 each time it finds a target, and then recurs upon the remainder of the string. If it doesn't find a match it still returns a value, but it does two critical things:
When added to outer frames, doesn't change the value.
Doesn't recur any further.
(OK, so the critical things are things it doesn't do. You get the picture.)
Meta/Edit: Despite this meta article it's apparently not possible to actually properly format code in spoiler text. So I'll leave it unformatted until that feature is fixed, or forever, whichever comes first.
If key is not found in target, print numb, else create a new string that starts after the the found occurrence (so cut away the beginning) and continue the search from there.

Categories