Python declare winner using dictionary and loop - python

This is the output of the code I am trying to write. I have seen this done for C++, but not python with a dictionary. The key here is the dictionary is not optional. I need to use it to fulfill the assignment.
ID Candidate Votes Received % of Total Vote
1 Johnson 5000 55.55
2 Miller 4000 44.44
Total 9000
and the winner is Johnson!
I need to use a dictionary and a loop to create this. However, I am stuck on 3 points.
1.The percent- current code returns the percent before it has the whole total ex: first candidate always has 100%.
2. Declare a winner- code finds the max votes and returns the number value but I need it to return the name.
3. How to format the dictionary values so it lines up under the header. I don't think is possible, but it must be a requirement to use a dictionary for a reason. I am thinking I need to make a copy of the dictionary and format that?
Here is what I have so far:
totalVotes=[]
dct = {}
i = 1
while(True):
name = input('Please enter a name: ')
if name == '':
break
votes = input('Please enter vote total for canidate: ')
totalVotes.append(votes)
totalVotesInt= map(int, totalVotes)
total = sum(totalVotesInt)
dct[i] = {name,votes,int(votes)/total*100}
i += 1
header='{:>0}{:>10}{:>10}{:>20}'.format('ID','Name','Votes','% of Total Vote')
print(header)
print("\n".join("{}\t{}".format(key, value) for key, value in dct.items()))
print('Total '+str(total))
print('The Winner of the Election is '+max(totalVotes))
Which returns:
Please enter a name: Smith
Please enter vote total for canidate: 100
Please enter a name: Frieda
Please enter vote total for canidate: 200
Please enter a name: West
Please enter vote total for canidate: 10
Please enter a name:
ID Name Votes % of Total Vote
1 {'Smith', '100', 100.0}
2 {'Frieda', 66.66666666666666, '200'}
3 {3.225806451612903, '10', 'West'}
Total 310
The Winner of the Election is 200

You add the number of each candidates votes at the same time you calculate the percent vote for each candidate. You need to find the total votes first, then divide each candidates votes by the total
You are returning the max of a list of integers. Obviously you aren't going to get a string. You need some way to connect the number votes with the candidate.
Don't bother. You can try to figure out how many tabs you need to get the whole thing lined up, but from experience, it is basically impossible. You could separate them with commas and open it in excel as a csv, or you could just make the user figure out what number goes with what.
The other answer uses data tables, so I will take another, more vanilla and cool approach to getting what you want.
class candidate():
def __init__(self, name, votes):
self.name = name
self.votes = int(votes)
def percentvotes(self, total):
self.percent = self.votes/total
def printself(self, i):
print('{}\t{}\t\t{}\t\t{}'.format(i, self.name, self.votes, self.percent))
def getinput():
inp = input('Please enter your candidates name and votes')
return inp
candidates = []
inp = getinput()
s = 0
while inp != '':
s+=1
candidates.append(candidate(*inp.split(" ")))
inp = getinput()
for c in candidates:
c.percentvotes(s)
candidates.sort(key = lambda x:-x.percent)
print('ID\tname\t\tvotes\t\tpercentage')
for i, c in enumerate(candidates):
c.printself(i+1)

I have added very little changes to your code to make it work:
I have mentioned the changes as comments in the code.
Edit: It's more efficient to use objects for each candidate if you require scaling in the future.
totalVotes=[]
dct = {}
i = 1
while(True):
name = input('Please enter a name: ')
if name == '':
break
votes = input('Please enter vote total for canidate: ')
totalVotes.append(votes)
totalVotesInt= map(int, totalVotes)
total = sum(totalVotesInt)
# I change it to a list so it's much easier to append to it later
dct[i] = list((name,int(votes)))
i += 1
# I calculate the total percent of votes in the end and append to the candidate
maxVal = 0
for i in range(1, len(dct) + 1):
if dct[i][1] > maxVal:
maxInd = i
dct[i].append(int((dct[i][len(dct[i]) - 1]) / total * 100))
header='{:>0}{:>10}{:>10}{:>20}'.format('ID','Name','Votes','% of Total Vote')
print(dct)
print(header)
print("\n".join("{}\t{}".format(key, value) for key, value in dct.items()))
print('Total '+str(total))
print('The Winner of the Election is '+ dct[maxInd][0]))

I believe that this is the solution you are looking for. Just change the input statements in case you are using Python 2.x. Using Dataframe, the output will be exactly how you wanted.
import pandas as pd
import numpy as np
df = pd.DataFrame(columns=["Candidate", "Votes Received","Percentage of total votes"])
names=list()
votes=list()
while True:
name = str(input("Enter Name of Candidate."))
if name=='':
break
else:
vote = int(input("Enter the number of votes obtained."))
names.append(name)
votes.append(vote)
s=sum(votes)
xx=(votes.index(max(votes)))
myArray = np.array(votes)
percent = myArray/s*100
for i in range(len(names)):
df1 = pd.DataFrame(data=[[names[i],votes[i],percent[i]]],columns=["Candidate", "Votes Received","Percentage of total votes"])
df = pd.concat([df,df1], axis=0)
df.index = range(len(df.index))
print (df)
print ("Total votes = ",s)
print ("The man who won is ",names[xx])

Related

How to find the average of an array and pin it with its corresponding name with another array

I have my code set to allow the user to make a list of names for students and another list for their corresponding grades. What I cant seem to figure out is how to take the highest grade, the lowest grade, and the closest to the average then state it with the student it belongs to.
This is what I have so far
# creating statements
students = []
grades = []
print('students:',students)
print('grades:',grades)
looper1 = 0
looper2 = 0
studentappend = 0
gradeappend = 0
# list creation
while looper1 != 2:
print('please choose an option:')
print('1: add student and grade')
print('2: Finish step')
looper1 = int(input())
if looper1 ==1:
students.append(input('enter student name: '))
grades.append(int(input('enter grade:')))
print('students:',students)
print('grades:',grades)
if looper1 ==2:
break
if looper1 !=1 and looper1 !=2:
print('Invalid. enter 1 or 2')
print('students:',students)
print('grades:',grades)
print("Largest element is:", max(grades))
On the last line I have it set to say "Largest grade is: 55" for example, but I want to make it say the name the grade belongs to as well. For example "Bill has the largest grade of 55" This will apply to the lowest grade and the grade that is the closest to the average. I was hoping the max() function would print the number that would tell me where the grade I was looking for was located rather then simply stating it.
Here is a solution with modifications to make your code more streamlined:
students = []
grades = []
#gather input
looper = 1
while looper == 1:
students.append(input('enter student name: '))
grades.append(int(input('enter grade: ')))
looper = int(input('Enter 1 to add more data or another number to exit: '))
#calculate closest to mean
true_mean = sum(grades)/len(grades)
close_to_mean = 0
for i, grade in enumerate(sorted(grades)):
if grade < true_mean < sorted(grades)[i+1]:
close_to_mean = grade
print('students:',students)
print('grades:',grades)
print(f"Highest grade is: {max(grades)} and belongs to {students[grades.index(max(grades))]}.")
print(f"Lowest grade is: {min(grades)} and belongs to {students[grades.index(min(grades))]}.")
print(f"Closest to mean grade is: {close_to_mean} and belongs to {students[grades.index(close_to_mean)]}.")
You can reference the index location for the highest value in the grades list and use that index to return the corresponding student in the students list.
print(students[grades.index(max(grades))]+" has the larges grade of "+str(max(grades)))
Note that the index method returns the index of the first matching item in the list. So if two students are tied with the highest score, it will only return the one listed first.
If you aren't opposed, another approach is to use NumPy functions.
np.argmax and np.argmin give the indices of the (first occurrence of) the maximum and minimum value in an array or list.
To get the name of the student with the highest grade: students[np.argmax(grades)]
To get the name of the student with the lowest grade: students[np.argmin(grades)]
To get the name of the student with the grade closest to the average, you may need list comprehension to calculate the absolute difference between the average grade and each student's grade:
students[np.argmin(np.abs([x - np.mean(grades) for x in grades]))]
Alternatively, instead of list comprehension, you can directly cast it to a numpy array:
students[np.argmin(np.abs(np.array(grades) - np.mean(grades)))]

Implement a condition into a array

I'm trying to implement another condition into my program but can't seem to figure it out.
Here is the code:
print ("Welcome to the winning card program.")
year_one=[]
year_one.append(eval(input("Enter the salary individual 1 got in year 1: ")))
year_one.append(eval(input("Enter the salary individual 2 got in year 1: ")))
if year_one[0]==year_one[1]:
print("Error. The amount are the same, please reenter information.")
year_two=[]
year_two.append(eval(input("Enter the salary individual 1 got in year 2: ")))
year_two.append(eval(input("Enter the salary individual 2 got in year 2: ")))
if year_two[0]==year_two[1]:
print("Error. The amount are the same, please reenter information.")
year_three=[]
year_three.append(eval(input("Enter the salary individual 1 got in year 3: ")))
year_three.append(eval(input("Enter the salary individual 2 got in year 3: ")))
if year_three[0]==year_three[1]:
print("Error. The amount are the same, please reenter information.")
year_four=[]
year_four.append(eval(input("Enter the salary individual 1 got in year 4: ")))
year_four.append(eval(input("Enter the salary individual 2 got in year 4: ")))
if year_four[0]==year_four[1]:
print("Error. The amount are the same, please reenter information.")
year_five=[]
year_five.append(eval(input("Enter the salary individual 1 got in year 4: ")))
year_five.append(eval(input("Enter the salary individual 2 got in year 4: ")))
if year_five[0]==year_five[1]:
print("Error. The amount are the same, please reenter information.")
individual1_total=year_one[0]+year_two[0]+year_three[0]+year_four[0]+year_five[0]
individual2_total=year_one[1]+year_two[1]+year_three[1]+year_four[1]+year_five[1]
if (individual1_total>individual2_total):
print("Individual one has the highest salary.")
elif (individual2_total>individual1_total):
print("Individual two has the highest salary.")
If the salary for the two individuals for a particular year is exactly the same, you should print an error and make the user enter both the salaries again for that year. (The condition is the salaries should not be the exact same).
I look forward to everyone's feedback.
Thank you in advance.
Ok so building on surge10 here is a more complete replacement of your code. I broke all the pieces down into functions, and made a dictionary as my in in-memory database.
total_years = 5
years = {}
def dict_key(year, userId):
return '{}:{}'.format(year, userId)
def get_user_data(year, userId):
key = dict_key(year, userId)
years[key] = float(input("Enter the salary individual {} got in year {}:".format(userId, year)))
def get_year_salaray(year, userId):
key = dict_key(year, userId)
return years[key]
def any_salaries_match(year, userIds):
for userLeft in userIds:
salary_left = get_year_salaray(year, userLeft)
for userRight in userIds:
if userLeft != userRight:
salary_right = get_year_salaray(year, userRight)
if salary_left == salary_right:
return True
def get_user_totals(userId):
total = 0
for key, value in years.items():
if ':{}'.format(userId) in key:
total += value
return total
for x in range(total_years):
year = x + 1
data_invalid = True
while data_invalid:
userOne = 1
userTwo = 2
get_user_data(year, userOne)
get_user_data(year, userTwo)
if any_salaries_match(year, [userOne, userTwo]):
print("Error. The amount are the same, please reenter information.")
else:
data_invalid = False
userOneTotal = get_user_totals(1)
userTwoTotal = get_user_totals(2)
if (userOneTotal>userTwoTotal):
print("Individual one has the highest salary.")
elif (userTwoTotal>userOneTotal):
print("Individual two has the highest salary.")
Since we were checking for five different years I used a loop for those five years
Later we can get it back into individual years.
print ("Welcome to the winning card program.")
years=[]
for x in range(5):
# range starts at zero so add one all the time
# to start it at one
y = str(x + 1)
errors = True
while errors:
salary_one = input("Enter the salary individual 1 got in year " + y + ": ")
salary_two = input("Enter the salary individual 2 got in year " + y + ": ")
if salary_one == salary_two:
print("Error. The amount are the same, please reenter information.")
errors = True
else:
years.append([salary_one, salary_two])
errors = False
year_one = years[0]
year_two = years[1]
...
print(year_one)
print(year_two)
...

Defining lists and calling functions in Python

I am using Python 3. This is for a homework project for a class, but I'm not looking for something to do the problem for me! I was just wondering if someone could help point out exactly where I've gone wrong, or what I need to look into to make my code work.
def main():
taxPayersList = []
incomesList = []
taxesList = []
taxPayersList, incomesList = inputNamesAndIncomes(taxPayersList, incomesList)
taxesList = calculateTaxes(incomesList)
displayTaxReport(taxesList, incomesList, taxPayersList)
def inputNamesAndIncomes(taxPayersList, incomesList):
print('Welcome to Xanadu Tax Computation Program')
print('')
confirmation = input('Do you have income amounts? y/n ')
index = 0
try:
while confirmation == 'y' or confirmation == 'Y':
taxPayersList[index] = input('Enter a tax payer name: ')
incomesList[index] = float(input('Enter income amount: '))
confirmation = input('Are there more income amounts? ')
index += 1
except:
print('An error occurred. Please only enter numbers for income amount.')
return taxPayersList, incomesList
def calculateTaxes(incomesList):
index = len(incomesList)
while index < len(incomesList):
if incomesList[index] >= 0 and incomesList[index] <= 50000:
taxesList[index] = incomesList[index] * .05
elif incomesList[index] >= 50000 and incomesList[index] <= 100000:
taxesList[index] = 2500 + ((incomesList[index] - 50000) * .07)
elif incomesList[index] >= 100000:
taxesList[index] = 6000 + ((incomesList[index] - 100000) * .09)
index += 1
return incomesList
def displayTaxReport(taxesList, incomesList, taxPayersList):
print('2018 TAX DUES FOR XANADU STATE')
print('')
print('Name\t\tANNUAL INCOME\tTAXDUE')
for n in incomesList:
print(taxPayersList,'\t\t',incomesList,'\t',taxesList)
main()
Right now, I can enter a name into the first input, but as soon as I hit enter it just prints out my error code and then print out the final function like below.
Welcome to Xanadu Tax Computation Program
Do you have income amounts? y/n y
Enter a taxpayer name: Susan
An error occurred. Please only enter numbers for income amount.
2018 TAX DUES FOR XANADU STATE
Name ANNUAL INCOME TAXDUE
I know this is a total mess but any help at all would be so appreciated!
There is an IndexError: list assignment index out of range for the line
taxPayersList[index] = input('Enter a tax payer name: ')
You didn't see it because you excepted all errors and didn't print them. I suggest using
name = input('Enter a tax payer name:')
taxPayersList.append(name)
etc. Note that I append it to the list. I also suggest a different strategy of handling errors.
Alternatively, you might wish to use a dictionary instead of using two lists, since you want to associate an income with a name,
name = input('Enter a tax payer name:')
income = float(input('Enter income amount:'))
incomes[name] = income
You can't just assign into a non-existant index for a list to add items to it:
>>> a = []
>>> a[0] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
Instead you should look at using the .append() method for lists.
(The reason you aren't seeing the IndexError debugging details is because your except clause prevents it from being displayed. Bare except clauses are often considered an antipattern because they mask unexpected errors like this and make it harder to tell what went wrong - they catch any exception, not just ones due to bad user input.)

Python FOR loops with dictionaries

I'm doing a small program that has the job of a school's subjects and marks management.
HOW IT WORKS
I've created 4 variables: a dictionary, an initialized empty string(for subjects) and two initialized empty integers(one for the marks, the other one for the subjects number). The program asks the user to input the numbers of subjects to work with. After that, it enters in a for loop that repeats itself in the range of the subjects number. And it works fine. Now the problem comes when the user inputs a mark over the range specified. Let's suppose we have a school and the marks we can input are between 1 and 10. The user can't write 11,12 and so on..
CODE
pagella = {}
materia = ""
voti = 0
length = 0
print("Insert the number of subjects, the subjects and the marks-")
num = int(input("Number of subjects: "))
length = len(pagella)
length = num
for i in range(length):
materia = input("Subject: ")
voto = eval(input("Mark: "))
if(voto > 10):
print("Number between 1 and 10")
else:
pagella[materia] = voto
print(pagella)
As you can see, there's the for loop that asks the user to input the subjects and the marks in the range of num(the number of subjects). If I try to input 12 on a mark, the program tells me to input a mark between 1 and 10 so it repeat again the cycle from the beginning. But the problem is that in this case, if I want to have 3 subjects with 3 marks (that means 3 iterations), one is lost because of the wrong mark, so I will not have 3 subjects and marks to input correctly, but only 2.
I hope I've explained correctly everything and someone can help me!
Thanks in advice
I suggest you the following solution that handles also the cases of non-numeric values as input for marks:
pagella = {}
materia = ""
length = 0
print("Insert the number of subjects, the subjects and the marks-")
num = int(input("Number of subjects: "))
length = num
for i in range(num):
# Ask for subject
materia = input("Subject: ")
# Ask for mark until the input is correct
voto = None
while (voto is None):
try:
voto = int(input("Mark: "))
if (voto > 10):
print("Number between 1 and 10")
voto = None
except:
print("Pleaser enter an integer")
# Store in dictionary pagella (if mark is correct)
pagella[materia] = voto
print(pagella)

Python appending a list and stopping it

I have to use the append method to get info from the user however I am only suppose to take 10 lines from the user and not suppose to ask them if they have another set of information to enter. Can anyone tell me how to stop a list_append without asking the user to stop it?
The following is my code in python.
#set limit
num_grades = 10
def main():
#making of the list
grades = [0] * num_grades
#hold the index
index = 0
#ask the user for the info
print('Please enter the final grades for 10 students: ')
#put the info into the list with a loop
while index < num_grades:
grade = input('Enter a grade: ')
grades.append(grade)
main()
Your given code is missing only one thing: you forgot to increment the index each time through the loop.
Do this better with a for loop:
for index in range(num_grades):
grade = input('Enter a grade: ')
grades.append(grade)
Your issue is that you are forgetting to increment index inside the while loop you have created, and hence it is always zero.
Just adding a index += 1 line inside the loop will fix your issue.
As stated by #Prune, a for loop would be much more suitable in this situation.
This kind of thing is easily handled by for loops. Here is your code edited:
num_grades = 10
def main():
#making of the list
grades = []
#ask the user for the info
print('Please enter the final grades for 10 students: ')
#put the info into the list with a loop
for i in range(num_grades):
grade = input('Enter a grade: ')
grades.append(grade)
main()
As #Wintro has mentioned, the issue was that you forgot to increment the index inside the while loop.
So the working solution looks as follows:
num_grades = 10
def main():
#making of the list
grades = [0] * num_grades
#hold the index
index = 0
#ask the user for the info
print('Please enter the final grades for 10 students: ')
#put the info into the list with a loop
while index < num_grades:
grade = input('Enter a grade: ')
grades.append(grade)
index += 1
main()

Categories

Resources