I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)
Related
"Given a string of both letters and special characters/numbers, use recursion to concatenate the letters into a single string and return it."
My code is below, I'm still learning recursion and am stuck in trying to trace it. I tried a bunch of different lines in this code but idk how to fix what I do have so far:
def decoder(encryptedStr):
if len(encryptedStr) != 0:
if encryptedStr[0].isalpha() == True:
decoded = encryptedStr[0]
decoded.join(decoder(encryptedStr[1:]))
print(decoded)
else:
decoder(encryptedStr[1:])
I haven't had it return anything yet because I'm struggling with the part where I have to join the new letters to the output string. Instead of .join I also tried:
decoded += decoder(encryptedStr[1:])
but it doesn't work bc Nonetype??
Your main issue is that you didnt return, but there are some issues with your approach that make this more complex than need-be.
Think tail-first when doing recursion- What is your end condition, and how do you decide to continue. Typically with this kind of method you do something like, 1) process a single value in the list, 2) let the recursive method handle the rest of it, 3) combine the results.
An easy indicator of the tail-first return here would be to return nothing if the string is empty:
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
...
Now in each run we want to operate on one letter and pass the rest to a recursive call. Ignoring the special character requirement, you'd get something like this:
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
first = encryptedStr[0]
rest = decoder(encryptedStr[1:])
return first + rest
Now we can handle the special case where we want to omit letters.
def decoder(encryptedStr):
if len(encryptedStr) == 0:
return ""
first = encryptedStr[0]
rest = decoder(encryptedStr[1:])
if not first.isalpha():
first = ""
return first + rest
And that's all there is to it!
Bonus for some refactoring:
def clean(letter):
return letter if letter.isalpha() else ""
def decoder(encrypted):
if len(encrypted) == 0:
return ""
return clean(encrypted[0]) + decoder(encrypted[1:])
There's a bunch of problems here:
I don't think join does what you want it to do in that case. If you want to add some strings together simply use +=. join would insert decoded character between whatever decoder(encryptedStr[1:]) returns.
You don't have a case for len(encryptedStr) == 0, so it returns default value of None. That's why you cannot append it's results to decoded.
Return immediately if there is nothing to do. Otherwise take the first letter if it matches the condition and add the result of the recursive call (where the parameter is the current encrypted string without the first character).
def decoder(encrypted):
if not encrypted:
return ''
decrypted = encrypted[0] if encrypted[0].isalpha() else ''
return decrypted + decoder(encrypted[1:])
print(decoder('Abc123rtZ5'))
The result is AbcrtZ.
Bonus info (as #JonSG mentioned in the comments):
Run this with print(decoder('A' * 1000)) and you'll see why recursion is a bad idea for this task.
Every recursive function must have a base condition that stops the recursion or else the function calls itself infinitely.
To recursively concatenate ONLY the letters of an input string into a single output string:
some_string = "I2L4o2v3e+P;y|t!o#n"
def decoder(encryptedStr, decoded = ""):
if len(encryptedStr) == 0: # Base condition
return decoded
if encryptedStr[0].isalpha():
decoded += encryptedStr[0]
return decoder(encryptedStr[1:], decoded)
# If the char in the index [0] is not a letter it will be sliced out.
return decoder(encryptedStr[1:], decoded)
print(decoder(some_string))
Output:
ILovePython
I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)
I'm trying to split and organize a string in a single function, my goal is to seperate lowercase and uppercase characters and then return a new string essentially like so:
"lowercasestring" + " " + "uppercasestring".
Importantly all characters must return in the order they were recieved but split up.
My problem is that i have to do this recursively in a single function(for educational purposes) and i struggle to understand how this is doable without an external function calling the recursive and then modifying the string.
def split_rec(string):
if string == '':
return "-" #used to seperate late
elif str.islower(string[0]) or string[0] == "_" or string[0] == ".": #case1
return string[0] + split_rec(string[1:])
elif str.isupper(string[0]) or string[0] == " " or string[0] == "|": #case2
return split_rec(string[1:]) + string[0]
else: #discard other
return split_rec(string[1:])
def call_split_rec(string):
##Essentially i want to integrate the functionality of this whole function into the recursion
mystring = split_rec(string)
left, right = mystring.split("-")
switch_right = right[::1]
print(left + " " + switchright)
The recursion alone would return:
"lowerUPPERcaseCASE" -> "lowercase" + "ESACREPPU"
My best attempt at solving this in a single function was to make case2:
elif str.isupper(string[-1]) or string[-1] == " " or string[-1] == "|": #case2
return split_rec(string[:-1]) + string[-1]
So that the uppercase letters would be added with last letter first, in order to correctly print the string. The issue here is that i obviously just get stuck when the first character is uppercase and the last one is lowercase.
I've spent alot of time trying to figure out a good solution to this, but im unable and there's no help for me to be found. I hope the question is not too stupid - if so feel free to remove it. Thanks!
I wouldn't do this recursively, but I guess you don't have a choice here. ;)
The simple way to do this in one function is to use a couple of extra arguments to act as temporary storage for the lower and upper case chars.
def split_rec(s, lo='', up=''):
''' Recursively split s into lower and upper case parts '''
# Handle the base case: s is the empty string
if not s:
return lo + ' ' + up
#Otherwise, append the leading char of s
# to the appropriate destination...
c = s[0]
if c.islower():
lo += c
else:
up += c
# ... and recurse
return split_rec(s[1:], lo, up)
# Test
print(split_rec("lowerUPPERcaseCASE"))
output
lowercase UPPERCASE
I have a couple of comments about your code.
It's not a great idea to use string as a variable name, since that's the name of a standard module. It won't hurt anything, unless you want to import that module, but it's still potentially confusing to people reading your code. The string module doesn't get a lot of use these days, but in the early versions of Python the standard string functions lived there. But then the str type inherited those functions as methods, making the old string functions obsolete.
And on that note, you generally should call those str methods as methods, rather than as functions. So don't do:
str.islower(s[0])
instead, do
s[0].islower()
Another take with recursive helper functions
def f(s):
def lower(s):
if not s:
return ''
c = s[0] if s[0].islower() else ''
return c + lower(s[1:])
def upper(s):
if not s:
return ''
c = s[0] if s[0].isupper() else ''
return c + upper(s[1:])
return lower(s) + ' ' + upper(s)
The easiest way would be to use sorted with a custom key:
>>> ''.join(sorted("lowerUPPERcaseCASE" + " ", key=str.isupper))
'lowercase UPPERCASE'
There's really no reason to use any recursive function here. If it's for educational purpose, you could try to find a problem for which it's actually a good idea to write a recursive function (fibonacci, tree parsing, merge sort, ...).
As mentioned by #PM2Ring in the comments, this sort works fine here because Python sorted is stable: when sorting by case, letters with the same case stay at the same place relative to one another.
Here is a way to do it with only the string as parameter:
def split_rec(s):
if not '|' in s:
s = s + '|'
if s.startswith('|'):
return s.replace('|', ' ')
elif s[0].islower():
return s[0] + split_rec(s[1:])
elif s[0].isupper():
# we move the uppercase first letter to the end
s = s[1:] + s[0]
return split_rec(s)
else:
return split_rec(s[1:])
split_rec('aAbBCD')
# 'ab ABCD'
The idea is:
We add a marker at the end (I chose |)
If the first char is lowercase, we return it + the organized rest
If it is uppercase, we move it to the end, and reorganize the whole string
We stop once we reach the marker: the current string is the marker followed by the organized uppercase letters. We replace the marker by a space and return it.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need help on how to define and test three functions on strings. Following these guidelines. This is review for my exam on Wednesday and would really like to have the correct solutions because mine are all coming back with the syntax errors.
I need to come up with the code for all three examples following the requirements listed below.
Without using any string methods only len function and the string operations +, *, indexing slicing, and == for comparing strings or characters.
In the repl function, use the accumulator pattern to build up the new string.
Examples
The ends function takes a string as argument; if the string has two or more characters, it returns a string consisting of the first and last character of the given string; otherwise, it returns the given string.
>>> ends("ab")
'ab'
>>> ends("abc")
'ac'
>>> ends("a long sentence")
'ae'
>>> ends("")
''
>>> ends("*")
'*'
The butends function takes a string argument; if the string has two or more characters, it returns a string consisting of all but the first and last character of the string; otherwise, it returns the given string.
>>> butends("abcde")
'bcd'
>>> butends("abc")
'b'
>>> butends("a long sentence")
' long sentenc'
>>> butends("")
''
>>> butends("a")
'a'
The repl function takes three arguments:
old is a single character;
new is a string of 0 or more characters;
s is any string.
I know that it returns a new string formed by replacing every occurrence of old in s with new.
>>> repl('a', 'A', 'fast faces react snappily')
'fAst fAces reAct snAppily'
>>> repl('*', '+++', 'a*b = c*d')
'a+++b = c+++d'
>>> repl(' ', '\n', 'Practice every day.')
'Practice\nevery\nday.'
>>> print(repl(' ', '\n', 'Practice every day.'))
Practice
every
day.
>>> repl(",", ":", "a,b,cde,fghi")
'a:b:cde:fghi'
what I have so far for part 3 is:
def repl(old, new, s):
newStr = ""
for ch in s:
if ch != old:
newStr = newStr + ch
else:
newStr = newStr + new
return newStr
The code listed above does not replace the correct characters I'm not sure where I went wrong.
Here is one possible solution for the three functions. Note that, as I mentioned above in the comments, you would learn a lot more if you would show us what you have tried and what the problems with it are.
def ends (s):
if len(s) > 2:
return s[0] + s[-1]
else:
return s
def butends (s):
if len(s) > 2:
return s[1:-1]
else:
return s
def repl (find, replacement, s):
newString = ''
for c in s:
if c == find:
newString += replacement
else:
newString += c
return newString
If you can use len() and slicing, it would be best to simply grab
the first and last characters and return that.
def ends(input):
if len(input) < 2:
return input
else:
return input[0] + input[-1]
You can pretty much do the same thing here:
def butends(input):
if len(input) < 2:
return input
else:
return input[1:-1]
For this one, there's a function in Python called replace, but I'm
not sure you can use it.
def repl(old, new, input):
return input.replace(old, new)
If you can't, then simply loop through the input and replace each character whenever it matches with new.
I like programming assignments:
def ends (s): return s [0] + s [-1] if len (s) > 1 else s
def butends (s): return s [1:-1] if len (s) > 1 else s
def repl (a, b, c, acc = ''): return acc if not c else repl (a, b, c [1:], acc + (b if c [0] == a else c [0] ) )
Not sure what an "accumulator pattern" is, so for the replacement I used a recursive function with an accumulator as known from functional programming.
1)
def ends(s):
if len(s)<=2: return s
return s[0]+s[-1]
2)
def butends(s):
if len(s)<=2: return s
return s[1:-1]
3)
def repl(s,old,new):
return s.replace(old,new)
I understand that recursion is when a function calls itself, however I can't figure out how exactly to get my function to call it self to get the desired results. I need to simply count the vowels in the string given to the function.
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowelcount = 0
vowels = "aEiou".lower()
if s[0] in vowels:
vowelcount += 1
else:
???
I came up with this in the end, thanks to some insight from here.
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowels = "aeiouAEIOU"
if s == "":
return 0
elif s[0] in vowels:
return 1 + recVowelCount(s[1:])
else:
return 0 + recVowelCount(s[1:])
Try this, it's a simple solution:
def recVowelCount(s):
if not s:
return 0
return (1 if s[0] in 'aeiouAEIOU' else 0) + recVowelCount(s[1:])
It takes into account the case when the vowels are in either uppercase or lowercase. It might not be the most efficient way to traverse recursively a string (because each recursive call creates a new sliced string) but it's easy to understand:
Base case: if the string is empty, then it has zero vowels.
Recursive step: if the first character is a vowel add 1 to the solution, otherwise add 0. Either way, advance the recursion by removing the first character and continue traversing the rest of the string.
The second step will eventually reduce the string to zero length, therefore ending the recursion. Alternatively, the same procedure can be implemented using tail recursion - not that it makes any difference regarding performance, given that CPython doesn't implement tail recursion elimination.
def recVowelCount(s):
def loop(s, acc):
if not s:
return acc
return loop(s[1:], (1 if s[0] in 'aeiouAEIOU' else 0) + acc)
loop(s, 0)
Just for fun, if we remove the restriction that the solution has to be recursive, this is how I'd solve it:
def iterVowelCount(s):
vowels = frozenset('aeiouAEIOU')
return sum(1 for c in s if c in vowels)
Anyway this works:
recVowelCount('murcielago')
> 5
iterVowelCount('murcielago')
> 5
Your function probably needs to look generally like this:
if the string is empty, return 0.
if the string isn't empty and the first character is a vowel, return 1 + the result of a recursive call on the rest of the string
if the string isn't empty and the first character is not a vowel, return the result of a recursive call on the rest of the string.
Use slice to remove 1st character and test the others. You don't need an else block because you need to call the function for every case. If you put it in else block, then it will not be called, when your last character is vowel: -
### Improved Code
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowel_count = 0
# You should also declare your `vowels` string as class variable
vowels = "aEiou".lower()
if not s:
return 0
if s[0] in vowels:
return 1 + recVowelCount(s[1:])
return recVowelCount(s[1:])
# Invoke the function
print recVowelCount("rohit") # Prints 2
This will call your recursive function with new string with 1st character sliced.
this is the straightforward approach:
VOWELS = 'aeiouAEIOU'
def count_vowels(s):
if not s:
return 0
elif s[0] in VOWELS:
return 1 + count_vowels(s[1:])
else:
return 0 + count_vowels(s[1:])
here is the same with less code:
def count_vowels_short(s):
if not s:
return 0
return int(s[0] in VOWELS) + count_vowels_short(s[1:])
here is another one:
def count_vowels_tailrecursion(s, count=0):
return count if not s else count_vowels_tailrecursion(s[1:], count + int(s[0] in VOWELS))
Unfortunately, this will fail for long strings.
>>> medium_sized_string = str(range(1000))
>>> count_vowels(medium_sized_string)
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
if this is something of interest, look at this blog article.
Here's a functional programming approach for you to study:
map_ = lambda func, lst: [func(lst[0])] + map_(func, lst[1:]) if lst else []
reduce_ = lambda func, lst, init: reduce_(func, lst[1:], func(init, lst[0])) if lst else init
add = lambda x, y: int(x) + int(y)
is_vowel = lambda a: a in 'aeiou'
s = 'How razorback-jumping frogs can level six piqued gymnasts!'
num_vowels = reduce_(add, map_(is_vowel, s), 0)
The idea is to divide the problem into two steps, where the first ("map") converts the data into another form (a letter -> 0/1) and the second ("reduce") collects converted items into one single value (the sum of 1's).
References:
http://en.wikipedia.org/wiki/Map_(higher-order_function)
http://en.wikipedia.org/wiki/Reduce_(higher-order_function)
http://en.wikipedia.org/wiki/MapReduce
Another, more advanced solution is to convert the problem into tail recursive and use a trampoline to eliminate the recursive call:
def count_vowels(s):
f = lambda s, n: lambda: f(s[1:], n + (s[0] in 'aeiou')) if s else n
t = f(s, 0)
while callable(t): t = t()
return t
Note that unlike naive solutions this one can work with very long strings without causing "recursion depth exceeded" errors.