Asking how to sort in a csv being repeated - sorting

I have a quiz with results that are sorted into a .csv file, after the questions are answered it asks the user if the results should be sorted alphabetically or by highest to lowest. This question is then repeated no matter the answer entered, however if highest to lowest is entered a few times after alphabetically it works.
print ("Would you like to see the results alphabetically or by highest to lowest?")
alpha = input()
while alpha != "alphabetically":
alpha = str(input ("Would you like to see the results alphabetically or by highest to lowest? "))
break
while alpha != "highest to lowest":
alpha = str(input ("Would you like to see the results alphabetically or by highest to lowest? "))
break
def updatefile(file,sortby,Classnumber): #this shortens the code by about 3 lines per file update
if Class == Classnumber:
with open(file,'a') as f:
file_writer = csv.writer(f, delimiter = ',', lineterminator='\n')
file_writer.writerow((name,score))
sortcsv(file,sortby)
if alpha == "alphabetically":
updatefile('Class 1 Results.csv',0,"1") #saves space using shortened code, makes the code use alphabetical sorting
updatefile('Class 2 Results.csv',0,"2")
updatefile('Class 3 Results.csv',0,"3")
elif alpha == "highest to lowest":
updatefile('Class 1 Results.csv',1,"1") #makes the code use highest to lowest sorting
updatefile('Class 2 Results.csv',1,"2")
updatefile('Class 3 Results.csv',1,"3")

Ok, let's step through that input block and see what's going on.
print ("Would you like to see the results alphabetically or by highest to lowest?")
alpha = input()
Ok so far, but it's puzzling why you printed the prompt this time, and put it in the input() statement the rest.
while alpha != "alphabetically":
alpha = str(input ("Would you like to see the results alphabetically or by highest to lowest? "))
Now if the user didn't enter "alphabetically" at the first prompt, they will be prompted over and over until they do. That's probably not what you're going for. (Also, you don't need str() around input().)
while alpha != "highest to lowest":
highesttolowest = str(input ("Would you like to see the results alphabetically or by highest to lowest? "))
break
Now that your user finally entered "alphabetically", you prompt them again (since "alphabetically" != "highest to lowest"). Two major problems here, though. First, the unconditional break renders the while loop pointless, as it will always exit after one loop. Second, you're assigning the input to a new variable highesttolowest, but later on you're still testing against alpha, so the results of this prompt won't ever be checked.
The simpest way to do what you seem to want to be doing is to use membership testing to check for both conditions at the same time. Replace that whole block with:
alpha = ''
while alpha not in ("alphabetically", "highest to lowest"):
alpha = input("Would you like to see the results alphabetically or by highest to lowest? ")

Related

Input to different attributes values from a random.sample list

so this is what I'm trying to do, and I'm not sure how cause I'm new to python. I've searched for a few options and I'm not sure why this doesn't work.
So I have 6 different nodes, in maya, called aiSwitch. I need to generate random different numbers from 0 to 6 and input that value in the aiSiwtch*.index.
In short the result should be
aiSwitch1.index = (random number from 0 to 5)
aiSwitch2.index = (another random number from 0 to 5 different than the one before)
And so on unil aiSwitch6.index
I tried the following:
import maya.cmds as mc
import random
allswtich = mc.ls('aiSwitch*')
for i in allswitch:
print i
S = range(0,6)
print S
shuffle = random.sample(S, len(S))
print shuffle
for w in shuffle:
print w
mc.setAttr(i + '.index', w)
This is the result I get from the prints:
aiSwitch1 <-- from print i
[0,1,2,3,4,5] <--- from print S
[2,3,5,4,0,1] <--- from print Shuffle (random.sample results)
2
3
5
4
0
1 <--- from print w, every separated item in the random.sample list.
Now, this happens for every aiSwitch, cause it's in a loop of course. And the random numbers are always a different list cause it happens every time the loop runs.
So where is the problem then?
aiSwitch1.index = 1
And all the other aiSwitch*.index always take only the last item in the list but the time I get to do the setAttr. It seems to be that w is retaining the last value of the for loop. I don't quite understand how to
Get a random value from 0 to 5
Input that value in aiSwitch1.index
Get another random value from 0 to 6 different to the one before
Input that value in aiSwitch2.index
Repeat until aiSwitch5.index.
I did get it to work with the following form:
allSwitch = mc.ls('aiSwitch')
for i in allSwitch:
mc.setAttr(i + '.index', random.uniform(0,5))
This gave a random number from 0 to 5 to all aiSwitch*.index, but some of them repeat. I think this works cause the value is being generated every time the loop runs, hence setting the attribute with a random number. But the numbers repeat and I was trying to avoid that. I also tried a shuffle but failed to get any values from it.
My main mistake seems to be that I'm generating a list and sampling it, but I'm failing to assign every different item from that list to different aiSwitch*.index nodes. And I'm running out of ideas for this.
Any clues would be greatly appreciated.
Thanks.
Jonathan.
Here is a somewhat Pythonic way: shuffle the list of indices, then iterate over it using zip (which is useful for iterating over structures in parallel, which is what you need to do here):
import random
index = list(range(6))
random.shuffle(index)
allSwitch = mc.ls('aiSwitch*')
for i,j in zip(allSwitch,index):
mc.setAttr(i + '.index', j)

Printing in while loop, clearing previous iteration prints

I have the following code:
print("Hi there!")
def inputyournumber():
while True:
num = input("your number is?:")
if int(num) <100:
break
return
The output is:
Hi there!
your number is?: 101
your number is?: 1002
your number is?: 100
your number is?: 99
i just want the initial prints: and the final output until a correct input is entered:
Hi there!
your number is?: 99
Erasing the initially wrong inputs, but keeping the prints prior the loop. Is it possible? Or do i have to reprint them? My issue in just clearing everything then reprint the prior texts together with the correct input is that it may consume more time for more complex part of the code with similar problem.
Do you mean it only print out the number you entered when the number you enter is 100?
First, the input you get, will be a string, so the comparison won't work.
maybe this is what you wanted?
def printnum():
while True:
print('Hi there!')
num = input("your number is: ")
if num != '100':
continue
break
print(num)
printnum()

Sorting multiple columns from a CSV file in Python

I am a secondary school teacher attempting to find an appropriate way to teach KS4 pupils techniques that will allow them to write data to a CSV file and then read that same data from a file and display it back in Python in an organised structure.
Pupils and I have a clear understanding of how to write the data to the file however in terms of getting the data from the file into Python and then sorting it is becoming rather tricky and complex to explain.
I've created a program that allows the user to input their name followed by 3 separate numbers all of which get written to the CSV file in the format shown below...
James , 3 , 7 , 4
David , 5 , 5 , 9
Steven , 8 , 3 , 9
These results are saved in a file "7G1.csv"
So far I have a functioning program that sorts alphabetically, highest to lowest and by average highest to lowest. I have been able to establish through research and piecing together techniques from numerous sources the following program but can anybody suggest an easier more efficient approach that could be understood by 16 year olds.
import csv
G1 = open('7G1.csv')
csv_G1 = csv.reader(G1)
list7G1 = []
for column in csv_G1:
column[1] = int(column[1])
column[2] = int(column[2])
column[3] = int(column[3])
minimum = min(column[1:4])
column.append(minimum)
maximum = max(column[1:4])
column.append(maximum)
average = round(sum(column[1:4])/3)
column.append(average)
list7G1.append(column[0:7])
group_menu = 0
while group_menu != 4:
group_menu = int(input("Which group / class do you want to look at?\n1.7G1?\n2.7G2?\n3.7G3?\n4.Quit? "))
if group_menu == 1:
print ("You have chosen to focus on group 7G1.")
menu = int(input("\nDo you want to...\n1.Sort Alphabetically?\n2.Sort Highest to Lowest?\n3.Sort Average Highest to Lowest?\n4.Exit Group? "))
while menu != 4:
if menu == 1:
print("You have chosen to Sort Alphabetically...")
namesList = [[x[0], x[5]] for x in list7G1]
print("\nSorted Alphabetically with Highest Scores \n")
for names in sorted(namesList):
print (names)
elif menu == 2:
print("You have chosen to Sort Highest to Lowest...")
highestScore = [[x[5], x[0]] for x in list7G1]
print("\nScores Highest to Lowest \n")
for hightolow in sorted(highestScore, reverse = True):
print (hightolow)
elif menu == 3:
print("You have chosen to Sort Average Highest to Lowest")
averageScore = [[x[6], x[0]] for x in list7G1]
print("\nAverage Scores \n")
for average in sorted(averageScore, reverse = True):
print(average)
elif menu == 4:
print("You have chosen to exit this group")
else:
print("This is not a valid option")
menu = int(input("\nDo you want to...\n1.Sort Alphabetically?\n2.Sort Highest to Lowest?\n3.Sort Average Highest to Lowest?\n4.Exit Group? "))
Any suggestions on how to simplify this program would be hugely appreciated.

Python Birthday paradox math not working

it run corectly but it should have around 500 matches but it only has around 50 and I dont know why!
This is a probelm for my comsci class that I am having isues with
we had to make a function that checks a list for duplication I got that part but then we had to apply it to the birthday paradox( more info here http://en.wikipedia.org/wiki/Birthday_problem) thats where I am runing into problem because my teacher said that the total number of times should be around 500 or 50% but for me its only going around 50-70 times or 5%
duplicateNumber=0
import random
def has_duplicates(listToCheck):
for i in listToCheck:
x=listToCheck.index(i)
del listToCheck[x]
if i in listToCheck:
return True
else:
return False
listA=[1,2,3,4]
listB=[1,2,3,1]
#print has_duplicates(listA)
#print has_duplicates(listB)
for i in range(0,1000):
birthdayList=[]
for i in range(0,23):
birthday=random.randint(1,365)
birthdayList.append(birthday)
x= has_duplicates(birthdayList)
if x==True:
duplicateNumber+=1
else:
pass
print "after 1000 simulations with 23 students there were", duplicateNumber,"simulations with atleast one match. The approximate probibilatiy is", round(((duplicateNumber/1000)*100),3),"%"
This code gave me a result in line with what you were expecting:
import random
duplicateNumber=0
def has_duplicates(listToCheck):
number_set = set(listToCheck)
if len(number_set) is not len(listToCheck):
return True
else:
return False
for i in range(0,1000):
birthdayList=[]
for j in range(0,23):
birthday=random.randint(1,365)
birthdayList.append(birthday)
x = has_duplicates(birthdayList)
if x==True:
duplicateNumber+=1
print "after 1000 simulations with 23 students there were", duplicateNumber,"simulations with atleast one match. The approximate probibilatiy is", round(((duplicateNumber/1000.0)*100),3),"%"
The first change I made was tidying up the indices you were using in those nested for loops. You'll see I changed the second one to j, as they were previously bot i.
The big one, though, was to the has_duplicates function. The basic principle here is that creating a set out of the incoming list gets the unique values in the list. By comparing the number of items in the number_set to the number in listToCheck we can judge whether there are any duplicates or not.
Here is what you are looking for. As this is not standard practice (to just throw code at a new user), I apologize if this offends any other users. However, I believe showing the OP a correct way to write a program should be could all do us a favor if said user keeps the lack of documentation further on in his career.
Thus, please take a careful look at the code, and fill in the blanks. Look up the python doumentation (as dry as it is), and try to understand the things that you don't get right away. Even if you understand something just by the name, it would still be wise to see what is actually happening when some built-in method is being used.
Last, but not least, take a look at this code, and take a look at your code. Note the differences, and keep trying to write your code from scratch (without looking at mine), and if it messes up, see where you went wrong, and start over. This sort of practice is key if you wish to succeed later on in programming!
def same_birthdays():
import random
'''
This is a program that does ________. It is really important
that we tell readers of this code what it does, so that the
reader doesn't have to piece all of the puzzles together,
while the key is right there, in the mind of the programmer.
'''
count = 0
#Count is going to store the number of times that we have the same birthdays
timesToRun = 1000 #timesToRun should probably be in a parameter
#timesToRun is clearly defined in its name as well. Further elaboration
#on its purpose is not necessary.
for i in range(0,timesToRun):
birthdayList = []
for j in range(0,23):
random_birthday = random.randint(1,365)
birthdayList.append(random_birthday)
birthdayList = sorted(birthdayList) #sorting for easier matching
#If we really want to, we could provide a check in the above nester
#for loop to check right away if there is a duplicate.
#But again, we are here
for j in range(0, len(birthdayList)-1):
if (birthdayList[j] == birthdayList[j+1]):
count+=1
break #leaving this nested for-loop
return count
If you wish to find the percent, then get rid of the above return statement and add:
return (count/timesToRun)
Here's a solution that doesn't use set(). It also takes a different approach with the array so that each index represents a day of the year. I also removed the hasDuplicate() function.
import random
sim_total=0
birthdayList=[]
#initialize an array of 0's representing each calendar day
for i in range(365):
birthdayList.append(0)
for i in range(0,1000):
first_dup=True
for n in range(365):
birthdayList[n]=0
for b in range(0, 23):
r = random.randint(0,364)
birthdayList[r]+=1
if (birthdayList[r] > 1) and (first_dup==True):
sim_total+=1
first_dup=False
avg = float(sim_total) / 1000 * 100
print "after 1000 simulations with 23 students there were", sim_total,"simulations with atleast one duplicate. The approximate problibility is", round(avg,3),"%"

Algorithm to create unique random concatenation of items

I'm thinking about an algorithm that will create X most unique concatenations of Y parts, where each part can be one of several items. For example 3 parts:
part #1: 0,1,2
part #2: a,b,c
part #3: x,y,z
And the (random, one case of some possibilities) result of 5 concatenations:
0ax
1by
2cz
0bz (note that '0by' would be "less unique " than '0bz' because 'by' already was)
2ay (note that 'a' didn't after '2' jet, and 'y' didn't after 'a' jet)
Simple BAD results for next concatenation:
1cy ('c' wasn't after 1, 'y' wasn't after 'c', BUT '1'-'y' already was as first-last
Simple GOOD next result would be:
0cy ('c' wasn't after '0', 'y' wasn't after 'c', and '0'-'y' wasn't as first-last part)
1az
1cx
I know that this solution limit possible results, but when all full unique possibilities will gone, algorithm should continue and try to keep most avaible uniqueness (repeating as few as possible).
Consider real example:
Boy/Girl/Martin
bought/stole/get
bottle/milk/water
And I want results like:
Boy get milk
Martin stole bottle
Girl bought water
Boy bought bottle (not water, because of 'bought+water' and not milk, because of 'Boy+milk')
Maybe start with a tree of all combinations, but how to select most unique trees first?
Edit: According to this sample data, we can see, that creation of fully unique results for 4 words * 3 possibilities, provide us only 3 results:
Martin stole a bootle
Boy bought an milk
He get hard water
But, there can be more results requested. So, 4. result should be most-available-uniqueness like Martin bought hard milk, not Martin stole a water
Edit: Some start for a solution ?
Imagine each part as a barrel, wich can be rotated, and last item goes as first when rotates down, first goes as last when rotating up. Now, set barells like this:
Martin|stole |a |bootle
Boy |bought|an |milk
He |get |hard|water
Now, write sentences as We see, and rotate first barell UP once, second twice, third three and so on. We get sentences (note that third barell did one full rotation):
Boy |get |a |milk
He |stole |an |water
Martin|bought|hard|bootle
And we get next solutions. We can do process one more time to get more solutions:
He |bought|a |water
Martin|get |an |bootle
Boy |stole |hard|milk
The problem is that first barrel will be connected with last, because rotating parallel.
I'm wondering if that will be more uniqe if i rotate last barrel one more time in last solution (but the i provide other connections like an-water - but this will be repeated only 2 times, not 3 times like now). Don't know that "barrels" are good way ofthinking here.
I think that we should first found a definition for uniqueness
For example, what is changing uniqueness to drop ? If we use word that was already used ? Do repeating 2 words close to each other is less uniqe that repeating a word in some gap of other words ? So, this problem can be subjective.
But I think that in lot of sequences, each word should be used similar times (like selecting word randomly and removing from a set, and after getting all words refresh all options that they can be obtained next time) - this is easy to do.
But, even if we get each words similar number od times, we should do something to do-not-repeat-connections between words. I think, that more uniqe is repeating words far from each other, not next to each other.
Anytime you need a new concatenation, just generate a completely random one, calculate it's fitness, and then either accept that concatenation or reject it (probabilistically, that is).
const C = 1.0
function CreateGoodConcatenation()
{
for (rejectionCount = 0; ; rejectionCount++)
{
candidate = CreateRandomConcatination()
fitness = CalculateFitness(candidate) // returns 0 < fitness <= 1
r = GetRand(zero to one)
adjusted_r = Math.pow(r, C * rejectionCount + 1) // bias toward acceptability as rejectionCount increases
if (adjusted_r < fitness)
{
return candidate
}
}
}
CalculateFitness should never return zero. If it does, you might find yourself in an infinite loop.
As you increase C, less ideal concatenations are accepted more readily.
As you decrease C, you face increased iterations for each call to CreateGoodConcatenation (plus less entropy in the result)

Resources