3

I am currently working through "Automate the boring stuff with python". I am on the practice project for chapter 8 titled "Mad Libs". The task is as follows:

Create a Mad Libs program that reads in text fles and lets the user add their own text anywhere the word ADJECTIVE, NOUN, ADVERB, or VERB appears in the text file. For example, a text fle may look like this:

The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was unaffected by these events.

The program would find these occurrences and prompt the user to replace them.

Enter an adjective: silly

Enter a noun: chandelier

Enter a verb: screamed

Enter a noun: pickup truck

The following text file would then be created:

The silly panda walked to the chandelier and then screamed. A nearby pickup truck was unaffected by these events.

The results should be printed to the screen and saved to a new text file.

My current program is as follows:

#! python3
# Requests user for an ADJECTIVE, NOUN, ADVERB, and a NOUN
# Replaces the words ADJECTIVE/NOUN/ADVERB/NOUN with the input in a txt file
# Saves the new Mad Lib as a new txt file

import re

reADJECTIVE = re.compile(r'''(ADJECTIVE)''')
reNOUN = re.compile(r'''(NOUN)''')
reVERB = re.compile(r'''(VERB)''')

for i in range(1):
    # Gets user input for ADVECTIVE/NOUN/VERB/NOUN
    ADJECTIVE = input('Enter an adjective: ')
    NOUN = input('Enter a noun: ')
    VERB = input('Enter a verb: ')
    NOUN2 = input('Enter a noun: ')

    madLibFile = open('madlib%s.txt' % (i + 1))
    madLibFileContent = madLibFile.read()
    madLibFile.close()
    madLibFileContent = madLibFileContent.split('. ')
    print(madLibFileContent)

    newMadLib = re.sub(reADJECTIVE, ADJECTIVE, madLibFileContent[0])
    newMadLib = re.sub(reNOUN, NOUN, newMadLib)
    newMadLib = re.sub(reVERB, VERB, newMadLib)
    newMadLib = newMadLib + '. ' + re.sub(reNOUN, NOUN2, madLibFileContent[1])

    print(newMadLib)

For the given example this program works, however due to the way i seperate the file it reads in by the fullstop/period it only works when the format of the input file is:

ADJECTIVE NOUN ADVERB. NOUN.

and would not work for any other format such as:

ADJECTIVE NOUN. ADVERB NOUN.

My initial idea was to use the regex pattern:

(ADJECTIVE).*(NOUN).*(VERB).*(NOUN)

This works if we assume any given Mad Lib follows the same pattern of Adjective-Noun-Verb-Noun.

If I were to use:

re.sub(r'(NOUN)', replacement, someString)

It would replace ever instance of NOUN in the string with replacement. Is it possible to replace each capture group with something different?

Thank you for your time, and I hope the question was clear enough :)

2 Answers 2

2

The trick is to use a function in place of a replace string in the re.sub. Here's a crude way of doing it.

import re

sentence = 'The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was unaffected by these events.'

def consider(matchobj):
    content = matchobj.group()
    if content in ['NOUN', 'ADJECTIVE', 'ADVERB', 'VERB']:
        return input('Please enter ' + content)
    else:
        return content

print (re.sub('[A-Z]+', consider, sentence))

I didn't bother to use your words, just whatever came to my troubled mind at the time. Here's what it looks like in use.

Please enter ADJECTIVEbig
Please enter NOUNbear
Please enter VERBgoes
Please enter NOUNhome
The big panda walked to the bear and then goes. A nearby home was unaffected by these events.

EDIT: Added in response to comment.

import re

partsOfSpeech = ['NOUN', 'ADJECTIVE', 'ADVERB', 'VERB']
replacements = {_:'' for _ in partsOfSpeech}

for r in replacements:
    replacements[r] = input('Please enter ' + r.lower() + ': ')

madLibs = [
    'The ADJECTIVE panda walked to the NOUN and then VERB. A nearby NOUN was unaffected by these events.',
    'A NOUN ADVERB decided to VERB the NOUN'
    ]

def consider(matchobj):
    content = matchobj.group()
    if content in partsOfSpeech:
        return replacements[content]
    else:
        return content

for madLib in madLibs:
    print (re.sub('[A-Z]+', consider, madLib))

Result:

Please enter adjective: vast
Please enter adverb: smoothly
Please enter verb: went
Please enter noun: bear
The vast panda walked to the bear and then went. A nearby bear was unaffected by these events.
A bear smoothly decided to went the bear
Sign up to request clarification or add additional context in comments.

4 Comments

I kind of understand how that works. But wouldn't this require the user to enter a new Adjective/Noun/etc for each Mad Lib? Because what I am trying to accomplish is that the user enters in an Adjective/Noun/etc and it replaces those in any number of files, not on a file by file basis.
You're right. I've written a bigger script. Now the script saves the replacement words in a dictionary, available for use in the function that's called if there's a regex match. Rather than creating several files I have just created a list of two sentences.
Again thank you for your help. But I have a further question. In the example you have given, this does not allow for multiple nouns. For instance in the pattern outlined above of ADJECTIVE, NOUN, VERB, NOUN, if the user entered a different noun each time, only one would be considered for replacement.
You're welcome but it's time for you to go on for yourself. Best of luck!
0

This is my code:

#! python3
# Mad Libs program to replace ADJECTIVE, NOUN, ADVERB, or VERB
import re,os
dir=os.getcwd()
readFile=open(dir)
contents=readFile.read()
readFile.close()
content=contents.split()

Okay so the above lines are opening the file, and in contents the whole content of the file is stored. In content the individual words are stored independently.

i=0
for contents in content:
    if('ADJECTIVE' in contents):#Checks if the word is ADJECTIVE
        regex1=re.compile(r'ADJECTIVE')
        content[i]=regex1.sub(input('What is the ADJECTIVE?\nEnter:'),contents)
    elif ('NOUN' in contents):#Checks if the word is NOUN
        regex1=re.compile(r'NOUN')
        content[i]=regex1.sub(input('What is the NOUN?\nEnter:'),contents)
    elif ('VERB' in contents):#Checks if the word is VERB
        regex1=re.compile(r'VERB')
        content[i]=regex1.sub(input('What is the VERB?\nEnter:'),contents)
    elif ('ADVERB' in contents):#Checks if the word is adverb
        regex1=re.compile(r'ADVERB')
        content[i]=regex1.sub(input('What is the ADVERB?\nEnter:'),contents)
    i=i+1

The regex1 is responsible for substituting for individual inputs of VERB, ADJECTIVE, NOUN and an ADVERB. The content[i] and i to make sure of the locations and the right words get replaced.

contents=' '.join(content)
print(contents)
writeFile=open(dir,'w')
writeFile.write(contents)
writeFile.close()

Please feel free to correct me, or to solve this problem in a shorter way. Hope it solves your problem.

1 Comment

@MatthieuBrucher I have added some explanations, please tell me if I need to elaborate more.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.