I am very new to python and looking for a way to simplify the following:
if atotal == ainitial:
print: "The population of A has not changed"
if btotal == binitial:
print: "The population of B has not changed"
if ctotal == cinitial:
print: "The population of C has not changed"
if dtotal == dinitial:
print: "The population of D has not changed"
Obviously _total and _initial are predefined.
Thanks in advance for any help.
You can use two dictionaries:
totals = {'A' : 0, 'B' : 0, 'C' : 0, 'D' : 0}
initials = {'A' : 0, 'B' : 0, 'C' : 0, 'D' : 0}
for k in initials:
if initials[k] == totals[k]:
print "The population of {} has not changed".format(k)
A similar way is first determining not changed populations:
not_changed = [ k for k in initials if initials[k] == totals[k] ]
for k in not_changed:
print "The population of {} has not changed".format(k)
Or, you can have a single structure:
info = {'A' : [0, 0], 'B' : [0, 0], 'C' : [0, 0], 'D' : [0, 0]}
for k, (total, initial) in info.items():
if total == initial:
print "The population of {} has not changed".format(k)
You could organize all the pairs into a dictionary and cycle though all the elements:
populations = { 'a':[10,80], 'b':[10,56], 'c':[90,90] }
for i in populations:
if populations[i][1] == populations[i][0]:
print(i + '\'s population has not changed')
Another way (2.7) using an ordered dictionary:
from collections import OrderedDict
a = OrderedDict((var_name,eval(var_name))
for var_name in sorted(['atotal','ainitial','btotal','binitial']))
while True:
try:
init_value = a.popitem(last=False)
total_value = a.popitem(last=False)
if init_value[1] == total_value[1]:
print ("The population of {0} has "
"not changed".format(init_value[0][0].upper()))
except:
break
Related
I am new to coding in python. This is a craps game. It is played 50 times and I am able to output the wins and losses, I am also able to keep track of the rollcount. I want to make a dictionary that keeps track of the number of rolls it takes to win a game and loose a game(one win and one loose dictionary). For example this would be the key and value for an item. 4 : 20 meaning that it took four rolls to win or loose (depending if it was a win dictionary or a loss dictionary)when the game was played fifty times.
This is what I have so far. I'm eager to learn but I am stuck here. I would appreciate any help.
import random
from collections import Counter
def roll_dice():
"""Roll two dice and return their face values as a tuple."""
die1 = random.randrange(1, 7)
die2 = random.randrange(1, 7)
return (die1, die2) # pack die face values into a tuple
def display_dice(dice):
"""Display one roll of the two dice."""
die1, die2 = dice # unpack the tuple into variables die1 and die2
print(f'Player rolled {die1} + {die2} = {sum(dice)}')
def clear_values():
"""Clear rollcount """
gamecount = 0
wincount = 0
losecount = 0
rollcount = 0
list_of_win = {}
list_of_loss = {}
win_roll = {1:0, 2 : 0, 3 : 0, 4 : 0, 5 : 0, 6 : 0, 7 : 0, 8 : 0, 9 : 0, 10 : 0, 11 : 0, 12 : 0, 13 : 0, 14 : 0, 15 : 0, 16 : 0, 17 : 0, 18 : 0, 19 : 0}
lose_roll = {1:0, 2 : 0, 3 : 0, 4 : 0, 5 : 0, 6 : 0, 7 : 0, 8 : 0, 9 : 0, 10 : 0, 11 : 0, 12 : 0, 13 : 0, 14 : 0, 15 : 0, 16 : 0, 17 : 0, 18 : 0, 19 : 0}
while gamecount != 50:
rollcount = 0
die_values = roll_dice()
rollcount += 1 # first roll
display_dice(die_values)
# determine game status and point, based on first roll
sum_of_dice = sum(die_values)
if sum_of_dice in (7, 11): # win
wincount += 1
gamecount += 1
list_of_win = [{rollcount : key, "nbr": value} for key, value in Counter(list_of_win).values()]
game_status = 'WON'
elif sum_of_dice in (2, 3, 12): # lose
losecount += 1
list_of_loss =[{rollcount : key, "nbr": value} for key, value in Counter(list_of_loss).values()]
gamecount += 1
game_status = 'LOST'
else: # remember point
game_status = 'CONTINUE'
my_point = sum_of_dice
print('Point is', my_point)
# continue rolling until player wins or loses
while game_status == 'CONTINUE':
die_values = roll_dice()
rollcount += 1
display_dice(die_values)
sum_of_dice = sum(die_values)
if sum_of_dice == my_point: # win by making point
game_status = 'WON'
wincount += 1
list_of_win =[{rollcount : key, "nbr": value} for key, value in Counter(list_of_win).values()]
gamecount += 1
elif sum_of_dice == 7: # lose by rolling 7
game_status = 'LOST'
losecount += 1
list_of_loss =[{rollcount : key, "nbr": value} for key, value in Counter(list_of_loss).values()]
gamecount += 1
# display "wins" or "loses" message
if game_status == 'WON':
print('Player wins')
else:
print('Player loses')
print(f'| {wincount} = wins |\n| {losecount} = losses |\n| {gamecount} = games played |')
You are on the right track, but don't need the Counter object.
For the explanation, let's just take keeping track of wins. You'll be able to track losses similarly.
Instead of the places you assign list_of_wins, you can just increment the counter stored in win_rolls. You've already initialized the value for that rollcount in the dictionary to 0, so we can just add 1.
win_roll[rollcount] += 1
You'll have to do this in the two places, where you assign list_of_win.
Then at the end of the program you can print out all the keys and values in the dictionary.
for key, value in win_roll.items():
print(f'{key} : {value}')
Of course, it's possible that it could take more than 19 rolls to win a game, in which case this code won't work. Take the example of it taking 30 rolls to win or lose (unlikely but still statistically possible). Since you haven't initialized an entry in the dictionary for the key of 30, there won't be a value there to increment.
In this case we can check for the existence of the key in the dictionary and act appropriately. Instead of
win_roll[rollcount] += 1
We use
if rollcount in win_roll:
win_roll[rollcount] += 1
else:
win_roll[rollcount] = 1
You can do the same for loss_roll to track the number of times each rollcount won or lost.
Please consider the below Python code:
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
for k in dict2:
usr_id = 3
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
In the "dict2", if values == 1 then it is active or if values == 0 then it is inactive. Here, match the usr_id with key id in dict2.
Case 1: dict2 = {'1': 1, '2': 1, '3': 1, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==1. so allotted id=3.
Case 2: dict2 = {'1': 1, '2': 1, '3': 0, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==0 . Then next active id is allotted.So allotted id=4.
Case 3: dict2 = {'1': 1, '2': 1, '3': 0, '4': 0, '5': 1}. Now usr_id==3 and dict2 key '3' & '4'==0 . So the next nearest active id to the usr_id want allocate (is nothing but key id '2').How to do it?
Guide me for my case 3 scenario. Thanks in advance.
Assuming you want no efficiency changes to the code, you're overwriting the usr_id in the for k in dict2 loop.
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
usr_id = 3 # Move this out of the loop
for k in dict2:
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
You can write this code to do more checks and utilise the dictionary structure a bit more...
def allot():
# Variables to Enter
dict2 = {1: 1, 2: 1, 3: 0, 4: 0, 5: 1}
usr_id = 3
# Boolean Variables
allotted_id = None
upper_exhausted = False
lower_exhausted = False
# Need to calculate the min and max to know when to stop searching
max_id = max(dict2.keys())
min_id = min(dict2.keys())
# Check the initial ID
if dict2[usr_id] == 0:
print("ID {} inactive. Continuing search.".format(usr_id))
else:
allotted_id = usr_id
# Run two searches - one increasing through the dictionary
# and one decreasing through the dictionary
upper_usr_id = usr_id + 1
lower_usr_id = usr_id - 1
# Run loop whilst the max and min dict key haven't been reached
# AND there's no allotted ID.
while not allotted_id:
if not upper_exhausted:
if dict2[upper_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(upper_usr_id))
if upper_usr_id < max_id:
upper_usr_id += 1
else:
upper_exhausted = True # Maximum has been reached
else:
allotted_id = upper_usr_id
if not lower_exhausted:
if dict2[lower_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(lower_usr_id))
if lower_usr_id > min_id:
lower_usr_id -= 1
else:
lower_exhausted = True # Minimum has been reached
else:
allotted_id = lower_usr_id
# Exhausted all values - No Data value
if upper_exhausted and lower_exhausted:
allotted_id = -999
if allotted_id == -999:
print("Couldn't allot an ID")
else:
print("Allotted ID is: {}".format(allotted_id))
allot()
I would use numpy:
user_ids = np.array(range(5))
valid_user = np.array([1, 1, 0, 0, 1])
anchor_id = 2
dist_from_anchor = np.abs(user_ids - anchor_id)
dist_from_anchor[valid_user == 0] = len(user_ids) +1 #will not be the min
print(np.argmin(dist_from_anchor))
I used the minimum user_id as 0 (just a cs thing...) but you can easily change it to be 1...
I suggest a different approach (Dont know how flexible you are with your approach)-
Store your data like this
dict2 = {"1": {1, 2, 5}, "0": {3, 4}} # 1 for available Ids and 0 for allocated
Now for any incoming user id
if usr_id in dict2["1"]:
allotted_id = usr_id
elif usr_id in dict2["0"]:
# either return the first available Or
# traverse and return the next higher user id available
else:
# exception
My question would be how I withdraw winner based on highest score?
since u cant sort in dictionaries
i tried this with lists, but then name wouldnt appear, only the score...
a = {'name_a':0}
b = {'name_b':0}
c = {'name_c':0}
d = {'name_d':0}
e = {'name_e':0}
print("Each time someone scores a point, the letter of his name is typed in lowercase. If someone loses a point, the letter of his name is typed in uppercase")
score = input('Enter series of charachters indicating who scored a poitn: ')
for i in score:
if i == 'a':
a['name_a'] += 1
if i == 'A':
a['name_a'] -= 1
if i == 'b':
b['name_b'] += 1
if i == 'B':
b['name_b'] -= 1
if i == 'c':
c['name_c'] += 1
if i == 'C':
c['name_c'] -= 1
if i == 'd':
d['name_d'] += 1
if i == 'D':
d['name_d'] -= 1
if i == 'e':
e['name_e'] += 1
if i == 'E':
e['name_e'] -= 1
print(a,b,c,d,e)
print('Winner is: ', )
This will work:
max((i, name) for d in (a,b,c,d,e) for name, i in d.items())[1]
you probably want to use a single dict, instead of one for each, like such:
scores = {
'a': 0,
'b': 0,
'c': 0,
'd': 0,
'e': 0,
}
And then you can keep track of the highest scoring player as points are calculated:
point_scored = input('Enter series of charachters indicating who scored a point: ')
for i in point_scored:
if not scores.get(i) is None:
scores[i] += 1
elif not scores.get(i.lower()) is None:
scores[i.lower()] -= 1
else:
print(str(i) + ' is not a valid player...')
winner = max(scores, key=scores.get)
print(scores)
print('Winner is ' + winner)
max_key = ""
max_val = 0
for key, value in d.items():
if (value > max_val):
max_val = value
max_key = key
Is this what you mean?
i found the answer
winner = (sorted(d.items(), key = lambda x: int(x[1]), reverse = True))
I am creating a vote system to pick a team, butI have hit a wall. The code works fine up until the point of decision2. Any ideas?
Please remember this code is a work-in-progress.
teamNames = []
teams = {}
easy = [0, 1, 2, 3, 4, 5]
NoVotes1 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes2 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes3 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes4 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
NoVotes5 = {'first' : 0, 'second' : 0, 'third' : 0, 'fourth' : 0, 'fifth' : 0}
while True:
print("Enter team name " + str(len(teamNames) + 1) + (" or press enter to stop."))
name = input()
if name == "":
break
teamNames = teamNames + [name]
print("The team names are ")
for name in teamNames:
print(" " + name)
for name in teamNames:
teams[name] = 0
teamNames.sort()
print("In alphabetical order the team names are ")
print()
print(str(teamNames))
y = 0
decision1 = input("Would you like to enter a vote? (1 = yes, 2 = no)")
while decision1 == "1":
print("ok great, where did " + teamNames[y] + " come")
decision2 = input()
if decision2 == "1":
teams[easy[y]] = teams[easy[y]] + 1
y = y + 1
if decision1 == "2":
break
elif n == "6":
break
I think I see what you've misunderstood. Standard dictionaries, unlike lists, have no concept of order or the nth (e.g. first) item. They are just associations between keys and values. When you say teams[key] = value you are setting the value at key, when you say value = teams[key] you are getting the value at key. It's possible that key is a number but it doesn't have to be, and if key is 1 then that doesn't mean the second value in the dictionary, or the first, or any other position. Perhaps this example interactive session will help you understand:
>>> dictionary = {"a": "b", "c": "d"}
>>> dictionary = {"a": "b", "c": "d", 5: "e"}
>>> dictionary[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1
>>> dictionary["c"]
'd'
>>> dictionary[5]
'e'
What you want is teams[teamNames[y]] = teams[teamNames[y]] + 1, which by the way can be shortened to teams[teamNames[y]] += 1.
Does all that make sense? If not I suggest doing some simple experiments with dictionaries until you understand them better. Play around with the in the shell. Write some small programs using dictionaries to see what they do.
I'm doing course in codeacademy and i'm on lession Something of Value
In my final task i have to For each key in prices, multiply the number in prices by the number in stock. Print that value into the console and then add it to total.
My code:
for cena in prices:
total = prices[cena]*stock[cena]
print total
It's printing 0.
I also tried this:
for cena in prices:
for ilosc in stock:
total = prices[cena]*stock[ilosc]
print total
It's also returning 0.
EDIT: Whole code:
prices = {
"banana" : 4,
"apple" : 2,
"orange" : 1.5,
"pear" : 3,
}
stock = {
"banana" : 6,
"apple" : 0,
"orange" : 32,
"pear" : 15,
}
for key in prices:
print key
print "price: %s" % prices[key]
print "stock: %s" % stock[key]
total = 0
for cena in prices:
for ilosc in stock:
total = prices[cena]*stock[ilosc]
print total
It's printing 0 because the product of the "last" items in the dictionary is 0. If you want to know the products of each item in turn then you need to print inside the loop. If you want a total then you should either add to the existing value or use sum() with a generator expression (genex).
This worked for me
prices = {
"banana" : 4,
"apple" : 2,
"orange" : 1.5,
"pear" : 3,
}
stock = {
"banana" : 6,
"apple" : 0,
"orange" : 32,
"pear" : 15,
}
for key in prices:
print key
print "price: %s" % prices[key]
print "stock: %s" % stock[key]
total = 0
for key in prices:
price_of_stock = prices[key] * stock[key]
print price_of_stock
total = total + price_of_stock
print total
What about:
from itertools import chain
results = dict()
for k, v in chain(prices.iteritems(), stock.iteritems()):
if k in results:
results[k] *= v
else results[k] = v
I am also doing this course.My ansewer as below:
total=0
sums=0
for key in price:
print key
print "price: %s" % price[key]
print "stock: %s" % stock[key]
for x in stock:
sums=stock[x]*price[x]
print sums
total+=sums
print total
Mybe can give you a ref.