printing, splitting, and replacing in lists - python

I'm trying to make a quiz using a questions file, and a choice between two answer files. I am going to have the user choose between printing all questions and answers, or just a few randomly generated ones. My problem is that I am having trouble getting it to display as intended. I need for it to display like:
1. how many... etc.
a.answer
b.answer
c.answer
d.answer
e.none of the above
but I can't get the output right. the text files consists of the answers placed like this:
C,3,4,5,6
A,4O,30,20,10
E,65,245,456,756
so I have replaced the commas with spaces, and have been succesful displaying them as a row rather than one line by using \n in place of spaces.. but it won't work as some answers are more than one word. I also need to remove the letter before the answers (it's the correct answer) and place this into a list, and I'm really unsure of how to do this.
import random
def main():
print("Welcome to the Garbology Quiz \n")
quizfilecheck = input("First off, what is the quiz file name? ")
while quizfilecheck != "questions.txt":
quizfilecheck = input("File not found.. what is the correct quiz file name? ")
answerfilecheck = input("And now what answer file are you using? ")
while answerfilecheck != "american-answers.txt" and answerfilecheck != "metric-answers.txt":
answerfilecheck = input("File not found.. please enter the correct answer file name. ")
questionList = getData()
answerList = getFormat()
inputanswers = printinputanswers(questionList,answerList)
def getData():
with open("questions.txt") as questionFile:
questionList = questionFile.readlines()
return questionList
def getFormat():
formatchoice = input("\n Would you like the answers printed in metric or american format? (m or a): ")
formatchoice = formatchoice.lower()
while formatchoice != "a" and formatchoice != "m":
formatchoice = input("Invalid input, please enter a correct value (m or a): ")
formatchoice = formatchoice.lower()
if formatchoice == "a":
answerPath = "american-answers.txt"
else:
answerPath = "metric-answers.txt"
with open(answerPath) as answerFile:
answerList = answerFile.readlines()
return answerList
def printAllanswers(questionList,answerList):
for i in range(0,len(questionList)):
print(questionList[i])
print(''.join(map(str,answerList[i].replace(',',' ').replace(' ','\n'))))
allanswers = printAllanswers(questionList,answerList)
def printinputanswers(questionList,answerList):
numofquestions = input(" How many questions do you want to print? ")
if numofquestions.isdigit():
numofquestions = int(numofquestions)
for i in range(0,numofquestions):
randomnum = random.randint(0,len(questionList))
print (questionList[randomnum])
print(''.join(map(str,answerList[randomnum].replace(',',' ').replace(' ',' '))))
main()
***********output and i know I haven't called printallanswers() yet, I'm going to after I have the correct output working
First off, what is the quiz file name? questions.txt
And now what answer file are you using? metric-answers.txt
Would you like the answers printed in metric or american format? (m or a): m
How many questions do you want to print? 4
If every country consumed and threw away at the rate Americans do, how many planets' worth of resources would be required to meet the demand?
C 3 4 5 6
If every country consumed and threw away at the rate Americans do, how many planets' worth of resources would be required to meet the demand?
C 3 4 5 6
America is home to 4 percent of the world's children. What percentage of the world's toys do Americans buy and throw away?
A 4O 30 20 10
How many nonrecyclable Styrofoam cups do Americans throw away in a year?
D 5 billion 10 billion 15 billion 25 billion
code
def printsingleanswer(questionList,answerList):
randomnum = random.randint(0,len(questionList))
chars1= string.ascii_lowercase
answers=answerList[randomnum].split(',')[1:] #removes the answer letter
answers.append('none of the above')
print ('\n'.join(chars1[i]+'. '+answers[i] for i in range(len(answers))))
output
Would you like the answers printed in metric or american format? (m or a): m
a. 5 billion
b. 10 billion
c. 15 billion
d. 25 billion
e. none of the above
It's adding a new line before every "e" choice, is there a way to keep it grouped together like the first four choices?

For answer sets that do not have commas, how about:
import string
chars1= string.ascii_lowercase
answers=answerList[randomnum].strip().split(',')[1:] #removes the answer letter
answers.append('none of the above')
print '\n'.join(chars1[i]+'. '+answers[i] for i in range(len(answers)))
The statement:
chars1[i]+'. '+answers[i],
adds a character to the beginning of each answer, and as string.ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz' this will give a alphabetic character to every answer starting with 'a'.
If there are commas then you have to store the file as a full csv and use the csv module to load the file and then rather than using a split as in the code above, you just use each row from the extracted csv.

Related

Why does the third iteration of my code return incorrectly?

I am in a MOOC for Python. This is my first time posting a question here.
My expected results should print Captain Hawk, Doctor Yellow Jacket, and Moon Moon,
each on their own line.
Instead, I get Captain Hawk, Doctor Yellow Jacket, and Moon Yellow Jacket each on their own line. What is wrong with my code?
#A common meme on social media is the name generator. These
#are usually images where they map letters, months, days,
#etc. to parts of fictional names, and then based on your
#own name, birthday, etc., you determine your own.
#
#For example, here's one such image for "What's your
#superhero name?": https://i.imgur.com/TogK8id.png
#
#Write a function called generate_name. generate_name should
#have two parameters, both strings. The first string will
#represent a filename from which to read name parts. The
#second string will represent an individual person's name,
#which will always be a first and last name separate by a
#space.
#
#The file with always contain 52 lines. The first 26 lines
#are the words that map to the letters A through Z in order
#for the person's first name, and the last 26 lines are the
#words that map to the letters A through Z in order for the
#person's last name.
#
#Your function should return the person's name according to
#the names in the file.
#
#For example, take a look at the names in heronames.txt
#(look in the drop-down in the top left). If we were to call
#generate_name("heronames.txt", "Addison Zook"), then the
#function would return "Captain Hawk": Line 1 would map to
#"A", which is the first letter of Addison's first name, and
#line 52 would map to "Z", which is the first letter of
#Addison's last name. The contents of those lines are
#"Captain" and "Hawk", so the function returns "Captain Hawk".
#
#You should assume the contents of the file will change when
#the autograder runs your code. You should NOT assume
#that every name will appear only once. You may assume that
#both the first and last name will always be capitalized.
#
#HINT: Use chr() to convert an integer to a character.
#chr(65) returns "A", chr(90) returns "Z".
#Add your code here!
def generate_name(filename, name):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# splitting the name so I can add the intials of the name into a list.
z = []
j = name.split()
for i in j:
z.append(i[0])
# linking the initials to it's index in the alphabet
for k in alphabet:
if k == z[0]:
first = alphabet.index(k)
elif k == z[1]:
second = alphabet.index(k) + 26
else:
pass
# reading the super hero names from the file and linking the name to the index
file = open(filename, "r")
filelist = file.readlines()
for i in filelist:
global hero
if filelist.index(i) == first:
supe = i
supe = supe.strip()
elif filelist.index(i) == second:
hero = i
hero = hero.strip()
else:
pass
file.close()
return supe + " " + hero
#Below are some lines of code that will test your function.
#You can change the value of the variable(s) to test your
#function with different inputs.
#
#If your function works correctly, this will originally
#print: Captain Hawk, Doctor Yellow Jacket, and Moon Moon,
#each on their own line.
print(generate_name("heronames.txt", "Addison Zook"))
print(generate_name("heronames.txt", "Uma Irwin"))
print(generate_name("heronames.txt", "David Joyner"))
The file that has the superhero names is called heronames.txt and it looks like this, but every name is on it's own line:
Captain
Night
Ancident
Moon
Spider
Invisible
Silver
Dark
Professor
Golden
Radioactive
Incredible
Impossible
Iron
Rocket
Power
Green
Super
Wonder
Metal
Doctor
Masked
Crimson
Omega
Lord
Sun
Lightning
Knight
Hulk
Centurion
Surfer
Warriors
Ghost
Hornet
Yellow Jacket
Moon
Ghost
Phantom
Machine
X
Doom
Z
Fist
Shadow
Claw
Torch
Soldier
Skull
Thunder
Hurricane
Falcon
Hawk
Any insight will be greatly appreciated. Thank you!
if filelist.index(i) is your issue. You are saying with this code: "Tell me the index of the item in this list that has the value moon". It's going to return 3 because moon first appears in that position.
Because of that and the fact that you are doing if/elif only the first if condition ever fires, setting the supe twice and never setting the hero.
Lastly because you declare hero as a global, it retains the last hero value from the previous call and instead getting a NULL hero/second-name you get the previous hero's second name.
Instead of iterating the file, you already have determined the index of the item you need for first and second name, so replace
for i in filelist:
global hero
if filelist.index(i) == first:
supe = i
supe = supe.strip()
elif filelist.index(i) == second:
hero = i
hero = hero.strip()
else:
pass
With
supe = filelist[first].strip()
hero = filelist[second].strip()
I am not sure where your code goes wrong. You can simplify your code a bit, to make it easier to figure out where it is wrong. Your two for loops are not needed, as you can index your lists instead. For example:
for k in alphabet:
if k == z[0]:
first = alphabet.index(k)
elif k == z[1]:
second = alphabet.index(k) + 26
else:
pass
Becomes
first = alphabet.index(z[0])
second = alphabet.index(z[1])
You don't need to loop through the alphabet as Z[i] always is part of the alphabet.
You can do something similar with your last loop.
Hope it helps.
Your function is overly complicated. Here are a couple mistakes I see:
for k in alphabet:
if k == z[0]:
first = alphabet.index(k)
elif k == z[1]:
second = alphabet.index(k) + 26
else:
pass
You can just use for index, k in enumerate(alphabet) and then use index instead of searching alphabet for the letter k. You already know the index, since that is the string you're iterating over!
However, you don't need that loop at all. You know what letter you're looking for, so you might as well just use
first = alphabet.index(z[0])
second = alphabet.index(z[1]) + 26
Same thing with for i in fileList: You already know the index of i since you iterate over fileList, so just use enumerate. HOWEVER, you don't need to do that here either: You know the indices you want, so just select them:
supe = filelist[first].strip()
hero = filelist[second].strip()
Consider the following simplified code:
def generate_name(filename, name):
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
z = [word[0].upper() for word in name.split(maxsplit=1)]
first = alphabet.index(z[0])
second = alphabet.index(z[1]) + 26
with open(filename, "r") as f:
filelist = f.readlines()
supe = filelist[first].strip()
hero = filelist[second].strip()
return supe + " " + hero
Changes I made:
I used a list comprehension to create z. This basically condenses your for i in j loop into a single line. I also convert the character to uppercase just to be safe
I specify maxsplit=1 in name.split because we only want two values.
I used with to handle closing the file after we're done with it. This is more pythonic than opening a file handle and explicitly closing it.
Some other notes:
You don't need to define alphabet: Getting the index of the first character of either name is easily done by subtracting its ASCII code (ord) from the ASCII code for "A". e.g: first = ord(z[0]) - ord("A")
You can use the f-string syntax to format the return value. return f"{supe} {hero}"

The program repeats until the input string is quit and disregards the integer input that follows

Write a program that takes a string and an integer as input, and outputs a sentence using the input values as shown in the example below. The program repeats until the input string is quit and disregards the integer input that follows.
Ex: If the input is:
apples 5
shoes 2
quit 0
the output is:
Eating 5 apples a day keeps the doctor away.
Eating 2 shoes a day keeps the doctor away.
This is what I've got so far:
string = input().split()
string2 = input().split()
string3 = input().split()
all_input = (string + string2 + string3)
for word in all_input:
while word != 'quit':
print('Eating {} {} a day keeps the doctor away.'.format(string[1] , string[0]))
print('Eating {} {} a day keeps the doctor away.'.format(string2[1], string2[0]))
string = input().split()
string2 = input().split()
string3 = input().split()
all_input = (string + string2 + string3)
I get the correct output but also receive this error:
Traceback (most recent call last):
File "main.py", line 11, in <module>
string = input().split()
EOFError: EOF when reading a line
And when it tests with the inputs:
cars 99
quit 0
Then I get no output. I feel like I need to use a break statement somewhere but nowhere I put it seems to work.
you are using input() multiple times where you can use it once inside a loop and if the input_string contains 'quit' it will be terminated. try the following code, it will continue taking input till the user enters quit
while True:
input_string = input()
if 'quit' in input_string:
break
else:
a,b = input_string.split(' ')
print(f'Eating {b} {a} a day keeps the doctor away.')
OR
if you want to take all inputs at once, then find the code below, it will work as you expected
input_string = []
while True:
line = input()
if 'quit' in line:
break
else:
input_string.append(line)
for line in input_string:
a,b = line.split(' ')
print(f'Eating {b} {a} a day keeps the doctor away.')
You can use a loop to achieve the same result, and you can use it too for files with more and less lines.
You can use 'quit' not in variable_name as the exit condition of the loop. When the variable you test is a substing, this statement will look for "quit" as a substring.
To split the words in the lines str.split() is your friend. After calling it, it returns an array. The first element of this array will be the object, and the second the number of elements.
mad_lib = input()
while 'quit' not in mad_lib:
MD_list = mad_lib.split()
thing = MD_list[0]
integer = MD_list[1]
print("Eating {} {} a day keeps the doctor away.".format(integer,thing))
# Read the input again to process more lines
mad_lib = input()
The main roadblock may be splitting the input first, as others noted. Additionally, do not think of this exercise as there will be a set number of strings. Strings can be 0 to infinity -- that will be left to the user (or computer) to decide. Once you str.split() and loop input before the loop and in the loop, you can KISS (keep it simple stupid) with a not in rather than using breaks. Sure, the breaks look as if you paid attention during your lessons in the chapter, though so far I have found breaks to be only needed under select circumstances (if at all?). If your instructor does not have requirements on what you need to use in your program, use the following (also seen in #Jamal McDaniel / #Iñigo González above).
user_input = input() #initial input
while 'quit' not in user_input:
choices = user_input.split() #split the string
word = choices[0]
integer = choices[1]
print("Eating {} {} a day keeps the doctor away.".format(integer, word))
user_input = input() #get another input and loop until 'quit'
I solved the problem using this code.
var1 = input() #takes in string(apples 5)
mad_lib = var1.split() #splits user input into two strings (apples, 5)
while 'quit' not in mad_lib: #loop that only stops when 'quit' is entered
print('Eating {} {} a day keeps the doctor away.'.format(mad_lib[1], mad_lib[0]))
var1 = input() #increments loop with new input(shoes 2)
mad_lib = var1.split() #splits new user input into two strings again (shoes, 2)

How to split a single line input string having Name(1 or more words) and Number into ["Name" , "Number"] in Python?

I am a newbie. I failed one of the test cases in a phone book problem. As per the question, a user is expected to enter a single line input which contains a name (which can be one or more words) followed by a number. I have to split the the input into ["name","number"] and store it in dictionary. Note that the name will have one or more words(Eg: John Conor Jr. or Apollo Creed). I am confused with the splitting part. I tried out the split() function and re.split(). Not sure I can solve this.
Sample input 1 : david james 93930000
Sample Input 2 : hshhs kskssk sshs 99383000
Output: num = {"david james" : "93930000", "hshhs kskssk sshs" : "99383000"}
I need to store it in a dictionary where the key:value is "david james": "93930000"
Please help. Thank you
=====>I found a solution<==========
if __name__ == '__main__':
N=int(input())
phonebook={}
(*name,num) = input().split()
name = ''.join(map(str,name)
phonebook.update({name:num})
print(phonebook)
The astrik method words. But for a large data set this might slow me down. Not sure.
So im assuming that the inputs stated are coming from a user, if that
is the case you could change the format in your code to something
similar to this. You can change the range depending on how many inputs you want.
name = {}
for i in range(5):
student_name = input("Enter student's name: ")
student_mark = input("Enter student's mark: ")
name[student_name.title()] = student_mark
print(marks)
This should print the results in the way you mentioned!
Please check for the updated answer if this is what you are looking
for.
# Sample text in a line...
# With a name surname and number
txt = "Tamer Jar 9000"
# We define a dictionary variable
name_dictionary = {}
# We make a list inorder to appened the name and surname to the list
name_with_surname = []
# We split the text and if we print it out it should look something like this
# "Tamer", "Jar", "9000"
# But you need the name and surname together so we do that below
x = txt.split()
# We take the first value of the split text which is "Tamer"
# And we take the second value of the split text us "Jar"
name = x[0]
surname = x[1]
# And here we append them to our list
name_with_surname.append(name + " " + surname)
#print(name_with_surname)
# Finally here to display the values in a dictionary format
# We take the value of the list which is "Tamer Jar" and the value of the number "9000"
name_dictionary[name_with_surname[0]] = x[2]
print(name_dictionary)
The above answers can't handle if a data has too many name parts in one line.
Try my code below.
You can just loop through whatever the total number of inputs you want.
phonebook = {}
total_inputs = int(input())
for i in range(total_inputs):
name_marks = input().split() # taking input and splitting them by spaces
name = " ".join(x for x in name_marks[:-1]) # extracting the name
marks = name_marks[-1] # extracting the marks
phonebook[name] = marks # storing the marks in the dictionary
This way you can store the marks for the name. It will handle even one input has many name parts.

picking a file and reading the words from it python

I need help with this, I'm a total beginner at python. my assignment is to create a program that has the user pick a category, then scramble words from a file that are in that category. I just want to figure out why this first part isn't working, the first part being the first of four different methods that run depending on which category the user picks.
print ("Instructions: Enter your chosen category, animals, places, names or colors.")
viewYourFile = input("Enter your category")
category = 'animals'
if category == 'animals':
animals = open('animals.txt')
next = animals.read(1)
while next != "":
animal1 = animals.read(1)
animal2 = animals.read(2)
animal3 = animals.read(3)
animal4 = animals.read(4)
animal5 = animals.read(5)
animalList = ['animal1', 'animal2', 'animal3', 'animal4', 'animal5']
chosenAnimal = random.choice(animalList)
animalLetters = list(chosenAnimal)
random.shuffle(animalLetters)
scrambledAnimal = ' '.join(animalLetters)
print(scrambledAnimal)
print("Enter the correct spelling of the word")
The first problem is that you're reading only 1-5 letters from the file.
Please read the (documentation)[https://docs.python.org/2/tutorial/inputoutput.html] on how the read function works. The number in parentheses is how many bytes you want to read.
You may want a simpler solution, such as reading the entire file and splitting it into words. This would look something like:
file_contents = animals.read()
animalList = file_contents.split()
If split is new to you, then (look up)[https://docs.python.org/2/library/string.html] that method as well.
The next problem is that you've set your animal list to literal strings, rather than the input values you read. I think you want the line to read:
animalList = [animal1, animal2, animal3, animal4, animal5]

User entering a sentence in an input and Python picking out keywords and getting it from CSV file

I have a task to create a code with a CSV file. I have to create a code and after I run it, the user must enter the answer in a sentence and Python must then pick out keywords from the sentence and cross-reference from the CSV file and give the user an answer.
I have created a code which asks:
Which game(s) would you like to know the price of?
The user must write an answer which could possibly say:
The games which I would like to know the prices of are: FarCry4 GTA 5
Python must then pick out the words FarCry4 and GTA5. It must then tell the price of the games after importing the CSV file but I can't do this because Python picks every word in Python and tells the price. Please help.
CODE:
import csv
games = []#subjects
howmuchitcosts = []#teachers
with open('gamesandprices.csv') as csvfile:
readCSV = csv.reader(csvfile)
for row in readCSV:
games.append(row[0])
howmuchitcosts.append(row[1])
what_game = input("Which game(s) would you like to find out the price of?: ")
what_game = what_game.split(' ')
if len(what_game) > 6:
print("Too many games. Only type in 6 games.")
for one_game in what_game:
theprice = []
gamedex = 0
while True:
try:
gamedex = games.index(one_game, gamedex)
except:
break
theprice.append(howmuchitcosts[gamedex])
gamedex += 1
theprice = ', '.join(theprice)
print("The price of", one_game, "is", theprice)
P.S: I used this code from another question which was asked in StackOverflow from another topic.
When I enter a sentence which is this:
I want to know the price of GTA5 and FarCry4
And when I press ENTER, this comes up:
Too many games. Only type in 6 games.
The price of I is
The price of want is
The price of to is
The price of know is
The price of the is
The price of price is
The price of of is
The price of GTA5 is £30.99
The price of and is
The price of FarCry4 is £40.99
But I want python to pick up only GTA5 and FarCry4 and tell the price of those games, not the whole sentence.
This is from another topic as he is working on the same code :)
Change the code that reads your csv to produce a dictionary, then simply lookup the word from the input. If the word is in the dictionary, it means you have a price for that game; and so only print the output then:
import csv
price_list = {} # this is an empty dictionary
with open('gamesandprices.csv') as csvfile:
readCSV = csv.reader(csvfile)
for row in readCSV:
price_list[row[0]] = row[1]
what_game = input("Which game(s) would you like to find out the price of?: ")
what_game = what_game.split(' ')
# Now what we want to do, is for each word in the input, check if it
# exists in our dictionary. If it does exist, it must be the name of
# a game, so we need to know its price.
# We also want to make sure we limit the number of games in one
# request to 6 games. To find out how many games the person entered,
# lets filter all the words and collect those words (and prices)
# that are games in a list.
# The long way of writing this is:
# results = [] - this is an empty list
# for word in what_game:
# if word in price_list:
# results.append(word, price_list[word])
results = [(game, price_list[game]) for game in what_game if game in price_list]
if len(results) > 6:
print('Please ask prices for a maximum of 6 games')
else:
for game, price in results:
print('The price of {} is {}'.format(game, price))

Categories

Resources