Keeping count in recursive function - python

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)

Related

recursive way to find if a string is valid

hey so i am trying to write a code that that tells me if a string is valid or not .
a valid string is a string that contains an equal number of "(" and ")" and each "(" must be closed by a ")"
for example
'((()()))' this is a valid string . this isn't ')( '
this is what i wrote so far :
def is_valid_paren(s, cnt=0):
if s == "":
return True
if "(" in s:
cnt += 1
if ")" in s:
cnt -= 1
return is_valid_paren(s[1:])
it doesn't give the correct output for
"(.(a)"
yet for
"p(()r((0)))"
it does
why does it sometimes work ?
oh one more thing this is to be solved only by recursion ( without the use of loops anywhere )
While I don't understand why you want to solve this problem with recursion (it's very unnatural in this case), here is a recursive solution:
def is_valid(s):
def _is_valid(s, idx):
if idx == len(s): return 0
if s[idx] == '(': return _is_valid(s, idx + 1) + 1
if s[idx] == ')': return _is_valid(s, idx + 1) - 1
return _is_valid(s, idx + 1)
return _is_valid(s, 0) == 0
You can pass down a count of pending apertures (i.e. number of unclosed parentheses) and check if the count goes below 0 (too many closures) as you go and if it ends back at zero at the end:
def validPar(s,count=0):
if count<0 : return False # too many closing
if not s: return count == 0 # must balance pending apertures
return validPar(s[1:],count+(-1,1)[s[0]=="("]) # pass down count +/- 1
print(validPar('((()()))')) # True
Recursion
Iteration is likely to be the best method of solving this, but recursion also works. To attack this problem recursively, we need a system of checking the count of each and if at any stage that count falls below zero, the parentheses will be invalid because there are more closing brackets than opening ones. This is where the tough section comes into play: we need some method of not only returning the count, but whether or not the past ones were valid, so we will have to return and save using variables like return count, valid and count, valid = is_valid_parentheses(s[1:]). The next thing we need is some over-arching function which looks at the end results and says: "is the count equal to zero, and were the parentheses valid to begin with". From there, it needs to return the result.

Variable location in recursion

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)

Recursive function in python does not call itself out

The problem is formulated as follows:
Write a recursive function that, given a string, checks if the string
is formed by two halves equal to each other (i.e. s = s1 + s2, with s1
= s2), imposing the constraint that the equality operator == can only be applied to strings of length ≤1. If the length of the string is
odd, return an error.
I wrote this code in Python 2.7 that is correct (it gives me the right answer every time) but does not enter that recursive loop at all. So can I omit that call here?
def recursiveHalfString(s):
##param s: string
##return bool
if (len(s))%2==0: #verify if the rest of the division by 2 = 0 (even number)
if len(s)<=1: # case in which I can use the == operator
if s[0]==s[1]:
return True
else:
return False
if len(s)>1:
if s[0:len(s)/2] != s[len(s)/2:len(s)]: # here I used != instead of ==
if s!=0:
return False
else:
return recursiveHalfString(s[0:(len(s)/2)-1]+s[(len(s)/2)+1:len(s)]) # broken call
return True
else:
return "Error: odd string"
The expected results are True if the string is like "abbaabba"
or False when it's like anything else not similat to the pattern ("wordword")
This is a much simplified recursive version that actually uses the single char comparison to reduce the problem size:
def rhs(s):
half, rest = divmod(len(s), 2)
if rest: # odd length
raise ValueError # return 'error'
if half == 0: # simplest base case: empty string
return True
return s[0] == s[half] and rhs(s[1:half] + s[half+1:])
It has to be said though that, algorithmically, this problem does not lend itself well to a recursive approach, given the constraints.
Here is another recursive solution. A good rule of thumb when taking a recursive approach is to first think about your base case.
def recursiveHalfString(s):
# base case, if string is empty
if s == '':
return True
if (len(s))%2==0:
if s[0] != s[(len(s)/2)]:
return False
else:
left = s[1:len(s)/2] # the left half of the string without first char
right = s[(len(s)/2)+1: len(s)] # the right half without first char
return recursiveHalfString(left + right)
else:
return "Error: odd string"
print(recursiveHalfString('abbaabba')) # True
print(recursiveHalfString('fail')) # False
print(recursiveHalfString('oddstring')) # Error: odd string
This function will split the string into two halves, compare the first characters and recursively call itself with the two halves concatenated together without the leading characters.
However like stated in another answer, recursion is not necessarily an efficient solution in this case. This approach creates a lot of new strings and is in no way an optimal way to do this. It is for demonstration purposes only.
Another recursive solution that doesn't involve creating a bunch of new strings might look like:
def recursiveHalfString(s, offset=0):
half, odd = divmod(len(s), 2)
assert(not odd)
if not s or offset > half:
return True
if s[offset] != s[half + offset]:
return False
return recursiveHalfString(s, offset + 1)
However, as #schwobaseggl suggested, a recursive approach here is a bit clunkier than a simple iterative approach:
def recursiveHalfString(s, offset=0):
half, odd = divmod(len(s), 2)
assert(not odd)
for offset in range(half):
if s[offset] != s[half + offset]:
return False
return True

Python recursion doesn't yield desired result

I am trying to find the length of the string with out using the inbuilt len() function. Here's my python code:
increment = -1
def lenRecur(aStr):
'''
aStr: a string
returns: int, the length of aStr
'''
global increment
if aStr == '':
return increment
else:
increment += 1
return lenRecur (aStr[increment:])
print lenRecur ("abcdefq")
The result I am expecting is 7 but what I got was 4.What I realized was when the increment became 2, the value pass to the lenRecur (aStr[increment:]) was "defq". Which means aStr[2:] is evaluated as "defq" instead of "cdefq".
Why this is happening?
Your function should not depend on external variables.
def lenRecur(aStr):
'''
aStr: a string
returns: int, the length of aStr
'''
if aStr == '':
return 0
else:
return 1 + lenRecur(aStr[1:])
print lenRecur("abcdefq")
A common idiom is to use a default argument:
>>> def l(s, c=0): return l(s[1:], c+1) if s else c
This kind of solution works with anything that can be sliced
>>> l('pip')
3
>>> l([1,2,3])
3
>>> l('')
0
>>> l([])
0
>>>
As an other option, you could write this:
def lenRecur(aStr):
return _lenRecur(aStr, 0)
def _lenRecur(aStr, acc):
if not aStr:
return acc
return _lenRecur(aStr[1:], acc+1)
A noticed by #gboffi in his answer, it is commonly accepted in Python to use a default argument instead of using of an helper function:
def lenRecur(aStr, acc = 0):
if not aStr:
return acc
return lenRecur(aStr[1:], acc+1)
The choice of one form or the other will depend how much you want/don't want to allow the called to set the initial accumulator value to something else than 0.
Anyway, the interesting point here is in using an accumulator as the second parameter. That way, you have proper tail recursion. Unfortunately, this is not properly optimized by Python. But this is a good habit as many other languages have such optimization. And this will be a required skill if you switch someday to functional programing language.

First index appearance in a string recursive

Im trying to write a recursive function that gets as an input a string and a char. the function return the first index appearance of the char in the string. If the char doesnt appear it returns None.
I have a problem only with returning None. In my case when the char isnt in the string the function throws an error, any advice?
def char_first_index(s,c):
if len_rec(s)==0:
return None
if s[0]==c:
return 0
return 1+ char_first_index(s[1:],c)
You are creating a new slice at each iteration, and you have to add 1 for each recursion. Instead, recurse on the index:
def char_first_index(s, c, index = 0):
if len(s) == index:
return None
if s[index] == c:
return index
return char_first_index(s, c, index + 1)
If the character is not in the input, your function tries to perform 1+None, hence the error. Try this instead:
def char_first_index(s,c):
if len_rec(s)==0:
return None
if s[0]==c:
return 0
answer = char_first_index(s[1:],c)
if answer is not None:
return 1+answer
else:
return answer
Firstly I'm assuming len_rec is a recursive function that gets the length of the string; you haven't written it so I've just changed it to len() for testing.
Secondly, I'm not sure how this function is supposed to handle the character not being in the string, as that will mean trying to add None to a number.
Here is an amended function that still uses your count idea, but handles the case of a None being returned:
def char_first_index(s,c):
if len(s)==0:
return None
elif s[0]==c:
return 0
else:
count = char_first_index(s[1:], c)
if count != None:
return count + 1
else:
return None

Categories