Anti_vowel


#1



anti_vowel


Error: Your function fails on anti_vowel("Hey look Words!"). It returns "None" when it should return "Hy lk Wrds!".


I expected the code to return "Hy lk Wrds!". Not sure why it's coming up "none." If you copy and paste the same code into repl.it it works just fine.


new = ""
n = 0
def anti_vowel(text):
    global new
    global n
    if n == (len(text) - 1):
        return new
    else:
        if text[n] == 'a' or text[n] == 'e' or text[n] == 'i' or text[n] == 'o' or text[n] == 'u' or text[n] == 'A' or text[n] == 'E' or text[n] == 'I' or   text[n] == 'O' or text[n] == 'U':
            n = n + 1
            anti_vowel(text)
        else:
            new += text[n]
            n = n + 1
            anti_vowel(text)


#2

Because there are no returned strings. The SCT is reading the return value, not a global variable, new. It doesn't know it exists.

Interesting use of recursion, though perhaps a little more advanced than Unit 8 and previous units. It would be a good idea to circle back to using concepts and tools learned up to this point just so your work is closer to the expectations of the lesson checker.


#3

Awesome!

I appreciate your prompt response immensely. In regards to the use of recursion, I work in an IT department and have likely been exposed here and there to random elements and practices that may be out of the range of the lessons. I agree with you, though, I'll stick closer to what the course intends.

In the meantime, I would like to see if I could make this work and return to the problem again with the aforementioned intent. So, a quick follow up question: I was under the impression that defining the variable with global at the beginning of the function would make all the instances of the variable (new in my case) follow and recall based on the global definition. Is there something I could do to make the return value reference the global variable?


#4

In terms of global variables, unless they are intended for universal use such as global constants or data structures, they should be avoided. They pollute the global namespace and are subject to corruption by other programs residing in the same space. At least this is the case with JavaScript, I think it best to give variables their own environment, either in a function or a class with instances. Not an expert opinion, mind. Others here are far more knowledgeable on the subject than am I.

The first thing I would look at with your code is the lengthy and verbose conditional expression. In Python we can use the in operator with great efficiency...

if text[n] not in "aeiouAEIOU":

Instead of making new and n global, define them locally. In the recursion, instead of just returning on the base case, have the other cases return the function call.

return anti_vowel(text)

This will set up a call stack that will be cycled down once the base case is reached. The final return should be the filtered text.

I haven't tested this, but let me know how it goes.


#5

Yeah, I couldn't get it to work. The trouble is defining a string to add the consonants to that doesn't get reset each time the function recurses.

However, I did get it to work quite simply in a way more likely intended by the course progression:

def anti_vowel(text):
    new = ""
    for n in text:
        if n not in "aeiouAEIOU":
            new = new + n
    return new

Which, at the end of the day, simplicity and readability is the goal. Thanks for your help!


#6

This is an interesting problem, and one that will challenge me, a hobbyist not prone to recursive approaches, favoring the more mechanical and less intuitive means. I could not discount your idea and now just to see it work will give it a go. If you solve it before I do, please advise. I may be pulling my hair out and need relief.

It just occurs to me that the answer may take this form:

return t + foo(n - 1)

sort of thing. This way when the stack winds down, it grabs all the values of t all the way down and result in a complete return value.


#7

Of course this only betrays my vague understanding of recursion, which I will will defer to another member...


#8

Managing global variables with a recursion can get messy, especially if we anticipate making an external call to the function more than once. We may need to clean up the global variables when we are done, in preparation for reusing the function. Here is a solution that passes the SCT ...

new = ""
n = -1
def anti_vowel(text):
    global new, n
    n += 1
    # print text, new
    if n == len(text):
        # We are done,
        # so clean up global variables for next external call
        res = new
        new = ""
        n = -1
        return res
    if text[n] not in "aeiouAEIOU":
        new = new + text[n]
    return anti_vowel(text)
          
print anti_vowel("Hey look Words!")
print anti_vowel("Holy Grail!")

#9

Whoa that's really messy. The way I learned recursion is using cases. In this case, we have three:

One where string is empty, one where first letter is vowel and one where first letter is not a vowel.

(idk if this is optimal but then again, Python isn't designed for recursion)
And of course, this code can be improved to look shorter (such as removing the else: and unindenting the last return statement).

def anti_vowel(text):
    if text == "": #string is empty
        return text
    elif text[0] in "AEIOUaeiou": #first letter is a vowel
        return anti_vowel(text[1:])
    else: #first letter is not a vowel
        return text[0] + anti_vowel(text[1:])

Anti-vowel, Recursive problem(SOLVED)
#10

Thanks for the nice clean recursive solution, @datfatcat. :smile:


#12

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.