Is this recursive? - python-3.x

Second attempt here, I just wanted to know if this is considered a recursive function.
The purpose of the function is to take a string and
if the the first element is equal to the last element
then append the last element to a list and return nothing,
else call istelf and pass the same string from index [1]
finally append the first element to the list
I know that error checking needs to be done on the if statement. However I am only doing this to try and get my head around recursion...Struggling to be honest.
Also I would never write a program like this if it where anything but trivial I just wanted to check if my understanding is correct so far.
def parse(theList):
theList.reverse()
parsedString = ''.join(theList)
return parsedString
def recursiveMessage(theString):
lastElement = theString[len(theString) - 1]
if theString[0] == lastElement:
buildString.append(theString[0])
return None
else:
recursiveMessage(theString[1::])
buildString.append(theString[0])
toPrint = "Hello Everyone!"
buildString = []
recursiveMessage(toPrint)
print(parse(buildString))
Thanks again.

Is this recursive?
If at any point in a function's execution it calls itself, then it is consider recursive. This happens in your example, so recursiveMessage is indeed recursive.
so which is quicker recursion or iteration?
Recursion is usually much slower and consumes more space due to a new stack frame having to be created on the call stack each recursive call. If you know your recursive function will need to be run many times, iteration is the best route.
As an interesting side note, many compilers actually optimize a recursive function by rolling it out into a loop anyways.

Related

What's wrong with my python recursive code?

Sorry for my ugly English.
This is one of my homework.
I'm making function that finds the max integer in any list, tuple, integer..
like "max_val((5, (1,2), [[1],[2]])) returns 5"
When I ran my code, there was no syntax error. I ran as many various cases I can.
But the homework system told me this code was incorrect.
Anyone give me hint?
numList = []
def max_val(t):
if type(t) is int:
numList.append(t)
else:
for i in range(len(t)):
if t[i] is int:
numList.append(t[i])
else:
max_val(t[i])
return max(numList)
Your code gives wrong results when called several times:
>>> max_val((5,4,3))
5
>>> max_val((2, 1))
5
That's because numList is a global variable that you don't "reset" between calls of your function.
You can simplify your code quite a bit, without needing that global variable:
def max_val(t):
if isinstance(t, int):
return t # t is the only element, so it's by definition the biggest
else:
# Assuming max_val works correctly for an element of t,
# return the largest result
return max(max_val(element) for element in t)
As explained in L3viathan's answer, the main issue with your code is that numList is a global variable. Here is a simple way to fix it without changing the logic of your code:
def max_val(t):
numList = [] # local variable
max_val_helper(t, numList) # fill numList with elements from t
return max(numList)
def max_val_helper(t, numList): # this function modifies its second argument and doesn't return a value
if type(t) is int:
numList.append(t)
else:
for i in range(len(t)):
max_val_helper(t[i], numList)
The function max_val_helper is recursive and appends all numbers in the nested iterables to its argument numList. This function doesn't have a return value; the effect of calling it is that it modifies its argument. This kind of function is sometimes called a "procedure".
The function max_val, on the other hand, is a "pure" function: it returns a value without any side-effect, like modifying its argument or a global variable. It creates a local variable numList, and passes this local variable to max_val_helper which fills it with the numberss from the nested iterables.
The code suggested in L3viathan's answer is arguably more elegant than this one, but I think it's important to understand why your code didn't work properly and how to fix it.
It's also good practice to differentiate between functions with side-effects (like modifying an argument, modifying a global variable, or calls to print) and functions without side-effects.

Receiving function as another function´s parameter

Let´s say I have 2 functions like these ones:
def list(n):
l=[x for x in range(n)]
return l
def square(l):
l=list(map(lambda x:x**2,l))
print(l)
The first one makes a list from all numbers in a given range which is "n" and the second one receives a list as a parameter and returns the squared values of this list.
However when I write:
square(list(20))
it raises the error "map object cannot be interpreted as an integer" and whenever I erase one of the functions above and run the other one it runs perfectly and I have no idea what mistake I made.
You redefined the standard function list()! Rename it to my_list() and clean the code accordingly.
As a side note, your function list() is doing exactly what list(range(n)) would do. Why do you need it at all? In fact, for most purposes (including your example), range(n) alone is sufficient.
Finally, you do not pass a function as a parameter. You pass the value generated by another function. It is not the same.

Why is the time complexity of this algorithm exponential?

During an interview, I was asked the time complexity of the following algorithm:
static bool SetContainsString(string searchString, HashSet<string> setOfStrings)
{
for (int i = 0; i < searchString.Length; i++)
{
var segment = searchString.Substring(0, i + 1);
if (setOfStrings.Contains(segment))
{
var remainingSegment = searchString.Substring(segment.Length);
if (remainingSegment == "") return true;
return SetContainsString(remainingSegment, setOfStrings);
}
}
return false;
}
I answered "linear" because it appears to me to loop only through the length of searchString. Yes, it is recursive, but the recursive call is only on the portion of the string that has not yet been iterated over, so the end result number of iterations is the length of the string.
I was told by my interviewer that the time complexity in the worst case is exponential.
Can anyone help me clarify this? If I am wrong, I need to understand why.
I believe that your interviewer was incorrect here. Here’s how I’d argue why the time complexity isn’t exponential:
Each call to the function either makes zero or one recursive call.
Each recursive call reduces the length of the string by at least one.
This bounds the total number of recursive calls at O(n), where n is the length of the input string. Each individual recursive call does a polynomial amount of work, so the total work done is some polynomial.
I think the reason your interviewer was confused here is that the code given above - which I think is supposed to check if a string can be decomposed into one or more words - doesn’t work correctly in all cases. In particular, notice that the recursion works by always optimistically grabbing the first prefix it finds that’s a word and assuming that what it grabbed is the right way to split the word apart. But imagine you have a word like “applesauce.” If you pull off “a” and try to recursively form “pplesauce,” you’ll incorrectly report that the word isn’t a compound because theres no way to decompose “pplesauce.” To fix this, you’d need to change the recursive call to something like this:
if (SetContainsString(...)) return true;
This way, if you pick the wrong split, you’ll go on to check the other possible splits you can make. That variant on the code does take exponential time in the worst case because it can potentially revisit the same substrings multiple times, and I think that’s what the interviewer incorrectly thought you were doing.

Return multiple values to main function from a for loop in another function in Python

I've read several questions similar to this, but still can't quite figure this out. This should be simple, but I'm not seeing the forest from the trees.
I have a for loop in a function as follows:
for item in range(len(mf)):
fp = fp + str(mf[item])
return(fp)
I then want to call the function in my main function and return however many instances of fp there are like:
print(return_1)
print(return_2)
Take the return statement out of the loop. You don't want to return until you've finished concatenating all the items.
You can also replace the loop with a list comprehension and the join function.
return "".join(str(item) for item in mf)

Why doesn't this simple Lua coroutine work?

I have a very simple little piece of Lua code, which I wrote while teaching myself how coroutines work.
I was fine until I got to coroutine.wrap, the spec states:
coroutine.wrap (f)
Creates a new coroutine, with body f.
f must be a Lua function. Returns a
function that resumes the coroutine
each time it is called. Any arguments
passed to the function behave as the
extra arguments to resume. Returns the
same values returned by resume, except
the first boolean. In case of error,
propagates the error.
However this code:
Enumeration = {}
Enumeration.Create = function(generator)
return coroutine.wrap(generator, coroutine.yield)
end
local function TestEnumerator(yield)
yield(1) --ERROR HERE
yield(2)
yield(3)
end
local enumerator = Enumeration.Create(TestEnumerator)
local first = enumerator()
local second = enumerator()
local third = enumerator()
print (first, second, third)
Complains that yield is nil (on the line I have marked above). As I understand it, yield should be the second argument passed into coroutine.wrap, so where am I going wrong?
Really obvious solution, thanks to the answer below
Enumeration.Create = function(generator)
local iter = coroutine.wrap(generator, coroutine.yield)
return function()
return iter(coroutine.yield)
end
end
This is not how coroutine.wrap works. You have to pass coroutine.yield in the first call to enumerator.

Resources