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).
Related
I am relatively new to Python. However, my needs generally only involve simple string manipulation of rigidly formatted data files. I have a specific situation that I have scoured the web trying to solve and have come up blank.
This is the situation. I have a simple list of two-part entires, formatted like this:
name = ['PAUL;25', 'MARY;60', 'PAUL;40', 'NEIL;50', 'MARY;55', 'HELEN;25', ...]
And, I need to keep only one instance of any repeated name (ignoring the number to the right of the ' ; '), keeping only the entry with the highest number, along with that highest value still attached. So the answer would look like this:
ans = ['MARY;60', 'PAUL;40', 'HELEN;25', 'NEIL;50, ...]
The order of the elements in the list is irrelevant, but the format of the ans list entries must remain the same.
I can probably figure out a way to brute force it. I have looked at 2D lists, sets, tuples, etc. But, I can't seem to find the answer. The name list has about a million entries, so I need something that is efficient. I am sure it will be painfully easy for some of you.
Thanks for any input you can provide.
Cheers.
alkemyst
Probably the best data structure for this would be a dictionary, with the entries split up (and converted to integer) and later re-joined.
Something like this:
max_score = {}
for n in name:
person, score_str = n.split(';')
score = int(score_str)
if person not in max_score or max_score[person] < score:
max_score[person] = score
ans = [
'%s;%s' % (person, score)
for person, score in max_score.items()
]
This is a fairly common structure for many functions and programs: first convert the input to an internal representation (in this case, split and convert to integer), then do the logic or calculation (in this case, uniqueness and maximum), then convert to the required output representation (in this case, string separated with ;).
In terms of efficiency, this code looks at each input item once, then at each output item once; there's unlikely to be any approach that can do better than that (certainly not formally, and likely not in practice). All of the per-item operations are constant-time and fast. It accumulates the intermediate answer in memory (in max_score), but again that is unavoidable; if memory is an issue, the input and output could be changed to iterators/generators, but the whole intermediate answer has to be accumulated in max_score before any items can be output.
This is my first post, please be gentle. I'm attempting to sort some
files into ascending and descending order. Once I have sorted a file, I am storing it in a list which is assigned to a variable. The user is then to choose a file and search for an item. I get an error message....
TypeError: unorderable types; int() < list()
.....when ever I try to search for an item using the variable of my sorted list, the error occurs on line 27 of my code. From research, I know that an int and list cannot be compared, but I cant for the life of me think how else to search a large (600) list for an item.
At the moment I'm just playing around with binary search to get used to it.
Any suggestions would be appreciated.
year = []
with open("Year_1.txt") as file:
for line in file:
line = line.strip()
year.append(line)
def selectionSort(alist):
for fillslot in range(len(alist)-1,0,-1):
positionOfMax=0
for location in range(1,fillslot+1):
if alist[location]>alist[positionOfMax]:
positionOfMax = location
temp = alist[fillslot]
alist[fillslot] = alist[positionOfMax]
alist[positionOfMax] = temp
def binarySearch(alist, item):
first = 0
last = len(alist)-1
found = False
while first<=last and not found:
midpoint = (first + last)//2
if alist[midpoint] == item:
found = True
else:
if item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return found
selectionSort(year)
testlist = []
testlist.append(year)
print(binarySearch(testlist, 2014))
Year_1.txt file consists of 600 items, all years in the format of 2016.
They are listed in descending order and start at 2017, down to 2013. Hope that makes sense.
Is there some reason you're not using the Python: bisect module?
Something like:
import bisect
sorted_year = list()
for each in year:
bisect.insort(sorted_year, each)
... is sufficient to create the sorted list. Then you can search it using functions such as those in the documentation.
(Actually you could just use year.sort() to sort the list in-place ... bisect.insort() might be marginally more efficient for building the list from the input stream in lieu of your call to year.append() ... but my point about using the `bisect module remains).
Also note that 600 items is trivial for modern computing platforms. Even 6,000 won't take but a few milliseconds. On my laptop sorting 600,000 random integers takes about 180ms and similar sized strings still takes under 200ms.
So you're probably not gaining anything by sorting this list in this application at that data scale.
On the other hand Python also includes a number of modules in its standard libraries for managing structured data and data files. For example you could use Python: SQLite3.
Using this you'd use standard SQL DDL (data definition language) to describe your data structure and schema, SQL DML (data manipulation language: INSERT, UPDATE, and DELETE statements) to manage the contents of the data and SQL queries to fetch data from it. Your data can be returned sorted on any column and any mixture of ascending and descending on any number of columns with the standard SQL ORDER BY clauses and you can add indexes to your schema to ensure that the data is stored in a manner to enable efficient querying and traversal (table scans) in any order on any key(s) you choose.
Because Python includes SQLite in its standard libraries, and because SQLite provides SQL client/server semantics over simple local files ... there's almost no downside to using it for structured data. It's not like you have to install and maintain additional software, servers, handle network connections to a remote database server nor any of that.
I'm going to walk through some steps before getting to the answer.
You need to post a [mcve]. Instead of telling us to read from "Year1.txt", which we don't have, you need to put the list itself in the code. Do you NEED 600 entries to get the error in your code? No. This is sufficient:
year = ["2001", "2002", "2003"]
If you really need 600 entries, then provide them. Either post the actual data, or
year = [str(x) for x in range(2017-600, 2017)]
The code you post needs to be Cut, Paste, Boom - reproduces the error on my computer just like that.
selectionSort is completely irrelevant to the question, so delete it from the question entirely. In fact, since you say the input was already sorted, I'm not sure what selectionSort is actually supposed to do in your code, either. :)
Next you say testlist = [].append(year). USE YOUR DEBUGGER before you ask here. Simply looking at the value in your variable would have made a problem obvious.
How to append list to second list (concatenate lists)
Fixing that means you now have a list of things to search. Before you were searching a list to see if 2014 matched the one thing in there, which was a complete list of all the years.
Now we get into binarySearch. If you look at the variables, you see you are comparing the integer 2014 with some string, maybe "1716", and the answer to that is useless, if it even lets you do that (I have python 2.7 so I am not sure exactly what you get there). But the point is you can't find the integer 2014 in a list of strings, so it will always return False.
If you don't have a debugger, then you can place strategic print statements like
print ("debug info: binarySearch comparing ", item, alist[midpoint])
Now here, what VBB said in comments worked for me, after I fixed the other problems. If you are searching for something that isn't even in the list, and expecting True, that's wrong. Searching for "2014" returns True, if you provide the correct list to search. Alternatively, you could force it to string and then search for it. You could force all the years to int during the input phase. But the int 2014 is not the same as the string "2014".
I have two lists, pPop and sPop. sPop is pPop after being sorted in ascending numerical order (they're populations of towns/cities).
I also have four other lists, pName, pType, pLat, and pLong, but I'm not really doing anything with them at this point in time.
I need to sort this list of cities by ascending population size, and I basically have been told to do it using what I know currently - which isn't that much. I've tried this using tuples and other stuff, but those fall under things I haven't been taught.
I have to compare sPop to pPop and use the information I get from that to reorder the other four lists, so I can spit them out in a .csv file.
I get the idea, I'm just not sure of the execution. I think I need to run a loop over all of sPop, with a loop inside that running for all pPop, which checks if sPop[x] = pPop[y], (x from 0 to len(sPop)) giving some kind of affirmative response when it's true. If it's true, then set pVar[y] equal to sVar[x].
After writing this out it seems fine, I'm just not entirely sure how to loop for every index in python. When I do, say,
for x in sPop
it's
x = sPop[i] i=range(0:len(sPop))
when I'd prefer x to refer to the index itself, not the value of the array/list at that index.
Short version: loop over indices in an array with
for x in array
where x refers to the index. How do? If you can't, best way to refer to the index within a loop? It's late and my brain is fried on this problem after spending about six hours trying to work this out a few days ago using different methods.
EDIT:
Alright, got it. For anyone who is somehow curious (maybe someone'll stumble across this one in five years), you loop over sPop, then over pPop, (use
for indexX, varX in enumerate(list) twice) then use
if varX ==varY
sortedList.append(initialList[varY])
Can't put down the actual code or I'd probably get smacked with a plagiarism checker.
To get the index:
for index, x in enumerate(sPop):
print index, x
for x in range(len(sPop)):
item = sPop[x]
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.
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! :)