openpyxl first column is empty when using append method - python

I'm new to Python, and i'm programming a simple math question program. The user is prompted a math question, and the user have to type the correct answer. All of the questions, solutions and answers are saved to a local excel ark. That is the summary of my project, now comes the problem:
When i append resultsArr the question column is blank in the excel ark. When i print resultArr i get an array back with the question as the first index in the array.
So i get an array back with all of the values, but for some reason it doesn't accept the first index. I have tried to manually write a string in its place, and that works.
main.py - current version
from colors import colors
from mathQuestion import mathQuestion
from openpyxl import Workbook
gameResults = []
score = 0
def saveData(rows):
wb = Workbook()
ws = wb.active
ws.append(["Question", "Answer", "Solution"])
[ws.append(x) for x in rows]
wb.save("data.xlsx")
wb.close()
while True:
result = mathQuestion()
gameResults.append(
[result["question"], result["answer"], result["solution"]])
if(result["answer"] == result["solution"]):
score += 1
print(f"{colors.green}Correct{colors.default}, your current score: {colors.yellow+str(score)+colors.default}")
else:
print(colors.red+"Game Over"+colors.default)
break
saveData(gameResults)
mathQuestion.py
from random import randint
from colors import colors
def oddOrEven():
number = randint(1, 1000)
numberIsOdd = number % 2 != 0
question = f"Is {number} odd or even: "
if(numberIsOdd):
solution = "odd"
else:
solution = "even"
while True:
userInput = input(question)
if(userInput == "odd" or userInput == "even"):
return {
"answer": userInput,
"question": question,
"solution": solution
}
else:
print("Only odd or even")
def muliply():
a = randint(0, 10)
b = randint(0, 10)
question = f"What is {a} * {b}: "
solution = a*b
while True:
userInput = input(question)
try:
return {
"answer": int(userInput),
"question": question,
"solution": solution
}
except:
print("Only numbers are allowed")
mathFunctions = [
oddOrEven,
muliply
]
def mathQuestion():
return mathFunctions[randint(0, len(mathFunctions)-1)]()
Github repo

Related

Randomize questions from web API and print out wrong answer

I want to get 10 random questions from an web API with many questions, but I dont seem to get it to work. Right now im getting KeyError: 'prompt', but I dont know if the function is correct at all as I have been trying a few diffrent options.
Im also trying to print out in the end which questions you get wrong, but with no luck there either.
import random
import requests
from random import randint
url = ""
the_questions = requests.get(url).json()
print("------ Welcome to Python quiz ------")
def random_question():
data = the_questions['prompt']
random_index = randint(0, len(data)-1)
return data[random_index]['prompt']
def get_correct_answers(answers):
res = []
for ans in answers:
if ans['correct']:
res.append(ans['answer'])
return res
def get_numeric(prompt, max_value,):
while True:
try:
res = int(input(prompt))
except ValueError:
print("Answer only with a number!")
continue
if 0 < res < max_value:
break
else:
print("Invalid answer option!")
return res
def main():
score = 0
for questions in the_questions['questions']:
#print(questions['prompt'])
print(random_question())
for i, a in enumerate(questions['answers'], start=1):
print(f"[{i}] {a['answer']}")
user_answer = get_numeric("> ", len(questions['answers']) + 1)
if questions['answers'][user_answer - 1]['correct']:
score += 1
print(f"Right!")
else:
all_correct = ", ".join(get_correct_answers(questions['answers']))
print(f"Wrong, right is: {all_correct}")
print(f"You got {score} points of {len(the_questions['questions'])} possible!")
if __name__ == '__main__':
main()
Sample of the API
{"questions":[{"id":"1","prompt":"Which functions is used to write out text in the terminal?","answers":[{"answer":"print","correct":true},{"answer":"input","correct":false},{"answer":"import","correct":false},{"answer":"sys.exit","correct":false}]}
Error shows problem with key prompt and you use it only in random_question().
If you use print() to see values in variables random_question() then you will see that you need
data = the_questions['questions']
instead of
data = the_questions['prompt']
As for me name of variables are missleading. You should use name data for all information from API and later questions = data['questions'] could make sense.
EDIT:
My version with random.shuffle()
import random
#import requests
import json
def get_correct_answers(answers):
res = []
for ans in answers:
if ans['correct']:
res.append(ans['answer'])
return res
def get_numeric(prompt, max_value,):
while True:
try:
res = int(input(prompt))
except ValueError:
print("Answer only with a number!")
continue
if 0 < res < max_value:
break
else:
print("Invalid answer option!")
return res
def main():
print("------ Welcome to Python quiz ------")
#url = ""
#data = requests.get(url).json()
data = json.loads('''
{"questions":[
{"id":"1","prompt":"Which functions is used to write out text in the terminal?","answers":[{"answer":"print","correct":true},{"answer":"input","correct":false},{"answer":"import","correct":false},{"answer":"sys.exit","correct":false}]},
{"id":"2","prompt":"Which functions is used to read text from the terminal?","answers":[{"answer":"print","correct":false},{"answer":"input","correct":true},{"answer":"exec","correct":false},{"answer":"load","correct":false}]}
]}
''')
questions = data['questions']
random.shuffle(questions)
score = 0
for question in questions:
print(question['prompt'])
answers = question['answers']
for i, a in enumerate(question['answers'], 1):
print(f"[{i}] {a['answer']}")
user_answer = get_numeric("> ", len(answers)+1)
if answers[user_answer-1]['correct']:
score += 1
print(f"Right!")
else:
all_correct = ", ".join(get_correct_answers(answers))
print(f"Wrong, right is: {all_correct}")
print(f"You got {score} points of {len('questions')} possible!")
if __name__ == '__main__':
main()

Why does my IF statement not work on python?

import random
circlediameter = random.randint(1,99)
pi = 3.142
print("The circle diameter is",circlediameter," Find the area")
#find 4 possible answers
circleanswer1 = circlediameter/pi
circleanswer2 = circlediameter*pi
circleanswer3 = circlediameter+pi
circleanswer4 = circlediameter
#makes sure all numbers are integers
circleanswer1 = int(circleanswer1)
circleanswer2 = int(circleanswer2)
circleanswer3 = int(circleanswer3)
circleanswer4 = int(circleanswer4)
answerlist = [circleanswer1 , circleanswer2 , circleanswer3 , circleanswer4]
#shuffles the list
random.shuffle(answerlist)
#answer 2 is always the right answer
print("Four options are: ", answerlist)
#user enters a number
useranswercircle = input("Please choose an answer: ")
int(useranswercircle)
str(useranswercircle)
str(circleanswer2)
if useranswercircle == circleanswer2:
print("EEE")
I am comparing two integers, why is my IF statement not working when i
compare two numbers. I have converted the two variables into integers, and it still isn't comparing successfully
Try with this cast:
import random
circlediameter = random.randint(1,99)
pi = 3.142
print("The circle diameter is",circlediameter," Find the area")
#find 4 possible answers
circleanswer1 = circlediameter/pi
circleanswer2 = circlediameter*pi
circleanswer3 = circlediameter+pi
circleanswer4 = circlediameter
#makes sure all numbers are integers
circleanswer1 = int(circleanswer1)
circleanswer2 = int(circleanswer2)
circleanswer3 = int(circleanswer3)
circleanswer4 = int(circleanswer4)
answerlist = [circleanswer1 , circleanswer2 , circleanswer3 , circleanswer4]
#shuffles the list
random.shuffle(answerlist)
#answer 2 is always the right answer
print("Four options are: ", answerlist)
#user enters a number
useranswercircle = input("Please choose an answer: ")
# EDIT:
# HERE IS THE TRICK
useranswercircle = int(useranswercircle)
if useranswercircle == circleanswer2:
print("EEE")
You need to indent the print:
if useranswercircle == circleanswer2:
print("EEE")
Try like this -
if str(useranswercircle) == str(circleanswer2):
print("EEE")
And remove these two statements -
str(useranswercircle)
str(circleanswer2)

python: Adding to username

I am fairly new to python and I need to make a program to ask 10 questions, save the score into a file and allow someone to read the scores in from the file.
My problem: I need to check if the person who has done the quiz already has a record in the file, and if so, I need to add their score to the end of their record.
The records should look like this:
name,score,score,score,score,
etc so they can be split using commas.
I am also looking for the simplest answer, not the most efficient. Also, if you could comment the code, it would make it much easier. Here is my code so far:
import random
import math
import operator as op
import sys
import re
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, num1)
ops = {
'+': op.add,
'-': op.sub,
'*': op.mul,
}
keys = list(ops.keys())
rand_key = random.choice(keys)
operation = ops[rand_key]
correct_result = operation(num1, num2)
print ("What is {} {} {}?".format(num1, rand_key, num2))
while True:
try:
user_answer = int(input("Your answer: "))
except ValueError:
print("Only enter numbers!")
continue
else:
break
if user_answer != correct_result:
print ("Incorrect. The right answer is {}".format(correct_result))
return False
else:
print("Correct!")
return True
print("1. Are you a student?")
print("2. Are you a teacher?")
print("3. Exit")
while True:
try:
status = int(input("Please select an option:"))
except ValueError:
print("Please enter a number!")
else:
if status not in {1,2,3}:
print("Please enter a number in {1,2,3}!")
else:
break
if status == 1:
username=input("What is your name?")
while not re.match("^[A-Za-z ]*$", username) or username=="":
username=input(str("Please enter a valid name (it must not contain numbers or symbols)."))
print ("Hi {}! Wellcome to the Arithmetic quiz...".format(username))
while True:
try:
users_class = int(input("Which class are you in? (1,2 or 3)"))
except ValueError:
print("Please enter a number!")
else:
if users_class not in {1,2,3}:
print("Please enter a number in {1,2,3}!")
else:
break
correct_answers = 0
num_questions = 10
for i in range(num_questions):
if test():
correct_answers +=1
print("{}: You got {}/{} {} correct.".format(username, correct_answers, num_questions,
'question' if (correct_answers==1) else 'questions'))
if users_class == 1:
class1 = open("Class1.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class1.write(newRecord)
class1.close()
elif users_class == 2:
class2 = open("Class2.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class2.write(newRecord)
class2.close()
elif users_class == 3:
class3 = open("Class3.txt", "a+")
newRecord = username+ "," + str(correct_answers) + "," + "\n"
class3.write(newRecord)
class3.close()
else:
print("Sorry, we can not save your data as the class you entered is not valid.")
EDIT:
Add this function before your "test" function:
def writeUserScore(file, name, score):
with open (file, "r") as myfile:
s = myfile.read()
rows = s.split("\n")
data = {}
for row in rows:
tmp = row.split(",")
if len(tmp) >= 2: data[tmp[0]] = tmp[1:]
if name not in data:
data[name] = []
data[name].append(str(score))
output = ""
for name in data:
output = output + name + "," + ",".join(data[name]) + "\n"
handle = open(file, "w+")
handle.write(output)
handle.close()
After that, where you have "if users_class == 1:" do this:
writeUserScore("Class1.txt", username, str(correct_answers))
Do the same for the other two else ifs.
Let me know what you think!
Try using a dictionary to hold the existing file data.
Read the file in a variable called "str" for example. And then do something like this:
rows = str.split("\n")
data1 = {}
for row in rows:
tmp = row.split(",")
data1[tmp[0]] = tmp[1:]
When you have a new score you should then do:
if username not in data1:
data1[username] = []
data1[username] = str(correct_answers)
And to save the data back to the file:
output = ""
for name in data1:
output = outupt + name + "," + ",".join(data1[name]) | "\n"
And save the contents of "output" to the file.
PS: If you are not bound by the file format you can use a JSON file. I can tell you more about this if you wish.
Hope that helps,
Alex
First, define these functions:
from collections import defaultdict
def read_scores(users_class):
"""
If the score file for users_class does not exist, return an empty
defaultdict(list). If the score file does exist, read it in and return
it as a defaultdict(list). The keys of the dict are the user names,
and the values are lists of ints (the scores for each user)
"""
assert 0 <= users_class <= 3
result = defaultdict(list)
try:
lines =open("Class%d.txt"%users_class,'r').readlines()
except IOError:
return result
for line in lines:
# this line requires python3
user, *scores = line.strip().split(',')
# if you need to use python2, replace the above line
# with these two lines:
# line = line.strip().split(',')
# user, scores = line[0], line[1:]
result[user] = [int(s) for s in scores]
return result
def write_scores(users_class, all_scores):
"""
Write user scores to the appropriate file.
users_class is the class number, all scores is a dict kind of dict
returned by read_scores.
"""
f = open("Class%d.txt"%users_class,'w')
for user, scores in all_scores.items():
f.write("%s,%s\n"%(user, ','.join([str(s) for s in scores])))
def update_user_score(users_class, user_name, new_score):
"""
Update the appropriate score file for users_class.
Append new_score to user_name's existing scores. If the user has
no scores, a new record is created for them.
"""
scores = read_scores(users_class)
scores[user_name].append(new_score)
write_scores(users_class, scores)
Now, in the last portion of your code (where you actually write the scores out) becomes much simpler. Here's an example of writing some scores:
update_user_score(1, 'phil', 7)
update_user_score(1, 'phil', 6)
update_user_score(1, 'alice', 6)
update_user_score(1, 'phil', 9)
there will be two lines in Class1.txt:
phil,7,6,9
alice,6
We read the whole file into a dict (actually a defaultdict(list)),
and overwrite that same file with an updated dict. By using defaultdict(list), we don't have to worry about distinguishing between updating and adding a record.
Note also that we don't need separate if/elif cases to read/write the files. "Scores%d.txt"%users_class gives us the name of the file.

How can I modify this code so it doesn't go back to the beginning of the function, but a little bit after the beginning?

I'm working on a school project and I have a problem. I have to write code for apothecary where clients can buy medicine. So, I need to make restrictions, which one doesn't go with others and etc. Here is the code:
def prodajLek():
lekovi = Fajl1.UcitavanjeLekova()
lekoviRed = []
brojacZaForPetlju = 1
n = 0
cena = 0
kolicina = []
korpa = []
rednibrojevilekova = []
ukupnacena = 0
print(" Fabricki naziv Genericki naziv Serijski broj Kolicina Cena \n")
for i in lekovi:
x = i.strip().split("|")
lekoviRed.append(x)
if lekoviRed[n][5] == "False":
print(brojacZaForPetlju,"\t {:10} \t {:10} \t\t\t {:3} \t\t\t {:4} \t\t {:5}".format(x[0],x[1],x[2],x[3],x[4]))
brojacZaForPetlju = brojacZaForPetlju + 1
n = n + 1
print("\n\n\n\n")
rednibrleka = input("Izaberite redni broj leka koji zelite da prodate:\n>>\t")
rednibrleka = int(rednibrleka)
rednibrleka = rednibrleka - 1
rednibrojevilekova.append(rednibrleka)
kolicinaZahteva = input("Koju kolicinu zelite da prodate?\n>>\t")
kolicinaZahteva = int(kolicinaZahteva)
if kolicinaZahteva > int(lekoviRed[rednibrleka][3]):
print("Nema toliko na lageru!\n")
Fajl1.LekarMenu()
kolicina.append(kolicinaZahteva)
cena = int(lekoviRed[rednibrleka][4])
korpa.append(cena)
print("Da li zelite da kupite jos lekova?\n1.Da\n2.Ne\n")
nastavakKupovine = input(">>")
if nastavakKupovine == "1":
prodajLek()
elif nastavakKupovine == "2":
Fajl1.LekarMenu()
So, when I get to the nastavakKupovine input, when I press 1, I need to continue shopping and store my row numbers, my price and quantity in arrays rednibrojlekova = [] , korpa = [] and kolicina = []. But I have a problem, because I dont know how to continue this without reseting these arrays to empty.
The standard idiom for what you want to do is a while True loop. Rather than show how to change your (rather long) function, here's a very simple one which hopefully shows the principle in a straightforward way:
def ask():
answers = []
while True:
response = input("What do you have to say? ")
answers.append(response)
check = input("Type 'q' to quit, anything else to repeat: ")
if check == "q":
break
else:
continue
return answers
For this simple function, the else: continue part isn't necessary, because the loop will continue anyway, but I've included it so you can see how to use it.
Here's an example of the function in action:
>>> ask()
What do you have to say? Something
Type 'q' to quit, anything else to repeat:
What do you have to say? Another thing
Type 'q' to quit, anything else to repeat:
What do you have to say? Ok, done
Type 'q' to quit, anything else to repeat: q
['Something', 'Another thing', 'Ok, done']
>>>
You can find out more about while, break and continue by reading the More Control Flow Tools chapter of the official Python tutorial.

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Categories