Appending to lists, with variables. Python - python

I have made a math quiz(simple.asks 10 maths question to the user). I made the user take the quiz 3 times using a for loop, because i needed 3 scores for each student.I decided to store the 3 scores in a list HOWEVER because the variable "score" changes every time the for loop runs and every time the user does the quiz..i find it very difficult to append each score in the same list one after another.
I have read some other response to a similar question and the answer was the use of indexes, but i am not quiet sure how i could use them for my problem as i don't have a specific location in the list to add my 3 different scores, i need to add them one after another.
Here is the part in my code that i need to work on:
hscore = []
hscore.append(score)
print("This is hscore: ",hscore)
score = 0
I am sorry, this is my first time using this webiste so..i don't know how to present my code properly. But as you can see..i have my empty list which i want to append to. score is the variable that changes 3 times, and the print was just for me to check if it was working which it wasn't. Also every time the for loops runs again i had to set the score to 0, so the scores wouldn't get add up together.

You should declare all variables out side your loop, cause it looks like you're resetting score to 0.
And as a recommendation, try using a dictionary to better handle this kind of information.
Like this:
scores={}
scores[Name]=[]
## Your code block here
## or for loop
scores[Name].append(score)
print scores[Name]
scores will be able to hold the scores of each student with a list of their score. Hope that helps! :)

Related

How do I write the scores of my game into the leaderboard.txt and display the top 5 scores only with each player's name

I'm currently doing a dice game for my school programming project, and it includes the rules: 'Stores the winner’s score, and their name, in an external file' and 'Displays the score and player name of the top 5 winning scores from the external file.' I've done everything in my game apart from the leaderboard. I am able to write the name and score of the user into the txt file, but I am unsure of how to then sort it, and would also like when people first start the program can use the menu to go to the leaderboard where it would then read the txt file and print the top 5 scores in order including the names.
I've checked loads of over questions similar to mine, but none of them exactly worked for my code as I kept on getting errors implementing other people's code into mine which just weren't compatible with my layout.
(deleted)
Thanks in advance, I've never used stack overflow to ask a question so I apologize if there's anything I've done wrong in my post.
You did good on the question. You stated the problem clearly and, most importantly, you added enough code to run the code so we can have a look at how the program behaves and what's going wrong. In this case nothing is going wrong which is good :)
Considering you mention that this is a school project I will not give you a fully copy/paste solution but will explain hopefully enough details on how to solve this on your own.
Now according to the question, you don't know how to sort your leaderboard. I ran the program a few times myself (after removing the sleeps because I am impatient 😋) and see that your leaderboard file looks like this:
90 - somename
38 - anothername
48 - yetanothername
To display this you must do two things:
Open the file and read the data
Convert the data from the file into something usable by the program
The first step seems to be something you already know as you already use open() to write into the file. Reading is very similar.
The next step is not so obvious if you are new to programming. The file is read as text-data, and you need to sort it by numbers. For a computer the text "10" is not the same a the number 10 (note the quotes). You can try this by opening a Python shell:
>>> 10 == 10
True
>>> 10 == "10"
False
>>> "10" == 10
False
And text sorts differently to numbers. So you one piece of the solution is to convert the text into numbers.
You will also get the data as lines (either using readlines() or splitlines() depending on how you use it. These line need to be split into score and name. The pattern in the file is this:
<score> - <name>
It is important to notice that you have the text " - " as separator between the two (including spaces). Have a look at the Python functions str.split() and str.partition(). These functions can be applied to any text value:
>>> "hello.world".split(".")
['hello', 'world']
>>> "hello.world".partition(".")
('hello', '.', 'world')
You can use this to "cut" the line into multiple pieces.
After doing that you have to remember the previous point about converting text to numbers.
As a last step you will need to sort the values.
When reading from the file, you can load the converted data into a Python list, which can then be sorted.
A convenient solution is to create a list where each element of that list is a tuple with the fields (score, name). Like that you can directly sort the list without any arcane tricks.
And finally, after sorting it, you can print it to the screen.
In summary
Open the file
Read the data from the file as "lines"
Create a new, empty list.
Loop over each line and...
... split the line into multiple parts to get at the score and name separately
... convert the score into a number
... append the two values to the new list from point 3
Sort the list from point 3
Print out the list.
Some general thoughts
You can improve and simplify the code by using more functions
You already show that you know how to use functions. But look at the comments #THIS IS ROUND1 to #THIS IS ROUND5. The lines of code for each round are the same. By moving those lines into a function you will save a lot of code. And that has two benefits: You will only need to make a code-change (improvement or fix) in one place. And secondly, you guarantee that all blocks behave the same.
To do this, you need to think about what variables that block needs (those will be the new function arguments) and what the result will be (that will be the function return value).
A simple example with duplication:
print("round 1")
outcomes = []
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
outcomes.append("A")
else:
outcomes.append("B")
print("round 2")
outcome = ""
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
outcomes.append("A")
else:
outcomes.append("B")
Rewritten with functions
def run_round(round_name):
print(round_name)
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
return "A"
else:
return "B"
outcomes = []
result_1 = run_round("round 1")
outcomes.append(result_1)
result_2 = run_round("round 2")
outcomes.append(result_2)
As you can see, the second code is much shorter and has no more duplication. Your code will have more function arguments. It is generally a challenge in programming to organise your code in such a way that functions have few arguments and no complex return values. Although, as long as it works nobody will look too closely ;)
Safe way to ask for a password
You can use getpass() from the module getpass() to prompt for a password in a secure manner:
from getpass import getpass
password = getpass()
Note however, if you are using PyCharm, this causes some issues which are out of scope of this post. In that case, stick with input().
Sleeps
The "sleep()" calls are nice and give you the chance to follow the program, but make it slow to test the program. Consider to use smaller values (comma-values are possible), or, even better, write your own function that you can "short-circuit" for testing. Something like this:
import time
ENABLE_SLEEP = True
def sleep(s):
if ENABLE_SLEEP:
time.sleep(s)
print("some code")
sleep(1)
print("more code")
sleep(4)
You will then use your own sleep() function anytime you want to wait. That way, you can simply set the variable ENABLE_SLEEP to False and your code will run fast (for testing).

Python convert list into split lists

so I have been given the task of using an api to pull student records and learnerID's to put into an in house application. The json formatting is dreadful and the only successful way I managed to split students individually is by the last value.
Now I am at the next stumbling block, I need to split these student lists into smaller sections so I implement a for loop as so:
student = request.text.split('"SENMajorNeedsDetails"')
for students in student:
r = str(student).split(',')
print (student[0], student[1])
print (r[0], r[1])
This works perfectly except this puts it all into a single list again and each student record isn't a set length (some have more values/fields than others).
so what I am looking to do is have a list for each student split on the comma, so student1 would equal [learnerID,personID,name,etc...]
this way when I want to reference the learnerID I can call learner1[0]
It is also very possible that I am going about this the wrong way and I should be doing some other form of list comprehension
my step by step process that I am aiming towards is:
pull data from system - DONE
split data into individual students - DONE
take learnerID,name,group of each student and add database entry
I have split step 3 into two stages where one involves my issue above and the second is the create database records
Below is a shortended example of the list item student[0], followed by student[1] if more is needed then say
:null},{"LearnerId":XXXXXX,"PersonId":XXXXXX,"LearnerCode":"XXXX-XXXXXX","UPN":"XXXXXXXXXXX","ULN":"XXXXXXXXXX","Surname":"XXXXX","Forename":"XXXXX","LegalSurname":"XXXXX","LegalForename":"XXXXXX","DateOfBirth":"XX/XX/XXXX 00:00:00","Year":"XX","Course":"KS5","DateOfEntry":"XX/XX/XXXX 00:00:00","Gender":"X","RegGroup":"1XX",],
:null},{"LearnerId":YYYYYYY,"PersonId":YYYYYYYY,"LearnerCode":"XXXX-YYYYYYYY","UPN":"YYYYYYYYYY","ULN":"YYYYYYYYYY","Surname":"YYYYYYYY","Forename":"YYYYYY","LegalSurname":"YYYYYY","LegalForename":"YYYYYYY","DateOfBirth":"XX/XX/XXXX 00:00:00","Year":"XX","Course":"KS5","DateOfEntry":"XX/XX/XXXX 00:00:00","Gender":"X","RegGroup":"1YY",],
Sorry doesn't like putting it on seperate lines
EDIT* changed wording at the end and added a redacted student record
Just to clarify the resolution to my issue was to learn how to parse JSON propperly, this was pointed out by #Patrick Haugh and all credit should go to him for pointing me in the right direction. Second most helpful person was #ArndtJonasson
The problem was that I was manually trying to do the job of the JSON library and I am no where near that level of competency yet. As stated originally it was totally likely that I was going about it in completely the wrong way.

comparing list item integers python

I am writing a program which saves the last 3 scores in a text file for each user of my game. I have already written the code that saves it I am now bringing the data back into the program which will work out the users high scores . I also already have the scores saved in separate lists All users 1st score saved in 1 list all users 2nd score in another and the same for 3rd score. I am trying to put these in their own high score list so when I joint the lists with the names(in another list) I will be able to sort by score but will be attached to name.
Bellow is the code I have written:
for i in range (2):
if score1[i] > score2[i] or score1[i]> score3[i]:
highscores.append(score1[i])
elif score2[i] > score1[i] or score2[i] > score3[i]:
highscores.append(score2[i])
elif score3[i] > score1[i] or score3[i] > score2[i]:
highscores.append(score3[i])
By the way it is in a for loop for i in range 2 as their are currently only 2 users. I know I'm being incredibly stupid by having the or as it means only one event needs to be true for it to work but when I tried and it didn't work either. Please work along these lines as my tutor said 'I had the right idea' I also hope this helps anyone else which is comparing list items with integers in python as I couldn't find anything on the internet .
Thanks,
I await guidance
You want to use and, not or.
You can also use a < b < c syntax instead of using and.
What you should really do is use Python's built-in max function. A clean, single-liner instead of that 6-line if-elif block.
highscores.append(max(score1[i], score2[i], score3[i]))
Probably not allowed for this assignment, but for others who need to do something similar, the easy/fast way to select the top 3 values from a large sequence of values is to use heapq.nlargest. If you have multiple sequences, you can itertools.chain them to avoid concatenating (avoid increases in peak memory usage). You can even attach the names (with zip and itertools.repeat) to each input sequence so the selected high scores include the associated user:
from heapq import nlargest
from itertools import chain, repeat
highscores = nlargest(3, chain(zip(score1, repeat('user1')),
zip(score2, repeat('user2')),
zip(score3, repeat('user3'))))
highscores would then be a list with three elements (from highest to lowest score, ties broken by user name), each element being a tuple of the form (score, username).

Python Lists/ Tuples in terms of sorting

I am struggling to overcome a problem/task in Python and I'm really stuck for ideas. I need to read two lines from a file, sort one of these lines (from multiple files which are determined from user inputted data) but return both pieces of data in the context of a running club. The users average miles per hour will be calculated over a few weeks and stored in a .txt file alongside a user id stored at the beginning of the program, the final section of the program will need to read these files (the user id and the average miles per hour) and sort the average miles per hour while keeping the user id (returns both together allowing for a summary). I then need to state the top few runners. Any help would be much appreciated and I have not used SQL etc, just line-by-line, standard Python. My code is un-optimized but I'm at 'the home straight' with it now. Also, my friend suggested for me to use tuples but I don't know where to start in all honesty. Please excuse any 'elementary mistakes'. I have also played with tuples but never properly integrated them as I don't know where to begin. Also finding problems with the saving of variables as the clash with the operators which means I cannot globalize them without defining each and everyone.
def retrieve():
global datasave,y ###don't know where to go from this as it does not work
y=1
if y>3: #just practiced with 2 'users'
y=str(y)
print("All members entered and saved, a comparision of average miles per hour will be intiated")
file=open(y+".txt",'r') #saves files in which they occur for easy 'read'
datasave=file.readline(5)
datasave,y=datasave #gave me a 'cannot assign to operator' error
y=int(y)
y=y+1
else:
avmphlist=[datasave1,datasave2,datasave3,datasave4,datasave5,datasave6,datasave7,datasave8,datasave9,datasave10]
sorted(avmphlist)
print(avmphlist)
print("Unfortunately ",avmphlist[9]," and ",avmphlist[10],"have not made the team, thank you for your participation")
print("Congratulations to ",avmphlist[1],", ",avmphlist[2],", ",avmphlist[3],", ",avmphlist[4],", ",avmphlist[5],", ",avmphlist[6],", ",avmphlist[7]," and ",avmphlist[8],)
start with defining a list of tuples for you data
runnerData = [("TestName1", 70),("TestName2", 50), ("TestName3", 60)]
now use the inbuild sort method:
sortedRunnerData = sorted(runnerData, key=lambda data: data[1])
Now you have a sorted list of tuples of your data (ascending). If you need it in descending order just reverse the list:
sortedRunnerData.reverse()
Now the list sortedRunnerData list contains the data in descending order.

Error in selecting random item from Dictionary in python

I wan't to create a program that select 2 random items from two different dictionaries. Now I wan't to check if the sum of those items is equal to the value provided by the User. And i wan't to perform this action until i find 2 random items from different dictionaries that add up to the number entered by the User.
Here is what i tried to do:
import random
credit=int(raw_input("Please enter your amount: "))
food=dict([(10, 'Lays'), (10,'Pepsi'), (10,'Burger')])
toys=dict([(10, 'Car'), (10,'Train'), (10,'Chess')])
ranf=random.choice(food.keys())
rant=random.choice(toys.keys())
while int(ranf)+int(rant)!=credit:
ranf=random.choice(food.keys())
rant=random.choice(toys.keys())
print(ranf)
print(food[ranf])
print(rant)
print(food[rant])
When i try to run this code it fails to print those two random items. I'm not getting any error message. Please run this code and help me out.
Thank You
The problem lies within the fact, that you create your dictionaries with duplicate keys - effectively, your food dictionary contains only (10,'Burger') and your toys dictionary has only (10,'Chess') item (they both contain only most recently added item, which replaced all the previous ones). The simplest and quickest fix would be to abandon the usage of a dictionary:
import random
credit=20
food=[(10, 'Lays'), (10,'Pepsi'), (10,'Burger')]
toys=[(10, 'Car'), (10,'Train'), (10,'Chess')]
ranf=random.choice(food)
rant=random.choice(toys)
while int(ranf[0])+int(rant[0])!=credit:
ranf=random.choice(food)
rant=random.choice(toys)
print(ranf)
print(rant)
food.keys() only returns unique keys. So, essentially the only list of keys returned by the food.keys() function is [10].
ex if you make a dictionary like food = dict([(10, 'Lays'), (15,'Pepsi'), (15,'Burger')])
then the list returned by food.keys() will be [10,15] and not [10,15,15] which is what you expect. So, in your code, if ranf = 10, then interpreter takes up the latest value assigned to that key.
Therefore, the random.choice() you are using goes in vain.
Also, there is a silly mistake in your code, you wrote print(food[rant]) instead of writing print(toys[rant]).
It would be better if you don't use a list, otherwise, make the keys different.

Categories

Resources