python build a list recursively - python

Let's say I have a string
S = "qwertyu"
And I want to build a list using recursion so the list looks like
L = [u, y, t, r, e, w, q]
I tried to write code like this:
def rec (S):
if len(S) > 0:
return [S[-1]].append(rec(S[0:-1]))
Ideally I want to append the last element of a shrinking string until it reaches 0
but all I got as an output is None
I know I'm not doing it right, and I have absolutely no idea what to return when the length of S reaches 0, please show me how I can make this work
(sorry the answer has to use recursion, otherwise it won't bother me)
Thank you very much!!!

There are many simpler ways than using recursion, but here's one recursive way to do it:
def rec (S):
if not S:
return []
else:
temp = list(S[-1])
temp.extend(rec(S[:-1]))
return temp
EDIT:
Notice that the base case ensures that function also works with an empty string. I had to use temp, because you cannot return list(S[-1]).extend(rec(S[:-1])) due to it being a NoneType (it's a method call rather than an object). For the same reason you cannot assign to a variable (hence the two separate lines with temp). A workaround would be to use + to concatenate the two lists, like suggested in Aryerez's answer (however, I'd suggest against his advice to try to impress people with convoluted one liners):
def rec (S):
if not S:
return []
else:
return list(S[-1]) + rec(S[:-1])
In fact using + could be more efficient (although the improvement would most likely be negligible), see answers to this SO question for more details.

This is the simplest solution:
def rec(S):
if len(S) == 1:
return S
return S[-1] + rec(S[:-1])
Or in one-line, if you really want to impress someone :)
def rec(S):
return S if len(S) == 1 else S[-1] + rec(S[:-1])

Since append mutates the list, this is a bit difficult to express recursively. One way you could do this is by using a separate inner function that passes on the current L to the next recursive call.
def rec(S):
def go(S, L):
if len(S) > 0:
L.append(S[-1])
return go(S[0:-1], L)
else:
return L
return go(S, [])

L = [i for i in S[::-1]]
It should work.

Related

How to recursively append to an empty list?

I'm new to recursion and finding it pretty difficult to grasp. I can't figure out how to append an empty array if I can't directly "touch" it. If its a string I would add the value each time. If it was a number that involved multiplication, I could multiply it each time, but with an array, I don't know what to do.
I dont know how to append to an empty array without being able to directly "touch" it.
This is what I've done so far:
def laugh(num):
if num == 0:
return []
# This doesnt work since we can't append a function call. I'm unsure what to do.
return laugh(num - 1).append("ha ")
print(laugh(3)) -> ["ha, ha, ha"]
If could do this easily if i could just return a string of "Ha"'s instead. I could return an empty string and just add a "Ha" for each step.
You can modify it like:
def laugh(num):
if num == 0:
return []
haha = laugh(num-1)
haha.append("ha")
return haha
Since append does not return the modified list, you have to do it in two steps. Using concatenation and the ternary operator, you can shrink this to:
def laugh(num):
return laugh(num-1) + ["ha"] if num else []
In this case you are mutating the list by calling append on it. What you want to do is return a new list:
def laugh(num):
# base case
if num == 0:
return []
# recursive case
return ["ha"] + laugh(num-1)

Summing objects in recursive python function

I need to sum objects (strings, ints, etc.) in one function (don't create other function, it can be done within one). It should work this way: When given my_sum([[['s'],'ta'],['c',['k']]]), it should return 'stack'.
I came up with this:
def my_sum(array):
if not array: #empty array
return None
else:
for item in array:
if type(item) == list:
my_sum(item)
else:
print(item)
It of course is not doing what it should be, I was just playing around with it trying to come up with something. This code above returns this:
s
ta
c
k
I think I am not that far from result as I have what I need, but here is the problem how can I sum up those items ? I can't write result = '' anywhere in the function and then return it, because it would be deleting every time there would be recursion call. Also I don't want global variables (if anyone would think of that). Maybe I am just being stupid and can't see that it is one simple thing, pardon me if it is so.
Thank you for every answer!
The common accumulating pattern is:
result = <init value>
for item in argument:
result = result <operator> item
return result
(this can be written more concisely, but that's not the point for now).
Applied to your problem:
def my_sum(items):
result = ''
for item in items:
if type(item) == list:
result += my_sum(item)
else:
result += item
return result
Note that type(x) == y is frowned upon in Python, isinstance is considered better style.
Homework: extend the function so that it works for these arguments too:
print my_sum([[['s'],'ta'],('c',('k')), {('over'), ('flow')}])

Python String Reversal

This exercise involves a codeacademy problem to write a function which takes a string as an input and outputs the string in reverse, I've found solutions as to how to do it online, I'm just confused as to why mine doesnt work:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty[x]=c[stringsize-x]
return empty
You need to start at indexing your string from -1 through to -stringsize, and use empty.append() to add values:
for x in range(stringsize):
empty.append(c[stringsize - x - 1])
Python indexing starts at 0, making stringsize - 1 the last index. Because empty is an empty list, you cannot index into it. Using the list.append() method adds new values at the end instead.
You don't really need the stringsize reference there, because negative indices automatically are subtracted from the length for you:
for x in range(len(c)):
empty.append(c[-x-1])
Since this is supposed to return a string, not a list, you need to join the characters again at the end:
return ''.join(empty)
The easiest way to reverse a list is to use a negative slice stride:
def reverse(c):
return c[::-1]
One solution :
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[-(x+1)])
return ''.join(empty)
print reverse('string')
Another:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[stringsize - (x+1)])
return ''.join(empty)
print reverse('string')
Using recursion:
def reverse(string,start,stop):
if start < stop - 1:
string[start],string[stop - 1] = string[stop - 1],string[start]
reverse(string,start+1, stop-1)
return ''.join(string)
print reverse(list('string'), 0, len('string'))
In Python a string is an iterable so iterable functions can be used with it. For example reversed function:
>>> "".join(reversed("123"))
'321'
The least changes necessary to make your code run seem to be:
def reverse(c):
stringsize= len(c)
empty=[None] * stringsize
for x in range(stringsize):
empty[x]=c[stringsize-x-1]
return empty
But you should reconsider your name empty (as Martijn pointed out) because that thing isn't empty (at least in the end), so the name is misleading.
The classic answer to this problem is to use a slice with a negative step to get what you want:
def reverse(c):
return c[::-1]
...but maybe that's not allowed for you?

How to decrease running time of this particular solution?

I am trying to write a piece of code that will generate a permutation, or some series of characters that are all different in a recursive fashion.
def getSteps(length, res=[]):
if length == 1:
if res == []:
res.append("l")
res.append("r")
return res
else:
for i in range(0,len(res)):
res.append(res[i] + "l")
res.append(res[i] + "r")
print(res)
return res
else:
if res == []:
res.append("l")
res.append("r")
return getSteps(length-1,res)
else:
for i in range(0,len(res)):
res.append(res[i] + "l")
res.append(res[i] + "r")
print(res)
return getSteps(length-1,res)
def sanitize(length, res):
return [i for i in res if len(str(i)) == length]
print(sanitize(2,getSteps(2)))
So this would return
"LL", "LR", "RR, "RL" or some permutation of the series.
I can see right off the bat that this function probably runs quite slowly, seeing as I have to loop through an entire array. I tried to make the process as efficient as I could, but this is as far as I can get. I know that some unnecessary things happen during the run, but I don't know how to make it much better. So my question is this: what would I do to increase the efficiency and decrease the running time of this code?
edit = I want to be able to port this code to java or some other language in order to understand the concept of recursion rather than use external libraries and have my problem solved without understanding it.
Your design is broken. If you call getSteps again, res won't be an empty list, it will have garbage left over from the last call in it.
I think you want to generate permutations recursively, but I don't understand where you are going with the getSteps function
Here is a simple recursive function
def fn(x):
if x==1:
return 'LR'
return [j+i for i in fn(x-1) for j in "LR"]
Is there a way to combine the binary approach and a recursive approach?
Yes, and #gribbler came very close to that in the post to which that comment was attached. He just put the pieces together in "the other order".
How can you construct all the bitstrings of length n, in increasing order (when viewed as binary integers)? Well, if you already have all the bitstrings of length n-1, you can prefix them all with 0, and then prefix them all again with 1. It's that easy.
def f(n):
if n == 0:
return [""]
return [a + b for a in "RL" for b in f(n-1)]
print(f(3))
prints
['RRR', 'RRL', 'RLR', 'RLL', 'LRR', 'LRL', 'LLR', 'LLL']
Replace R with 0, and L with 1, and you have the 8 binary integers from 0 through 7 in increasing order.
You should look into itertools. There is a function there called permutations which does exactly what you want to achieve here.

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