Finding values in an unsorted list - python

so I have this assignment that is telling me to code a quiz about food. I pretty much ask some random questions about food and I have to display 2 of the top recommended foods from what they have answered. I made a list of 8 foods and a score for each one of the foods.
food=["pizza", "hotdogs", "chicken", "apples", "fish", "fries", "burgers", "donuts"]
score=[0,0,0,0,0,0,0,0,0]
print("Please answer each of the questions with yes or no.")
question=input("Do you eat meat?")
if question=="yes":
score[0]=score[0] + 1
score[1]=score[1] + 1
score[2]=score[2] + 1
score[4]=score[4] + 1
score[6]=score[6] + 1
question=input("Do you like fruits?")
if question=="yes":
score[3]=score[3] + 1
question=input("Do you like fried foods?")
if question=="yes":
score[2]=score[2] + 1
score[5]=score[5] + 1
score[4]=score[4] + 1
question=input("Do you like cheese?")
if question=="yes":
score[0]=score[0] + 1
score[1]=score[1] + 1
score[6]=score[6] + 1
question=input("Do you like food with holes in it?")
if question=="yes":
score[7]=score[7] + 1
question=input("Do you like to eat healthy?")
if question=="yes":
score[3]=score[3] + 1
question=input("Do you like bread?")
if question=="yes":
score[1]=score[1] + 1
score[6]=score[6] + 1
question=input("Do you like protein rich foods?")
if question=="yes":
score[2]=score[2] + 1
score[4]=score[4] + 1
question=input("Do you like dessert?")
if question=="yes":
score[3]=score[3] + 1
score[7]=score[7] + 1
question=input("Are you a vegan?")
if question=="yes":
score[3]=score[3] + 1
score[5]=score[5] + 1
score[7]=score[7] + 1
print(food)
print(score)
biggestsofar=0
for i in range(1, len(score)):
if (score[biggestsofar] < score[i]):
biggestsofar = i
print("The biggest value is", biggestsofar)
print("Your recommended food is", food[biggestsofar])
This is what I have so far. The thing I am struggling with is displaying the 2 recommended foods. I found out how to display one of them (which is the code above^) but don't understand how to do the second. I have to somehow find the second biggest number in the list that gets created when they answer the questions. If someone can help me I would appreciate it.(And yes I had to use a loop to find the first one)

Using Dictionary approach
While there are some interesting ways to solve this, i took both the food and questions, converted them into dictionary to help you get the answer.
Step 1: convert the food into a dictionary as keys, and value as scores.
Step 2: convert all the questions into a dictionary as keys and values as a list of items that needs to be scored. Use food list as the index to look up the key and increment. You can also use the value as list of food items.
Step 3: Iterate through the questions and ask the questions
Step 4: If answer is yes, use the food_score dictionary to increment the food by 1
Step 5: Sort the food_score dictionary in reverse order to get the top food items. The first 2 will be the top 2 food items.
food=["pizza", "hotdogs", "chicken", "apples", "fish", "fries", "burgers", "donuts"]
food_score = {f:0 for f in food}
questions = {'Do you eat meat ? ':[0,1,2,4,6],
'Do you like fruits ? ':[3],
'Do you like fried foods ? ':[2,4,5],
'Do you like cheese ? ':[0,1,6],
'Do you like food with holes in it ? ':[7],
'Do you like to eat healthy ? ':[3],
'Do you like bread ? ':[1,6],
'Do you like protein rich foods ? ':[2,4],
'Do you like dessert ? ':[3,7],
'Are you a vegan ? ':[3,5,7]}
print("Please answer each of the questions with yes or no.")
#iterate through all the questions. k is question,
#and v is the elements that needs incremented
for k,v in questions.items():
q = input(k)
if q.lower() == 'yes':
#if answer is yes, then increment each food item by 1
for i in v: food_score[food[i]] +=1
#sort the dictionary by value, in reversed order so first value is highest score
ranked_food = sorted(food_score, key=food_score.get, reverse=True)
print ('The biggest value is : ',food_score[ranked_food[0]])
print ('Your recommended food is : ', ranked_food[0])
print ('The second biggest value is : ', food_score[ranked_food[1]])
print ('Your second recommended food is : ', ranked_food[1])
The first two elements in ranked_food should give you the top 2 food per recommendation.
This solution is flexible and allows you to expand the list of food items and also to expand the question sets. The rest of the code can remain the same and will find the top two food recommendations.
With your existing approach
If you are not allowed to use the new approach, you can do the following:
Assume you are allowed to use zip:
score_food = [(s,f) for s,f in zip(score,food)]
If zip is not allowed, then do this:
score_food = []
for i in range(len(food)):
score_food.append((score[i],food[i]))
Now sort the list in descending order using this:
score_food.sort(reverse=True)
This will give you the scores in descending order. Since you stored them as a tuple, your score and food are paired together and you can identify each of them using the index.
score_food[0] will be the highest ranked. score_food[0][0] will be the score and score_food[0][1] will be the food.
Similarly, score_food[1] will be the second highest ranked. score_food[1][0] will be the score and score_food[1][1] will be the food.
If sort function is not allowed, use any sort logic (bubble sort is simplest to implement), and sort them in descending order. Remember score_food[i][0] will be the score where i ranges from 0 thru 7 (since there are 8 food items).
Another option to implement this is:
score_index = []
for i, s in enumerate(score):
score_index.append((s,i))
Now this is stored as a tuple with score and index pair. Again, this can be sorted and then referenced.
code to sort in descending order
for i in range (len(score_food)-1):
for j in range(i+1,len(score_food)):
if score_food[i][0] < score_food[j][0]:
score_food[i],score_food[j] = score_food[j],score_food[i]
Now you can reference score_food[0] It has highest_score and best_food.
score_food[1] will give you next highest_score and next best_food

I read your question wrong. Sorry :/
Ok, so you want the two largest values, right? My old code still works, but with some modifications. You need to find the index of that value.
lis = [0, 1, 3, 2, 1, 4, 3, 1, 9]
sorted_lis = sorted(lis)
print(lis.index(sorted_lis[-1]), lis.index(sorted_lis[-2]))
Carrying over to your example:
score = [0, 1, 3, 2, 1, 4, 3, 1, 9]
sorted_score = sorted(score)
print(food[score.index(sorted_score[-1])], food[score.index(sorted_score[-2])])
Side note
I'm not sure if you know classes yet, but here's an alternate solution that is cleaner:
class Food(): # create a food class
def __init__(self, type_):
self.type = type_
self.value = 0
def increment(self):
self.value += 1
def __lt__(self, other):
return self.value < other.value
def __le__(self, other):
return self.value <= other.value
def __gt__(self, other):
return self.value > other.value
def __ge__(self, other):
return self.value >= other.value
def __eq__(self, other):
return self.type == other.type
foods = [Food("pizza"), Food("burger"), Food("hot dog")] # make some foods
food_STRING = []
for i in foods:
food_STRING.append(i.type)
for i in range(10):
food = input("Food:")
foods[food_STRING.index(food)].increment()
sorted_food = sorted(foods)
print(sorted_food[-1].type, sorted_food[-2].type)

While other people have given good answers, I recommend you use a dictionary. A dictionary is when you correspond one value (usually a string) to another value (such as a boolean, number, or another string).
I think you should implement this in your code:
# Creating a dictionary (food: score)
my_dictionary = {
'pizza': 0,
'hotdogs': 0,
'chicken': 0,
'apples': 0,
'fish': 0,
'fries': 0,
'burgers': 0,
'donuts': 0,
}
# Creating a function to change the food and score.
# Execute this function to change your score
def change_score(food, score):
global my_dictionary
my_dictionary[food] = score
I'll let you use this to try and finish your program yourself, but this should hopefully be helpful.
This site should help you understand dictionaries:

You can think of the answer as having two buckets for which to you can assign a larger value that the current then check if one is larger than the other and swap them if so. I am assuming your assignment didn't allow for the sort/sorted functions:
largest, second_largest = (0, 0)
for item in range(len(score))):
if score[item] > score[largest]:
second_largest = largest
largest = item
elif score[largest] > score[item] > score[second_largest]:
second_largest = item
print("The biggest value is", score[largest])
print("Your recommended food is", food[largest])
print("The second biggest value is", score[second_largest])
print("Your second recommended food is", food[second_largest])

Related

Reduce iterations in a sorting algorithm

Let's say I have a list that I want to sort based on subjective criteria, such as the user's personal preferences. In this case, just using the input() function.
The goal is to minimize the number of iterations and maximize the certainty of the algorithm.
In the example below, I implement a simple algorithm that selects two items at random from the list and asks the user which one they prefer. It then transfers a percentage of the assigned coefficient, from the not chosen item to the item chosen. And it takes away a chosen item percentage from the not chosen item.
How can I minimize the number of iterations without disturbing the certainty of the algorithm?
# Assign a coefficient to each element initialized to 1.0
def ListToDict(list_of_items):
food_dict = {}
for item in list_of_items:
food_dict[item] = 1.0
return food_dict
# Ask the user to choose between two items
def AskUser(item_name_one, item_name_two):
print("\n [" + item_name_one + "] or [" + item_name_two + "] ?")
user_choice = input("--> ")
if user_choice == "1" or user_choice == "2":
return int(user_choice)
else:
print("\nONLY 1 OR 2 PLEASE!")
return AskUser(item_name_one, item_name_two)
# The PerformSort() function update the coefficient of each item.
# For each step, the user will be asked to choose between two items.
# If the user chooses the first item,
# the coefficient of the first item will be increased by 0.1 times the coefficient of the second item,
# and the coefficient of the second item will be decreased by 0.1 times the coefficient of the first item.
# The opposite happens if the user chooses the second item.
# When the number_of_iterations parameter is high,
# the certainty of the result will be higher but the user will have to answer more questions.
def PerformSort(my_dict, number_of_iterations):
from random import randint
length_of_dict = len(my_dict)
for i in range(number_of_iterations):
print("\n---- ITERATION " + str(i + 1) + " ----")
remaining_items = list(my_dict.keys())
while len(remaining_items) > 1:
item_one = remaining_items[randint(0, len(remaining_items) - 1)]
item_two = remaining_items[randint(0, len(remaining_items) - 1)]
while item_one == item_two:
item_two = remaining_items[randint(0, len(remaining_items) - 1)]
user_choice = AskUser(item_one, item_two)
if user_choice == 1:
my_dict[item_one] += 0.1 * my_dict[item_two]
my_dict[item_two] -= 0.1 * my_dict[item_one]
elif user_choice == 2:
my_dict[item_one] -= 0.1 * my_dict[item_two]
my_dict[item_two] += 0.1 * my_dict[item_one]
remaining_items.remove(item_one)
remaining_items.remove(item_two)
return my_dict
# Get the list of items sorted by their coefficient
def OrderByCoeficient(food_dict):
list_of_keys = list(food_dict.keys())
list_of_keys.sort(key=lambda x: food_dict[x], reverse=True)
return list_of_keys
if __name__ == "__main__":
items_to_sort = [ "pizza", "cheeseburger", "beef", "soup", "ice cream" ]
my_dict = ListToDict(items_to_sort)
my_dict = PerformSort(my_dict, 3)
print("\n Here's your list from highest to lowest:")
print(OrderByCoeficient(my_dict))
I'd suggest just doing a regular sort by turning your AskUser into a comparator function and using functools.cmp_to_key() to turn it into a sorting key function. That way you can take advantage of sort's built-in efficiency to minimize the number of comparisons, without having to invent and tune your own sorting algorithm.
import functools
def ask_user_cmp(item1, item2):
while True:
print(f"[{item1}](1) or [{item2}](2) ?")
cmp = input("--> ")
if cmp == "1":
return 1
if cmp == "2":
return -1
print("1 or 2, please!")
ask_user_key = functools.cmp_to_key(ask_user_cmp)
items_to_sort = ["pizza", "cheeseburger", "beef", "soup", "ice cream"]
items_to_sort.sort(key=ask_user_key, reverse=True)
print("Here's your list from highest to lowest:")
print(items_to_sort)
[soup](1) or [ice cream](2) ?
--> 2
[beef](1) or [soup](2) ?
--> 2
[cheeseburger](1) or [beef](2) ?
--> 1
[cheeseburger](1) or [soup](2) ?
--> 1
[cheeseburger](1) or [ice cream](2) ?
--> 2
[pizza](1) or [cheeseburger](2) ?
--> 1
[pizza](1) or [ice cream](2) ?
--> 2
Here's your list from highest to lowest:
['ice cream', 'pizza', 'cheeseburger', 'soup', 'beef']
Comparing this with the results of running your code and giving the same answers:
---- ITERATION 1 ----
[cheeseburger] or [soup] ?
--> 1
[pizza] or [beef] ?
--> 1
---- ITERATION 2 ----
[soup] or [beef] ?
--> 1
[ice cream] or [pizza] ?
--> 1
---- ITERATION 3 ----
[beef] or [soup] ?
--> 2
[ice cream] or [pizza] ?
--> 1
Here's your list from highest to lowest:
['ice cream', 'cheeseburger', 'soup', 'pizza', 'beef']
Note that your code asked me two redundant questions (ice cream vs pizza and beef vs soup were both asked twice), and it never figured out that I like pizza better than either cheeseburgers or soup.

Difference between stock[item] -= 1 and stock[item] = stock[item] - 1?

I've trying to write a small program that computes a bill based on certain lists. One of the requirements is to change to stock depending on what is taken out. I wrote my code the following way, and at least conceptually speaking, feel like I have the right idea.
shopping_list = ["banana", "orange", "apple"]
stock = {
"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {
"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
def compute_bill(food):
total = 0
for item in food:
if stock[item] > 0:
total += prices[item]
stock[item] = stock[item] - 1
return total
else:
return "Sorry: Out of Stock"
return total
Unfortunately it doesn't work. I've looked up a potential solution and found one that goes like this.
groceries = ["banana", "orange","apple"]
stock = {"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
def computeBill(food):
total = 0
for item in food:
if stock[item] > 0:
total += prices[item]
stock[item] -= 1
return total
print computeBill(groceries)
The main difference I see lies in these pieces of code:
stock[item] = stock[item] - 1
stock[item] -= 1
What is the main difference between the two and why does the second one work? And what exactly does "-=" do? I could understand if it was a different method of getting the same thing to work, but that they're not equivalent leaves me confounded. Any input would be greatly appreciated and apologies in advance for my ignorance/stupidity.
With numerical variables, the operator -= is exactly the same as assigning one less than the current value. But there's another difference between the two versions: Your solution returns a value as soon as you examine one element in your shopping list. Returning terminates the function, so only do it when you're done calculating.
The problem is likely this:
for item in food:
if stock[item] > 0:
total += prices[item]
stock[item] = stock[item] - 1
return total
Here, you're returning in the middle of the loop, so it will only ever process one item from food. In the second example, the only return statement is at the end of the loop.
What better way to show you the difference but by running a program that demonstrates the difference? Try running the following program and noting what it prints to your screen.
#! /usr/bin/env python3
def main():
stock = dict(apple=Number(100))
item = 'apple'
print('Memory location of stock[item]:', id(stock[item]))
stock[item] -= 1
print('Memory location of stock[item]:', id(stock[item]))
stock[item] = stock[item] - 1
print('Memory location of stock[item]:', id(stock[item]))
class Number:
__slots__ = '__value'
def __init__(self, value):
self.__value = value
def __repr__(self):
return repr(self.__value)
def __sub__(self, other):
type_of_self = type(self)
if isinstance(other, type_of_self):
other = other.__value
return type_of_self(self.__value - other)
def __isub__(self, other):
if isinstance(other, type(self)):
other = other.__value
self.__value -= other
return self
if __name__ == '__main__':
main()
The first operation may alter the object in place. The second operation will create a new object and replace the old one. Please note that is answers your question but not solve your problem.
I am not sure in python, however it could be that the first is decrementing the pointer (ie the actual array) and the second is decrementing the value stored in the pointer.
One way to check is to post the output with fixed values in the where the item variable is.

Iterate through list and assign a value to the variable in Python

So i'm currently working on code, which solves simple differentials. For now my code looks something like that:
deff diff():
coeffs = []
#checking a rank of a function
lvl = int(raw_input("Tell me a rank of your function: "))
if lvl == 0:
print "\nIf the rank is 0, a differential of a function will always be 0"
#Asking user to write coefficients (like 4x^2 - he writes 4)
for i in range(0, lvl):
coeff = int(raw_input("Tell me a coefficient: "))
coeffs.append(coeff)
#Printing all coefficients
print "\nSo your coefficients are: "
for item in coeffs:
print item
And so what I want to do next? I have every coefficient in my coeffs[] list. So now I want to take every single one from there and assign it to a different variable, just to make use of it. And how can I do it? I suppose I will have to use loop, but I tried to do so for hours - nothing helped me. Sooo, how can I do this? It would be like : a=coeff[0], b = coeff[1], ..., x = coeff[lvl] .
Just access the coefficients directly from the list via their indices.
If you are wanting to use the values in a different context that entails making changes to the values but you want to keep the original list unchanged then copy the list to a new list,
import copy
mutableCoeffs = copy.copy(coeffs)
You do not need new variables.
You already have all you need to compute the coefficients for the derivative function.
print "Coefficients for the derivative:"
l = len(coeffs) -1
for item in coeffs[:-1]:
print l * item
l -=1
Or if you want to put them in a new list :
deriv_coeffs = []
l = len(coeffs) -1
for item in coeffs[:-1]:
deriv_coeffs.append(l * item)
l -=1
I guess from there you want to differenciate no? So you just assign the cofficient times it rank to the index-1?
deff diff():
coeffs = []
#checking a rank of a function
lvl = int(raw_input("Tell me a rank of your function: "))
if lvl == 0:
print "\nIf the rank is 0, a differential of a function will always be 0"
#Asking user to write coefficients (like 4x^2 - he writes 4)
for i in range(0, lvl):
coeff = int(raw_input("Tell me a coefficient: "))
coeffs.append(coeff)
#Printing all coefficients
print "\nSo your coefficients are: "
for item in coeffs:
print item
answer_coeff = [0]*(lvl-1)
for i in range(0,lvl-1):
answer_coeff[i] = coeff[i+1]*(i+1)
print "The derivative is:"
string_answer = "%d" % answer_coeff[0]
for i in range(1,lvl-1):
string_answer = string_answer + (" + %d * X^%d" % (answer_coeff[i], i))
print string_answer
If you REALLY want to assign a list to variables you could do so by accessing the globals() dict. For example:
for j in len(coeffs):
globals()["elm{0}".format(j)] = coeffs[j]
Then you'll have your coefficients in the global variables elm0, elm1 and so on.
Please note that this is most probably not what you really want (but only what you asked for).

"Josephus-p‌r‌o‌b‌l‌e‌m" using list in python

I wanted to know if it will be possible to solve the Josepheus problem using list in python.
In simple terms Josephus problem is all about finding a position in a circular arrangement which would be safe if executions were handled out using a skip parameter which is known beforehand.
For eg : given a circular arrangement such as [1,2,3,4,5,6,7] and a skip parameter of 3, the people will be executed in the order as 3,6,2,7,5,1 and position 4 would be the safe.
I have been trying to solve this using list for some time now, but the index positions becomes tricky for me to handle.
a=[x for x in range(1,11)]
skip=2
step=2
while (len(a)!=1):
value=a[step-1]
a.remove(value)
n=len(a)
step=step+skip
large=max(a)
if step>=n:
diff=abs(large-value)
step=diff%skip
print a
Updated the question with code snippet, but i don't think my logic is correct.
Quite simply, you can use list.pop(i) to delete each victim (and get his ID) in a loop. Then, we just have to worry about wrapping the indices, which you can do just by taking the skipped index mod the number of remaining prisoners.
So then, the question solution becomes
def josephus(ls, skip):
skip -= 1 # pop automatically skips the dead guy
idx = skip
while len(ls) > 1:
print(ls.pop(idx)) # kill prisoner at idx
idx = (idx + skip) % len(ls)
print('survivor: ', ls[0])
Test output:
>>> josephus([1,2,3,4,5,6,7], 3)
3
6
2
7
5
1
survivor: 4
In [96]: def josephus(ls, skip):
...: from collections import deque
...: d = deque(ls)
...: while len(d)>1:
...: d.rotate(-skip)
...: print(d.pop())
...: print('survivor:' , d.pop())
...:
In [97]: josephus([1,2,3,4,5,6,7], 3)
3
6
2
7
5
1
survivor: 4
If you do not want to calculate the index, you can use the deque data structure.
My solution uses a math trick I found online here: https://www.youtube.com/watch?v=uCsD3ZGzMgE
It uses the binary way of writing the number of people in the circle and the position where the survivor sits. The result is the same and the code is shorter.
And the code is this:
numar_persoane = int(input("How many people are in the circle?\n")) #here we manually insert the number of people in the circle
x='{0:08b}'.format(int(numar_persoane)) #here we convert to binary
m=list(x) #here we transform it into a list
for i in range(0,len(m)): #here we remove the first '1' and append to the same list
m.remove('1')
m.append('1')
break
w=''.join(m) #here we make it a string again
print("The survivor sits in position",int(w, 2)) #int(w, 2) makes our string a decimal number
if you are looking for the final result only, here is a simple solution.
def JosephusProblem(people):
binary = bin(people) # Converting to binary
winner = binary[3:]+binary[2] # as the output looks like '0b101001'. removing 0b and adding the 1 to the end
print('The winner is',int(winner,2)) #converting the binary back to decimal
If you are looking for the math behind this code, go check out this video:
Josephus Problem(youTube)
it looks worse but easier to understand for beginners
def last(n):
a=[x for x in range(1,n+1)]
man_with_sword = 1
print(a)
while len(a)!=1:
if man_with_sword == a[len(a)-2]: #man_with_sword before last in circle
killed = a[len(a)-1]
a.remove(killed)
man_with_sword=a[0]
elif man_with_sword==a[len(a)-1]: #man_with_sword last in circle
killed = a[0]
a.remove(killed)
man_with_sword=a[0]
else:
i=0
while i < (len(a)//2):
i=a.index(man_with_sword)
killed = a[a.index(man_with_sword)+1]
a.remove(killed)
#pass the sword
man_with_sword=a[i+1] # pass the sword to next ( we killed next)
print (a, man_with_sword) #show who survived and sword owner
i+=1
print (a, man_with_sword,'next circle') #show who survived and sword owner
The total number of persons n and a number k, which indicates that k-1 persons are skipped and a kth person is killed in the circle.
def josephus(n, k):
if n == 1:
return 1
else:
return (josephus(n - 1, k) + k-1) % n + 1
n = 14
k = 2
print("The chosen place is ", josephus(n, k))
This is my solution to your question:
# simple queue implementation<ADT>
class Queue:
def __init__(self):
self.q = []
def enqueue(self,data):
self.q.insert(0,data)
def dequeue(self):
self.q.pop()
def sizeQ(self):
return len(self.q)
def printQ(self):
return self.q
lists = ["Josephus","Mark","Gladiator","Coward"]
to_die = 3
Q = Queue()
# inserting element into Q
for i in lists:
Q.enqueue(i)
# for size > 1
while Q.sizeP() > 1:
for j in range(1,3):
# every third element to be eliminated
Q.enqueue(Q.dequeue())
Q.dequeue()
print(Q.printQ())
def Last_Person(n):
person = [x for x in range(1,n+1)]
x = 0
c = 1
while len(person) > 1:
if x == len(person) - 1:
print("Round ", c, "- Here's who is left: ", person, "Person ", person[x], "killed person", person[0])
person.pop(0)
x = 0
c = c+1
elif x == len(person) - 2:
print("Round ", c, "- Here's who is left: ", person, "Person ", person[x], "killed person", person[x + 1])
person.pop(x+1)
x = 0
c = c + 1
else:
print("Round ", c, "- Here's who is left: ", person, "Person ", person[x], "killed person", person[x + 1])
person.pop(x + 1)
x = x + 1
c = c + 1
print("Person", person[x], "is the winner")
Last_Person(50)

How can I identify an element from a list within another list

I have been trying to make a block of code that finds the index of the largest bid for each item. Then I was going to use the index as a way to identify the person who paid that much moneys name. However no matter what i try I can't link the person and what they have gained from the auction together. Here is the code I have been writing: It has to be able to work with any information inputted
def sealedBids():
n = int(input('\nHow many people are in the group? '))#determines loop lengths
z = 0#meant to act as a counter in while loops
g = []#meant to store the names of all the people/players
s = []#meant to store name of all items being bidded on
b = []#meant to store all bids made
f = []#meant to store the each persons fair share
w = []#meant to store the highest bid for each item
q = []#trying to get it to store person linked to whatever they won
while z < n:#Process: to make the list nest lists
b.append([])
z = z + 1
z = 0
while z < n:
g.append(input('Enter a bidders name: '))#Input: Persons name
z = z + 1 #Process: store name in g[] list
z = 0
i = int(input('How many items are being bid on?'))#determines so loop lengths
while z < i:
s.append(input('Enter the name of an item: '))#input: Name of item
#process: stores names in s[] list
w.append(z)#was going to swap the info inside with the info I wanted
z = z + 1
z = 0
for j in range(n):#specifies which persons bid your taking
for k in range(i):#specifies which item is being bid on
b[j].append(int(input('How much money has {0} bid on the {1}? '.format(g[j], s[k]))))#input: takes bid for certain item
#process: stores bid in b[] list
print(' ')#adds a space when questions are being asked so it doesn't look crunched up
for j in range(n):#calculates fair share
f.append(sum(b[j])/n)#add a persons total bids then divides it by number of people bidding
for j in range(i):#meant to change the item after every bid is compared to stored highest bid
for k in range(n):#meant to change to a different persons bid to find out who bid the most money on a particular item
if w[j] < b[k][j]:#compares stored highest bid for particular item to each persons bid
w[j] = b[k][j]#if highest bid is smaller then highest bid changes to the bid that was larger
q.append(k)#trying to get it to store indentifier for whoever has highest bid so that I can use it later to link it with highest bid somehow
print(g)#meant to check outcome
print(s)#meant to check outcome
print(w)#meant to check outcome
print(q)#meant to check outcome
print(b)#meant to check outcome
print(f)#meant to check outcome
any advice is much appreciated.
You can use other structure for your bids. Instead of using different lists synchronized by index, you can use dictionary and python tuples. Maybe something like this:
items_bids = {
item1: [ (bidder1, amount), (some_other_bidder, amount), ... ],
item2: [ (bidder1, amount), (some_other_bidder, amount), ... ],
.
.
.
}
Then retrieving max. bids for each item is easy:
for item, bids in items_bids.iteritems():
print max(bids, key=lambda x: x[1])
You may design your data structure differently as this one has fast insert of bids but needs more time to retrieve the highest bid. Also retrieving all bids made by one bidder would be more work for the computer.
And for more maintainable code, you may use some objects with named fields instead of tuples.
I think it would be easiest to use dictionaries with the names as keys, that way you can see what's going on:
group_size = 3
bidders = ('Alice', 'Bob', 'Eve')
items = ('Pipe', 'Wrench')
bids = dict(((item ,dict(((bidder, 0) for bidder in bidders))) for item in items))
#>>> print bids
#{'Pipe': {'Bob': 0, 'Alice': 0, 'Eve': 0},
# 'Wrench': {'Bob': 0, 'Alice': 0, 'Eve': 0}}
#get the money amounts
for item in bids:
for bidder in bids[item]:
bids[item][bidder] = int(raw_input('How much money has {0} bid on the {1}?'.format(bidder, item)))
highest_bidders = dict((item, bidder) for item in bids for bidder in bids[item]
if bids[item][bidder] == max(bids[item].itervalues()))
print highest_bidders
This is horrible code - try this:
def sealedBids():
n = input('\nHow many people are in the group? ')
assert isinstance(n, int)
bidders = {}
for i in range(n):
bidders[raw_input('Enter a bidders name: ')] = {}
n = input('How many items are being bid on?')
assert isinstance(n, int)
bid_items = {}
for i in range(n):
bid_items[raw_input('Enter a item name: ')] = {}
del n
f = []
for bidder, bidder_bids in bidders.items():
for bid_item, bid_item_bids in bid_items.items():
bid = input('How much money has %s bid on the %s? '%(bidder, bid_items)
assert isinstance(bid, int)
bidder_bids[bid_item] = bid
bid_item_bids[bidder] = bid
print ''
f.append(sum(bidder_bids.values())/len(bidders)) # what is this for?
for bid_item, bid_item_bids in bid_items.items():
inv_bid_item_bids = dict(map(lambda item: (item[1],item[0]),bid_item_bids.items()))
high_bid = max(inv_bid_item_bids.keys())
high_bidder = inv_bid_item_bids[high_bid]
bid_items[bid_item] = (high_bidder, high_bid)

Categories