Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ThinkPython Exercise 9.3
#1
Hello, I am working on ThinkPython exercise 9.3 which asks us to write a function that determines whether any word contains a list of "forbidden letter"(fl) as a user input. I wrote the below code but can't seem to get Pyhon to recognize the "forbidden letters". Please help! Thank you.

def avoids(word):
    fl = raw_input('What letters you would like to forbid?\n')
    all_fl=fl.lower()+fl.upper()
    print (all_fl)  
    for char in word:
        if char == all_fl:
            return False
    return True
Reply
#2
The Problem is that you are concatenating two strings, so that the upper and lower case are both in one string and then you are searching the array for this long string.
Compare the lower and the upper case word with the list and if you find anything, than great:
def avoids(word):
    fl = raw_input('What letters you would like to forbid?\n')
    if fl.lower() in word or fl.upper() in word or fl in word:
          return False
    return True
Reply
#3
@ThiefOfTime - that's not correct answer. it will check that user input as a whole string is present/not present in word. The assignment asks if any single forbidden char is present
def avoids(word):
    forbidden = raw_input('What letters you would like to forbid?\n').lower()
    for char in word.lower():
        if char in forbidden:
            return False
    return True
my advice from the other thread that there is more concise way to do it still holds

def avoids(word, forbidden):
    return any(ch in forbidden.lower() for ch in word.lower())
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#4
Hello Buran - that's amazing. I didn't realize you can "lower case" an entire raw_input. That's a great idea and much more concise. The two line code looks really smart but I don't 100% understand the logic. Will check your other post. Thank you.

Thank you for trying @ ThiefofTime
Reply
#5
(May-23-2018, 07:14 PM)buran Wrote: @ThiefOfTime - that's not correct answer. it will check that user input as a whole string is present/not present in word. The assignment asks if any single forbidden char is present
def avoids(word):
    forbidden = raw_input('What letters you would like to forbid?\n').lower()
    for char in word.lower():
        if char in forbidden:
            return False
    return True
my advice from the other thread that there is more concise way to do it still holds

def avoids(word, forbidden):
    return any(ch in forbidden.lower() for ch in word.lower())

Oh, my bad. I misunderstood the task, sorry :) I thought it would get a single word as input and checks if this word is forbidden. but. I was confused that the lower and upper cases are connected. I thought it meant to check for words, not for chars.
Reply
#6
Hello, I wrote the rest of the code for the exercise which asks us to calculate the % of words in the document "words.txt" that does not contain the forbidden letters which are input by users. The code I wrote below just keeps repeating the user input line and don't move onto the next section. Can someone please help? Thank you.

fin=open('words.txt')

def avoids(word):
    fl = raw_input('What letters would you like to forbid?\n').lower()
    print (fl)
    for char in word.lower():
        if char in fl:
            return False
    return True

count=0
for line in fin:
    word=line.strip()
    if avoids(word):
        count = count+1
        
percent= (count/113809.0)*100
print str(percent)+"% of the words don't have the forbidden letters'."
Reply
#7
I tried your code and it keeps on going to the next piece of code. It really never reaches the last print? because if your file got 113809 lines it may take some time to get to the end and since you are asking for forbidden letters for each single word, you have to input those 1133809 times and therefore always get the input printed. I don't know if that is part of the task or not, but I would suggest to ask once at the beginning of the program and give your function the forbidden chars.
Some tips for your code:
Always make sure to close your file or use:
with open("words.txt") as fin:
     #your code
so that python takes care of that by itself.
Furthermore you want to have the amount of words with forbidden letters, but your function returns True if the word does not includes forbidden letters, change your if case to:
if not avoids(word):
    count += 1
to get the right count.
And finally you divide by a concrete number, but in a case where the file contains less than 1133809 words, it would be useful to have the amount of words in that file.
since you are iterating already you could have a second counter to count all words :)
Reply
#8
Thank you ThiefofTime!!Appreciate your input.

I rewrote my code below to enter another function that calls the calculation which works not but the user has to manually enter the function ("cal_perc") after putting in the forbidden letters. I am not sure if there is a way for the code just runs on its own course :

fin=open('words.txt')

fl = raw_input('What letters would you like to forbid?\n').lower()
def avoids(word):
    for char in word.lower():
        if char in fl:
            return False
    return True

def cal_perc():
    count=0
    for line in fin:
        word=line.strip()
        if avoids(word):
            count=count+1
    percent= (count/113809.0)*100
    print str(percent)+"% of the words does not have the forbidden letters'." 
Reply
#9
My suggestion for the code would be:
def avoids(word, forbidden_chars):
    for char in word.lower():
        if char in forbidden_chars:
            return False
    return True
 
#optionally you could even let the user insert a path to the word.txt
words_path = raw_input('Please provide a path to the words.txt file.\n')
if len(words_path) <= 0:
    words_path = 'words.txt'
fin=open(words_path)
fl = raw_input('What letters would you like to forbid?\n').lower()
count=0
complete_count = 0
for line in fin:
    word=line.strip()
    complete_count += 1
    if avoids(word, fl):
        count=count+1
percent = (count/complete_count)*100
print("{}% of the words does not have the forbidden letters'.".format(str(percent))) 
fin.close()
now the code runs on its own :) or what did you mean by runs on its own?
Reply
#10
a somewhat better would be
def avoids(word, forbidden):
    # return not any(char in forbidden for char in word) # this line is enough, instead all the rest to the end of function
    for char in word:
        if char in forbidden:
            return False
    return True
 
def cal_perc(filename):
    fl = raw_input('What letters would you like to forbid?\n').lower()
    count = 0
    with open(filename) as fin:
        for n, line in enumerate(fin, start=1):
            word = line.strip().lower()
            if avoids(word=word, forbidden=fl):
                count += 1
    return count/float(n)*100

if __name__ == '__main__':
    percent = calc_perc(filename='words.txt')
    print '{}% of the words does not have the forbidden letters'.format(percent)
by the way, it's better to switch to python3
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  ThinkPython Exercise 9.2 sangurocactus 6 4,787 May-23-2018, 04:17 PM
Last Post: sangurocactus

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020