Variable location in recursion - python

The problem is my code keeps reflecting a variable as zero and this is caused by the fact that the variable is assigned at the start of my function, so each time I call the function the value evaluates to zero. However I need this variable assignment for the code to work and placing it within the elif statements still evaluates to zero and placing the the variable outside the function causes the function not work.
The aim of the program is to count pairs of consecutive letters in a string using recursion with no for/while loops in the code.
def countpairs(s):
pairs=0
if len(s)<2:
return 0 #base case
elif s[0].lower() == s[1].lower(): #recursion
pairs=+1
return countpairs(s[1:])
else: #recursion
pairs=+0
return countpairs(s[1:])
print(countpairs('Hello Salaam'))
This code is supposed to evaluate to 2 because of "ll" and "aa".

You need to wrap your head a little around what the recursion will do: it will call the function recursively to count the pairs from that point on, then (it should) add the pair, if any, found by this instance.
So your function needs to do something with the result of the recursive call, not just return it unchanged. For example, instead of this
elif s[0].lower() == s[1].lower():
pairs = +1
return countpairs(s[1:])
you might write this:
elif s[0].lower() == s[1].lower():
return countpairs(s[1:]) + 1
Something along these lines. You'll need to do a bit more work to get it just right, but I hope you get the idea.

The problems is that the variable pairs resets every recursive call...
When using counting recursive algorithms you don't need a variable that counts, that's the beauty
Instead, try to think how to recursive call can help you count.
def countpairs(s):
if len(s)<2:
return 0
elif s[0].lower() == s[1].lower():
return countpairs(s[1:])+1
else:
return countpairs(s[1:])
print(countpairs('Hello Salaam'))
There you go, in the recursive call the "counter" gets bigger every time it should be, think of the counter as a part of the function stack (or something like that).

You need to fix the syntax: pairs=+1 should be pairs+=1, same for pairs=+0. And you can pass the total into the next level.
def countpairs(s, pairs=0):
if len(s)<2:
return pairs #base case
elif s[0].lower() == s[1].lower(): #recursion
pairs+=1
return countpairs(s[1:], pairs)
else: #recursion
pairs+=0
return countpairs(s[1:], pairs)
print(countpairs('Hello Salaam')) # 2

You can do it by creating a recursive nested function and defining pairs in the outer function. Here's what I mean (with fixes for other issues encountered):
def countpairs(s):
pairs = 0
def _countpairs(s):
nonlocal pairs # Since it's not local nor global.
if len(s) < 2: # base case
return pairs
elif s[0].lower() == s[1].lower():
pairs += 1
return _countpairs(s[1:]) # recursion
else:
return _countpairs(s[1:]) # recursion
return _countpairs(s)
print(countpairs('Hello Salaam')) # -> 2

The code will always evaluate to zero because the last recursion will always have the length of s being less than 2. Instead use the global keyword to be able to grab the value of pairs.
numberOfPairs = 0
pairsList = []
def countpairs(s):
global numberOfPairs
if len(s)<2:
print("doing nothing")
return 0 #base case
elif s[0].lower() == s[1].lower(): #recursion
numberOfPairs+=1
newString = f"{s[0]} is equal to {s[1]}"
print(newString)
pairsList.append(newString)
return countpairs(s[1:])
else:
print(f"nothing happened: {s[0]}") #recursion
return countpairs(s[1:])
print(f"\nThe returned value of countpairs is: {countpairs('Hello Salaam')}")
print(f"Number of pairs: {numberOfPairs}")
print(pairsList)

Related

Python fibonacci unexpecred indent

Im new to code and learning python . I got homework to make print Fibonacci
numbers for N = 11 and N = 200 using method called Memoization . I found solution but when im running the code i getting two things : 1 .
Traceback (most recent call last):
**File "python", line 7
if n== 1:
^**
**IndentationError: unexpected indent**
and second i got empty result sometime when im running. what is wrong which the code :
def fibonacci (n) :
# If we have cached the value, then return it
if n in fibonacci_cache:
return fibonacci_cache[n]
# Compute the Nth term
if n== 1:
value = 1
elif n == 2:
value = 1
elif n > 2:
value = fibonacci(n-1) + fibonacci(n-2)
# Cache the value and return it
fibonacci_cache[n] = value
return value
print(n, ":", fibonacchi(11))
See #Alexis Drakopoulos for a direct fix to your code. If you want to simplify implementing memoization you can use a decorator called lru_cache.
from functools import lru_cache
#lru_cache(maxsize=None)
def fibonacci(n):
if n<= 2:
return 1
return fibonacci(n-1)+fibonacci(n-2)
def fibonacci(n):
# If we have cached the value, then return it
if n in fibonacci_cache:
return fibonacci_cache[n]
# Compute the Nth term
if n == 1:
value = 1
elif n == 2:
value = 1
elif n > 2:
value = fibonacci(n-1) + fibonacci(n-2)
# Cache the value and return it
fibonacci_cache[n] = value
return value
print(n, ":", fibonacchi(11))
in Python indentation is everything, I am not sure if this is correct with the last lines with the cache.
I suggest using 4 spaces (using tabs) in order to be consistent.
Python looks at indentations to understand what you are trying to do.
Welcome to programming in Python and to StackOverflow :-)
There are three problems with your code:
1. The indentation: Python needs you to pay attention to the indentation, such that code at a particular level is indented the same amount.
For code that runs after something like an if statement, you need to put the next block of code indented. Then when you have the elif (which is at the same level as the if statement) you need to bring the indenting back out to match the level of the if.
You can indent with spaces or tabs, but you need to be consistent (ie stick to one)
It's possible that the editor you're using has messed up the intenting when you pasted the code in, and it's also possible that some of the indenting got messed up when you put it into StackOverflow too, but you need it to look like that below. In this case, each intent is two spaces (so indenting is first no spaces, then two spaces, then four spaces etc.)
2. Typos: The final statement has a typo (so you're not actually calling the function you define!)
3. Fibbonacci_cache: it isn't defined, so that's been added at the top
Hope that helps - good luck with the rest of your journey into programming... it will need perseverance but you'll get the hang in time I'm sure!
fibonacci_cache = {}
def fibonacci (n) :
# If we have cached the value, then return it
if n in fibonacci_cache:
return fibonacci_cache[n]
# Compute the Nth term
if n== 1:
value = 1
elif n == 2:
value = 1
elif n > 2:
value = fibonacci(n-1) + fibonacci(n-2)
# Cache the value and return it
fibonacci_cache[n] = value
return value
print("n:", fibonacci(11))

Recursion program flow

I have some textbook code that calls itself recursively. I don't understand the program flow. Here is the code:
def Recur_Factorial_Data(DataArray):
numbers = list(DataArray)
num_counter = 0
list_of_results = []
for num_float in numbers:
n = int(num_float)
1. result = Recur_Factorial(n)
list_of_results.append(result)
def Recur_Factorial(num):
if num == 1:
2. return num
else:
result = num*Recur_Factorial(num-1)
3. return result
if num < 0:
return -1
elif num == 0:
return 0
else:
return 0
In Recur_Factorial_Data, I loop through the data elements and call Recur_Factorial, which returns its value back to the calling function (Recur_Factorial_Data). I would expect that the lines marked 2 ("return num") and 3 ("return result") would always return a value back to the calling function, but that's not the case. For example, where the initial value (from the array DataArray) is 11, the function repeatedly calls itself until num is 1; at that point, the program falls to the line marked 2, but it does not loop back to the line marked 1. Instead, it falls through to the next line. The same happened on the line marked 3 -- I would expect it to return the result back to the calling function, but it does that in some cases and not in others.
I hope this is enough description to understand my question -- I just don't know why each return does not loop back to return the result to the calling function.
EDIT: The question at Understanding how recursive functions work is very helpful, and I recommend it to anyone interested in recursion. My question here is a bit different -- I asked it in the context of the program flow of the Python code where the recursive function is called.
If it call itself recursively 10 times, it will be at the 10th level of recursion and should go back 10 times at the point where there was a recursive call with an intermediate result and only then exit from the recursive function to the place where it was called. Learn more about recursion
Also try to rearrange instructions in Recur_Factorial function in this way:
def Recur_Factorial(num):
if num < 0:
return -1
elif num == 0:
return 0
elif num == 1:
return num
else:
return num * Recur_Factorial(num-1)

function is not getting called in python

Hi i am new to Python programming . I am writing a python code which uses stack.
There are two function in my python code isdesc() and poisonplant()
When i have called the function poisonplant in there is another function but that function is not get called
Code is indented properly
Here is my code:
def isdesc(arr):
if len(arr) == 0:
return False
for i in range(0,len(arr)):
if arr[i+1] < arr[i]:
return True
else:
return False
def poisonplant(expr):
count=0
pdb.set_trace()
while not isdesc(expr):
s.push(expr[0])
for i in range(0,len(expr)):
if expr[i+1] < expr[i]:
s.push(expr[i+1])
count+=1
del expr[:]
for each_item in s.items:
a=s.pop()
expr.insert(0,a)
return count
input1=[6,5,8,4,7,10,9]
print(poisonplant(input1))
I have only called poisonplant and i think isdec is automatically get called inside poison function.
Can someone help me in this why isdesc is not get called here
isdesc is returning too soon, without looking at all the adjacent elements. It should read
def isdesc(arr):
for i in range(len(arr)-1):
if arr[i] < arr[i+1]:
return False
return True
(I've slightly modified the definition to treat empty lists as descending. If you treat an empty list as non-descending, you'll enter the loop, where you are assuming the list is not empty.)
Your main problem is that you're using return as if it will return each iteration, but you're actually just going to return on the very first one. You could instead return False if any of the sorts are wrong, but a better way to check if the lists are sorting in descending order is to check if the list is equal to a reverse sort of itself.
def isdesc(arr):
if len(arr) == 0:
return False
return arr == sorted(arr, reverse=True)

Keeping count in a recursive function? [Jython]

I'm trying to count the number of times the letter 'x' appears in a string using a recursive function. My function currently does this, however I wish to have only one parameter (the string). I am having difficulty creating a counter that is not overwritten when the function is iterated in the return line.
To illustrate what I mean:
def xCounter(string): <br>
**counter = 0** (This resets the counter to 0 with each iteration) <br>
if len(string) == 0:
return counter
elif string[0] == 'x':
counter = counter + 1
elif string[0] != 'x':
return xCounter(string[1:],counter)
return xCounter(string[1:],counter)
xCounter("gfljkgfxlkjsfxxljsx")
0
The only way I have it working so far is defining counter as a parameter:
def xCounter(string, counter): <br>
if len(string) == 0: <br>
return counter <br>
elif string[0] == 'x': <br>
counter = counter + 1 <br>
elif string[0] != 'x': <br>
return xCounter(string[1:],counter) <br>
return xCounter(string[1:],counter) <br>
xCounter("werixiuewrxiewx",0)
3
Can anyone please provide me some insight on how to keep count in this function without overwriting the count or defining count as a parameter?
I assume you're doing this for exercise in recursion, not for actual solution, right? The right way to do it in python would be
count = "gfljkgfxlkjsfxxljsx".count('x')
print count
However, you are correct in that your code resets the counter with each iteration, it's supposed to.
There are ways (like global variables) to keep track of the counter without using it as a parameter, but that's BAD BAD BAD. The extra parameter is the way to do it right.
Try this:
def xCounter(string):
if len(string) == 0: return 0
return (string[0]=='x') + xCounter(string[1:])
... if you reach the end of a string, you return 0, otherwise you return 0 or 1 (depending whether string[0] is 'x') plus the function value for the rest of the string... you sum all these numbers in the end and get your answer!
Of course, that's not how it's done, but it's a good practice in recursive functions.
You can even do it shorter, like a lambda:
f=lambda s:len(s) and (s[0]=='x') + f(s[1:]) or 0
Return the recursive call, plus 1 if the character is present. The counter in this case would either be a 0 or a 1; instead of a running total.
You could set a Boolean variable to whether or not the current character is an 'x', then you can change the last line to something like:
return xCounter[1:] +
(if isX then 0 else 1)
The end result will be a chain of addition expressions, where the end result (an addition "chain" of 1s and 0s) is returned.
You could also wrap the "workhorse" function in a wrapper that automatically passes in the initial parameter so the caller doesn't have to:
def xCounter(str):
return xCounterHelper(str, 0)
where xCounterHelper is your original function.
In complicated recursive functions that require more parameters, the second option is very handy. Hide the ugly multi-parameter version as a private function (if it's a class method), and expose the cleaner 1 parameter version (note that Python doesn't have private functions. This is more for languages that do).

Keeping count in recursive function

I'm trying to figure out how to write a recursive function (with only one parameter) that returns the number of times the substring “ou” appears in the string. Where I'm confused at is that I'm not allowed to use any built-in string functions other than len, or the string operators [] and [:] for indexing and splicing. So I can't use the find built-in find function
I remember seeing something like this, but it uses two parameters and it also uses the find() method
def count_it(target, key):
index = target.find(key)
if index >= 0:
return 1 + count_it(target[index+len(key):], key)
else:
return 0
Very inefficient, but should work:
def count_it(target):
if len(target) < 2:
return 0
else:
return (target[:2] == 'ou') + count_it(target[1:])
See it working online: ideone
It's basically the same idea as the code you posted, except that it moves only one character at a time through the string instead of using find to jump ahead to the next match.
Try this, it works for the general case (any value of key, not only 'ou'):
def count_it(target, key):
if len(target) < len(key):
return 0
found = True
for i in xrange(len(key)):
if target[i] != key[i]:
found = False
break
if found:
return 1 + count_it(target[len(key):], key)
else:
return count_it(target[1:], key)

Categories