How do I separetly print two dictionary keys with the same value? - python

I want to print a message telling the user the most common personality type of an animal crossing villager using a dataset. However, the 'Lazy' and 'Normal' dictionary keys are both the most common and have the same value. I can't figure out how to make them print separately without hardcoding.
Here's my code:
totalfreq2 = {}
for p_type in personality:
if p_type in totalfreq2:
totalfreq2[p_type] +=1
else:
totalfreq2[p_type] = 1
print(totalfreq2)
maxfreq2 = max(totalfreq2.values())
print(maxfreq2)
toplst = ()
for p_type in totalfreq2:
if totalfreq2[p_type] == 63:
ww = p_type
print(ww)
print("The most common personality type for an Animal Crossing Villager is",ww,)
Here's the printed output:
{'Jock': 57, 'Cranky': 57, 'Peppy': 53, 'Big Sister': 26, 'Lazy': 63, 'Normal': 63, 'Snooty': 57, 'Smug': 37}
63
Normal
The most common personality type for an Animal Crossing Villager is Normal
How do I add 'Lazy' to this message without hardcoding?

Collect all the keys that have the max value, then use .join() to print them nicely:
# The missing data matching the OP's output.
personality = ['Jock'] * 57 + ['Cranky'] * 57 + ['Peppy'] * 53 + ['Big Sister'] * 26 + ['Lazy'] * 63 + ['Normal'] * 63 + ['Snooty'] * 57 + ['Smug'] * 37
totalfreq2 = {}
for p_type in personality:
if p_type in totalfreq2:
totalfreq2[p_type] +=1
else:
totalfreq2[p_type] = 1
maxfreq2 = max(totalfreq2.values())
# find all keys with same max value
toplist = [k for k,v in totalfreq2.items() if v == maxfreq2]
print(f"The most common personality type for an Animal Crossing Villager is: {', '.join(toplist)}")
Output:
The most common personality type for an Animal Crossing Villager is: Lazy, Normal
See also collections.Counter for a built-in way to count items and get the most common, for example:
import collections
...
totalfreq2 = collections.Counter(personality)
# Returns counts sorted highest to lowest and gets the first one.
# It returns [(key, count)] hence the subscripting to get the count.
maxfreq2 = totalfreq2.most_common(1)[0][1]
...

It looks like you had the right idea... just change toplist to an empty list and instead of assigning the value to the variable ww you can append the value to the list and then print the contents of the list once the loop has finished.
maxfreq2 = max(totalfreq2.values())
toplst = []
for p_type in totalfreq2:
if totalfreq2[p_type] == maxfreq2:
toplst.append(p_type)
print(toplst)
There are quite a few alternatives you could use as well.
list comprehension.
[print(i) for i in totalfreq2 if totalfreq2[i] == maxfreq2]
or you can use the filter function
for ptype in filter(lambda x: totalfreq2[x] == maxfreq2, totalfreq2.keys()):
print(ptype)

Related

Issues with KeyError: 0

Im having issued where my code keeps saying KeyError: 0, I have searched all over and couldn't find a way to fix this
student_scores = {'0':65.0, '1':54.7}
average_score = 66.0
i = 0
for v in student_scores:
if student_scores[i] >= average_score:
above_avg_check = "{} {}".format(student_names[i], student_scores[i])
above_avg.append(above_avg_check)
print(above_avg_check)
i += 1
I am not sure on what to do, i is both a counter and the key of student_scores, so I can use it in a while loop.
You're checking an integer index while your 0 index is actually a string.
This code compiles for me on repl, just convert your index values to strings before trying to find them
student_scores = {'0':65.0, '1':54.7}
average_score = 66.0
i = 0
for v in student_scores:
if student_scores[str(i)] >= average_score:
above_avg_check = "{} {}".format(student_names[str(i)], student_scores[str(i)])
above_avg.append(above_avg_check)
print(above_avg_check)
i += 1
You can use the .items() method and get the scores in a much more simple way. The you can format your string based on the student and their score within your for loop.
student_scores = {'0': 65.0, '1': 54.7}
average_score = 65.0
i = 0
above_avg = []
for student, score in student_scores.items():
if score >= average_score:
above_average_check = '{}: {}'.format(student, score)
above_avg.append(above_average_check)
print(above_average_check)
i += 1
And here is your output:
0: 65.0
This will get you the output that you are looking for as you iterate through each key and its corresponding value.

Comparing an unlimited number of values taken from a 2D array to see which element has the largest sum

I'm trying to produce a program that will check the highest sum value of a 2D array.Then it needs to compare each value against each other to output which is the largest of all the sums for each position in the array.
I'm able to do this for a set number of elements but i would like to do this for an unlimited number of elements depending on how many elements the user inputs.
Person = [123,321,213]
TotalMorn =[[3,5,6,4,5,3,7],
[2,1,1,2,3,4,5],
[3,4,5,6,7,6,5]]
TotalAft =[[8,7,6,2,6,7,5],
[4,3,2,3,4,3,2],
[1,1,1,1,2,3,1]]
def WeeklyTotal(K):
Total = 0
for j in range(7):
TotalM = TotalMorn[K][j]
TotslA = TotalAft[K][j]
Total = TotalM + TotalA + Total
return Total
Total1 = WeeklyTotal(0)
Total2 = WeeklyTotal(1)
Total3 = WeeklyTotal(2)
if Total1 > Total2 and Total1 > Total3:
print 'Person', (Person[0]), 'Has produced the most profit with ', Total1
elif Total2 > Total1 and Total2 > Total3:
print 'Peron', (Person[1]), 'Has produced the most profit with ', Total2
elif Total3 > Total1 and Total3 > Total2:
print 'Person', (Person[2]), 'Has produced the most profit with ', Total3
I assume what you want to do is find the max value in the array WeeklyTotal?
maxIndex, maxValue = 0,0
for i in range(0,len(WeeklyTotal)-1):
if WeeklyTotal[i] > maxValue :
maxValue = WeeklyTotal[i]
maxIndex = i
print 'Person ',Person[maxIndex],' Has produced the most profit with ',WeeklyTotal[maxIndex]
In your case, you either need to bind person to his totalScore. You would then look for the maximum score value, and so you would have the person with the maximum score affiliated with this value, such as...
arr = [('John', 15), ('Sue', 13), ('Jack', 20), ('Tom', 5)]
print max(arr, key = lambda x:x[1])
# outputs : ('Jack', 20)
Here, you have bound the score to the person into a list of tuples. You asking max function to look for the highest value using the second element of each tuple (that's what key = lambda x:x[1] means).
In your example, where data would be formatted such as...
people = ['John', 'Sue', 'Jack', 'Tom']
scores = [15, 13, 20, 5]
... you might want to use a function to determine the index of the highest value, doing :
# We set the highest score at the beginning as the first value, and save the index.
curr_score = scores[0]
saved_index = 0
# We then iterate through scores, not looping through the first item, as its index
# is already saved. We set the start of the index to `1`.
for index, score in enumerate(scores[1:], start=1):
if score > curr_score:
# We save the new highest score.
curr_score = score
# And keep its index.
saved_index = index
# At the end of the loop, we saved the maximum value index, and can use it
# on `people` array.
print people[saved_index]
# It will output the person with the highest score.
Here is a short solution using some python idioms:
(Thanks to IMCoins for reminding me about max(a, key = lambda...)
people = [123,321,213]
morning =[[3,5,6,4,5,3,7],
[2,1,1,2,3,4,5],
[3,4,5,6,7,6,5]]
afternoon =[[8,7,6,2,6,7,5],
[4,3,2,3,4,3,2],
[1,1,1,1,2,3,1]]
def makeTotals(people, morning, afternoon):
return [(p,sum(m+a)) for (p,m,a) in zip(people, morning, afternoon)]
allTotals = makeTotals(people, morning, afternoon)
print(max(allTotals, key = lambda x:x[1]))
Output:
(123, 74)
The makeTotals function zips up the arrays to align each person with their morning and afternoon scores and (p,sum(m+a)) creates a tuple of the person and their total.
The call to max uses the key = lambda x:x[1] parameter (thanks #IMCoins) to pull out the tuple with the largest sum of morning and afternoon scores.
how about a 'one-liner' (with line breaks and added whitespace for readability)
Person = [123,321,213]
TotalMorn =[[3,5,6,4,5,3,7],
[2,1,1,2,3,4,5],
[3,4,5,6,7,6,5]]
TotalAft =[[8,7,6,2,6,7,5],
[4,3,2,3,4,3,2],
[1,1,1,1,2,3,1]]
print('Person %s Has produced the most profit with %s'
% max(zip(map(sum,
zip(map(sum, TotalMorn),
map(sum, TotalAft))),
Person))[::-1])
Person 123 Has produced the most profit with 74

Getting elements from a table and counting total

I have a table as such representing the result of a game.
GameTab = [['TRE','ARD','1','1'],['PRK','GEA','2','3'],['ARD','PRK','1','0'],['TRE','GEA','2','1']]
I appended the result from a text file into table form so here's the text format: To put it easier, it's interpreted in such that for example, TRE scored 1 and ARD scored 1. PRK scored 2 and GEA score 3.
TRE:ARD:1:1
PRK:GEA:2:3
ARD:PRK:1:0
TRE:GEA:2:1
Instead of obtaining the result for the player, i want to obtain the result of the opponent instead. I have done my code in a way where it obtains the result of the player but i couldn't think of a way to obtain the opponents result.
For example, in the match of PRK:GEA and TRE:GEA:
The opponent of GEA scored a total of: 4
My code:
gameTab =[['TRE','ARD','1','1'],['PRK','GEA','2','3'],['ARD','PRK','1','0'],
['TRE','GEA','2','1']]
dictionary = {}
for i in gameTab:
for c in range(len(i[:2])):
if i[:2][c] not in dictionary.keys():
dictionary[i[:2][c]] = int(i[2:][c])
else:
dictionary[i[:2][c]] += int(i[2:][c])
print(dictionary)
In order to obtain the result of the opponent against a team, The below code satisfied the condition:
gameTab =[['TRE','ARD','1','1'],['PRK','GEA','2','3'],['ARD','PRK','1','0'],['TRE','GEA','2','1']]
dictionary = {}
for i in gameTab:
if i[0] in dictionary:
dictionary[i[0]] += int(i[3])
else:
dictionary[i[0]] = int(i[2])
if i[1] in dictionary:
dictionary[i[1]] += int(i[2])
else:
dictionary[i[1]] = int(i[2])
print(dictionary)
it prints out: {'ARD': 1, 'GEA': 4, 'TRE': 2, 'PRK': 3}
Basically traverse the list of lists, and for every team check if it exists in dictionary then increment its value as the opponents value. And finally you would get all point scored against a team by the opposition.
gametab = [['TRE','ARD','1','1'],['PRK','GEA','2','3'],['ARD','PRK','1','0'],['TRE','GEA','2','1']]
dicta = {}
for i in range(len(gametab)):
for j in range(2):
if gametab[i][j] in dicta:
dicta[gametab[i][j]] += int(gametab[i][j+2])
else:
dicta[gametab[i][j]] = int(gametab[i][j+2])
print dicta

Assigning salespersons to different cities program

I was working on a problem of assigning 8 salespersons to 8 different cities, which are represented in below format.
The column represents Sales person and row represent cities.
1) The condition for assigning are :
1) Only one city per person
2) Once a city is assigned a salesperson , the rows and columns and diagonal cities cannot be assigned to another person
I am not able to recreate an example from memory , sorry for that , but the representation of cities and salesperson is correct.
I thought to avoid rows or columns for similar salesperson , I could use permutations from python which will give me distinct set of cities without overlapping and from there on I could check for diagonal values.
Here is my attempt.
import collections
import itertools
def display (l):
list_count = 0
k = ''
for i in l:
print i
list_count = list_count + 1
if list_count != len(l):
k = k + ','
cities = [1,2,3,4,5,6,7,8]
sales = [1,2,3,4,5,6,7,8]
print_list = []
count = 0
for i in itertools.permutations([1,2,3,4,5,6,7,8],8):
print_list.append(i)
if count == 2:
display(print_list)
#print print_list
#print '\n'
for j in range(8):
print_list.pop()
count = 0
count = count + 1
I am stuck on how to check if a salesperson is in diagonal position to another Salesperson, If someone can extend my approach that would be great , would like any other explanation , would be helpful, I would like python as I am practising in it.

Python Greedy Algorithm

I am writing a greedy algorithm (Python 3.x.x) for a 'jewel heist'. Given a series of jewels and values, the program grabs the most valuable jewel that it can fit in it's bag without going over the bag weight limit. I've got three test cases here, and it works perfectly for two of them.
Each test case is written in the same way: first line is the bag weight limit, all lines following are tuples(weight, value).
Sample Case 1 (works):
10
3 4
2 3
1 1
Sample Case 2 (doesn't work):
575
125 3000
50 100
500 6000
25 30
Code:
def take_input(infile):
f_open = open(infile, 'r')
lines = []
for line in f_open:
lines.append(line.strip())
f_open.close()
return lines
def set_weight(weight):
bag_weight = weight
return bag_weight
def jewel_list(lines):
jewels = []
for item in lines:
jewels.append(item.split())
jewels = sorted(jewels, reverse= True)
jewel_dict = {}
for item in jewels:
jewel_dict[item[1]] = item[0]
return jewel_dict
def greedy_grab(weight_max, jewels):
#first, we get a list of values
values = []
weights = []
for keys in jewels:
weights.append(jewels[keys])
for item in jewels.keys():
values.append(item)
values = sorted(values, reverse= True)
#then, we start working
max = int(weight_max)
running = 0
i = 0
grabbed_list = []
string = ''
total_haul = 0
# pick the most valuable item first. Pick as many of them as you can.
# Then, the next, all the way through.
while running < max:
next_add = int(jewels[values[i]])
if (running + next_add) > max:
i += 1
else:
running += next_add
grabbed_list.append(values[i])
for item in grabbed_list:
total_haul += int(item)
string = "The greedy approach would steal $" + str(total_haul) + " of
jewels."
return string
infile = "JT_test2.txt"
lines = take_input(infile)
#set the bag weight with the first line from the input
bag_max = set_weight(lines[0])
#once we set bag weight, we don't need it anymore
lines.pop(0)
#generate a list of jewels in a dictionary by weight, value
value_list = jewel_list(lines)
#run the greedy approach
print(greedy_grab(bag_max, value_list))
Does anyone have any clues why it wouldn't work for case 2? Your help is greatly appreciated.
EDIT: The expected outcome for case 2 is $6130. I seem to get $6090.
Your dictionary keys are strings, not integers so they are sorted like string when you try to sort them. So you would get:
['6000', '3000', '30', '100']
instead wanted:
['6000', '3000', '100', '30']
Change this function to be like this and to have integer keys:
def jewel_list(lines):
jewels = []
for item in lines:
jewels.append(item.split())
jewels = sorted(jewels, reverse= True)
jewel_dict = {}
for item in jewels:
jewel_dict[int(item[1])] = item[0] # changed line
return jewel_dict
When you change this it will give you:
The greedy approach would steal $6130 of jewels.
In [237]: %paste
def greedy(infilepath):
with open(infilepath) as infile:
capacity = int(infile.readline().strip())
items = [map(int, line.strip().split()) for line in infile]
bag = []
items.sort(key=operator.itemgetter(0))
while capacity and items:
if items[-1][0] <= capacity:
bag.append(items[-1])
capacity -= items[-1][0]
items.pop()
return bag
## -- End pasted text --
In [238]: sum(map(operator.itemgetter(1), greedy("JT_test1.txt")))
Out[238]: 8
In [239]: sum(map(operator.itemgetter(1), greedy("JT_test2.txt")))
Out[239]: 6130
I think in this piece of code i has to be incremented on the else side too
while running < max:
next_add = int(jewels[values[i]])
if (running + next_add) > max:
i += 1
else:
running += next_add
grabbed_list.append(values[i])
i += 1 #here
this and #iblazevic's answer explains why it behaves this way

Categories

Resources