Censor Dispenser project email_four problem

Hi folks, I’m running into a problem on the final question of the Censor Dispenser project (https://www.codecademy.com/practice/projects/censor-dispenser) which I can’t seem to get my head around, and was wondering if anyone would be so kind as to take a look at my code.

For context, the issue i’m having is with the following question:
5. “Write a function that censors not only all of the words from the negative_words and proprietary_terms lists, but also censor any words in email_four that come before AND after a term from those two lists.”

I should note that at the minute, the function I am trying to create is just trying to solve a simplified version of the problem by just censoring email_four of the words in the first list; proprietary_terms and the words before and after proprietary terms. I am not yet taking into account punctuation or case. I plan to add the functionality to fully meet the criteria of the question later.

So here’s my (probably exceedingly dry-violating and over-complicated) code (lol):

email_one = open("email_one.txt", "r").read()
email_two = open("email_two.txt", "r").read()
email_three = open("email_three.txt", "r").read()
email_four = open("email_four.txt", "r").read()


proprietary_terms = ["she", "personality matrix", "sense of self", "self-preservation", "learning algorithm", "herself", "her"]

negative_words = ["concerned", "behind", "danger", "dangerous", "alarming", "alarmed", "out of control", "help", "unhappy", "bad", "upset", "awful", "broken", "damage", "damaging", "dismal", "distressing", "distressed", "concerning", "horrible", "horribly", "questionable"]


def censor_all(text, censor_list_1, censor_list_2):
  censor_list_1.sort(key=len)
  censor_list_1.reverse()
  censor_list_2.sort(key=len)
  censor_list_2.reverse()
  # ^ SORTS THE CENSOR LISTS BY LENGTH IN DESCENDING ORDER

  for element in censor_list_1:
    if text.find(element) != -1:
      index_finder_pre = text.find(element) - 2
      while text[index_finder_pre] != " ":
        index_finder_pre - 1
      if text[index_finder_pre] == " ":
        precensor_start = index_finder_pre
      # SETS INDEX FOR PRECENSOR START ^

      index_finder_post = text.find(element) + 1
      while text[index_finder_post] != " ":
        index_finder_post + 1
      if text[index_finder_post] == " ":
        postcensor_end = index_finder_post + 2
      while text[postcensor_end] != " ":
        postcensor_end + 1
      if text[postcensor_end] == " ":
        text[precensor_start:postcensor_end] = "##CENSORED##"
      # SETS INDEX FOR POSTCENSOR END, THEN CENSORS ^


      if text.find(element) != -1:
        censor_list_1.append(element)
      if text.find(element) == -1:
        print(element)
        continue
      # CHECKS IF ALL OCCURENCES OF CENSOR WORD HAVE BEEN REMOVED ^
  return text




print(email_four)
print(censor_all(email_four, proprietary_terms, negative_words))

The problem I’m encountering is one I haven’t really encountered before (perhaps an infinite loop?)
Basically, print(censor_all(email_four, proprietary_terms, negative_words)) or calling censor_all in any way results in a very long loading bar and eventually ends in literally a blank output in the terminal. Not even [none], I mean no output whatsoever. The terminal doesn’t even print unrelated print statements even if I called a print statement on the first line before any of my code.

What’s weird, is that if i change a variable name to nonsense e.g text to 457370dfgs#€text anywhere in my function, or for that matter, change any part of the function in a way which should produce an error, the error is found as expected and reported in the terminal. I only get a 10second+ loading bar followed by a blank output when everything in my function seems to be written correctly.

Does anyone have any idea why this might be?

Hey,

I only get a 10second+ loading bar followed by a blank output when everything in my function seems to be written correctly.

Usually the sign of some infinite loop. Although I don’t user the CC terminal (I always did these things on text editors). But once you find what’s happening that’ll be the ultimate answer to this.

I would just comment out the return statement for now for debugging, set up choke points with information-rich print statements in your function, and if it’s not running comment out parts as necessary to isolate what is acting up. Luckily it’s not that much code (three small sections) so this process can weed out the issue pretty quick.

2 Likes

Thanks, will get to work on this now and post results :slight_smile:

I did as you suggested and managed to isolate the problems, which were pretty much all of the while loops. Looks like I need to do more research on while loops as I used them wrongly in this case. For some reason which I don’t yet understand, changing whiles to ifs avoided the infinite loop and allowed my function to execute.

The final issue causing these infinite loops was this line:

if text.find(element) != -1:
        censor_list_1.append(element)

Which was placed inside the for loop:

for element in censor_list_1:

I noticed, that if define an empty list at the start of my function, and append to this list instead of censor_list_1, the function runs just fine. So the problem here seems to be arising from the fact I am appending a list whilst iterating through that list?

On the face of it, I don’t see why this shouldn’t be possible…

While loops are tricky, because one has to be sure that the condition one sets it will break the loop at some point. One way to test it is to set a different while loop to test your original while loop condition, give it a finite counter, and throw a truthy statement with the original condition to see if it ever becomes false.

It might not be that the idea of using the while loop is not applicable, but that the condition has to be iron-clad.