I need to write a code, where for every time someone buys a product, the key in the demand dictionary increases by 1.
I couldn't figure out how to increase a key in a dictionary byknowing the value.
This is what I tried:
demand = {"bread":0,"butter":0,"cheese":0, "water":0,"ice cream":0}
# bread is the value and 0 is the key, which I want to increase every time
def bill(buy_lst):
for item in buy_lst:
demand[demand.get(item)] += 1
When I run it says:
demand[demand.get(item)] += 1
KeyError: 0
Thank you!
Your issue is how you are adding to the dictionary. Notice the following:
demand = {"bread": 0, "butter": 0, "cheese": 0, "water": 0, "ice cream": 0}
buy_lst = ["bread", "butter", "bread"]
def bill(buy_lst):
for item in buy_lst:
print(demand.get(item))
#demand[demand.get(item)] += 1
bill(buy_lst)
This outputs:
0
0
0
So in other words, in your:
demand[demand.get(item)] += 1
You are doing:
demand[0] += 1
Which will return the error:
Traceback (most recent call last):
File "/Users/felipefaria/Desktop/test/main.py", line 11, in <module>
bill(buy_lst)
File "/Users/felipefaria/Desktop/test/main.py", line 8, in bill
demand[demand.get(item)] += 1
KeyError: 0
Instead, you should be simply referring to the item itself within the brackets, like so:
demand = {"bread": 0, "butter": 0, "cheese": 0, "water": 0, "ice cream": 0}
buy_lst = ["bread", "butter", "bread"]
def bill(buy_lst):
for item in buy_lst:
demand[item] += 1
bill(buy_lst)
print(demand)
Which will output:
{'bread': 2, 'butter': 1, 'cheese': 0, 'water': 0, 'ice cream': 0}
I think you tried to mean was 'increasing value of a key that I know'. Because only values are ints so only they can be incremented. So incrementing value would be:
demand = {"bread":0,"butter":0,"cheese":0, "water":0,"ice cream":0}
def bill(buy_lst):
for item in buy_lst:
demand[item] += 1
For clarifying, dictionary item's first part is key and second part is value.
You seems to misunderstand key and value, in your case the string are the keys and their quantity is the value
demand = {"bread": 0, "butter": 0, "cheese": 0, "water": 0, "ice cream": 0}
So what you want is increase value given a key
buy_lst[item] += 1
To use it, you need something that ask the user one product like
def bill(buy_lst):
item = None
while not item:
item = input("Please select in " + str(list(buy_lst.keys())))
item = item if item in buy_lst else None
buy_lst[item] += 1
if __name__ == '__main__':
demand = {"bread": 0, "butter": 0, "cheese": 0, "water": 0, "ice cream": 0}
bill(demand)
print(demand)
You might be confusing key and value. In demand, the keys are the items and the values are the counts.
#!/usr/bin/env python
demand = {"bread":0, "butter":0, "cheese":0, "water":0, "ice cream":0}
def bill(buy_list):
for item in buy_list:
demand[item] += 1
buy_list = ["bread", "water"]
print("Before billing:")
print(demand)
bill(buy_list)
print("After billing")
print(demand)
This prints:
Before billing:
{'bread': 0, 'butter': 0, 'cheese': 0, 'water': 0, 'ice cream': 0}
After billing
{'bread': 1, 'butter': 0, 'cheese': 0, 'water': 1, 'ice cream': 0}
Your problem is really simple. You just have to add the operator * in front of the function parameter buy_lst, so you will have *buylst. See the below code:
demand = {"bread":0,"butter":0,"cheese":0, "water":0,"ice cream":0}
# bread is the value and 0 is the key, which I want to increase every time
def bill(*buy_lst): # see this line
for item in buy_lst:
demand[item] += 1 # see this line
bill("bread", "cheese") # The client buys the products `bread` and `cheese`
print(demand)
bill("bread", "cheese", "water", "butter")
print(demand)
Output
{'bread': 1, 'butter': 0, 'cheese': 1, 'water': 0, 'ice cream': 0}
{'bread': 2, 'butter': 1, 'cheese': 2, 'water': 1, 'ice cream': 0}
Related
So, I have been thinking of this for a long time now, but can't seem to get it right. So I have to use a JSON file to make a dictionary where I get the keys: 'userIds' and the value 'completed' tasks in a dictionary. The best I got was the answer: {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 90}, with this code under:
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
for user in data1:
if user['completed'] == True:
dict1[key] += 1
print(dict1)
but I feel like this next code would be closer, but I can't figure out how to get it to work
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
for key, value in data1.items():
if user['completed'] == True:
dict1[key].update += 1
print(dict1)
After this, the output is just
" line 24, in
for key, value in data1.items():
AttributeError: 'list' object has no attribute 'items'",
And I do get why, I don't jsut know how to continue from here.
Would really appreciate anyones help, with this obnoxious task.
can u try this ?
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
keys = []
values = []
for user in data1:
if user not in keys or values:
keys.append(user['userId'])
values.append(0)
for key, value in zip(keys, values):
dict1[key] = value
print(data1)
for x in data1:
for key, value in x.items():
if key =="completed" :
if value == True:
dict1[x["userId"]] += 1
print(dict1)
Try with this approach:
import json
import requests
response1 = requests.get("https://jsonplaceholder.typicode.com/todos")
data1 = response1.json()
dict1 = {}
for user in data1:
uid = user['userId']
if user['completed']:
dict1[uid] = dict1.get(uid, 0) + 1
elif uid not in dict1:
dict1[uid] = 0
print(dict1)
print(json.dumps(dict1, indent=2))
If needed, you can also simplify the above logic using defaultdict, and leverage the fact that bool is a subclass of int:
from collections import defaultdict
dict1 = defaultdict(int)
for user in data1:
dict1[user['userId']] += user['completed']
Output:
{1: 11, 2: 8, 3: 7, 4: 6, 5: 12, 6: 6, 7: 9, 8: 11, 9: 8, 10: 12}
{
"1": 11,
"2": 8,
"3": 7,
"4": 6,
"5": 12,
"6": 6,
"7": 9,
"8": 11,
"9": 8,
"10": 12
}
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.
I'm still new to Python and this my first ever question on stackoverflow and I've been having trouble for a week to implement an A* algorithm.
The code I've got finds a goal with a straight wall but as you will see, as soon as I extend the wall below the start point and it has to go backwards or around it, it starts looping forever.
I've been banging my head against the wall trying to fix it and how to implement a raise code so it stops looping. Any help will be very much appreciated.
My code:
class Node:
"""A node class for A* Pathfinding"""
def __init__(self, parent=None, position=None):
self.parent = parent
self.position = position
self.g = 0
self.h = 0
self.f = 0
def __eq__(self, other):
return self.position == other.position
def astar(maze, start, end):
"""Returns a list of tuples as a path from the given start to the given end in the given maze"""
# Create start and end node
start_node = Node(None, start)
start_node.g = start_node.h = start_node.f = 0
end_node = Node(None, end)
end_node.g = end_node.h = end_node.f = 0
# Initialize both open and closed list
open_list = []
closed_list = []
# Add the start node
open_list.append(start_node)
# Loop until you find the end
while len(open_list) > 0:
# Get the current node
current_node = open_list[0]
current_index = 0
for index, item in enumerate(open_list):
if item.f < current_node.f:
current_node = item
current_index = index
# Pop current off open list, add to closed list
open_list.pop(current_index)
closed_list.append(current_node)
# Found the goal
if current_node == end_node:
path = []
current = current_node
while current is not None:
path.append(current.position)
current = current.parent
return path[::-1] # Return reversed path
# Generate children
children = []
for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]: # Adjacent squares
# Get node position
node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1])
# Make sure within range
if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] > (
len(maze[len(maze) - 1]) - 1) or node_position[1] < 0:
continue
# Make sure walkable terrain
if maze[node_position[0]][node_position[1]] != 0:
print("node -", node_position[0],node_position[1], "is blocked")
continue
# Create new node
new_node = Node(current_node, node_position)
# Append
children.append(new_node)
# Loop through children
for child in children:
# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue
# Create the f, g, and h values
child.g = current_node.g + 1
child.h = ((child.position[0] - end_node.position[0]) ** 2) + (
(child.position[1] - end_node.position[1]) ** 2)
child.f = child.g + child.h
# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
# Add the child to the open list
open_list.append(child)
def main():
maze = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
start = (0, 0)
end = (1, 8)
path = astar(maze, start, end)
print(path)
main()
You have these two pieces:
# Child is on the closed list
for closed_child in closed_list:
if child == closed_child:
continue
# Child is already in the open list
for open_node in open_list:
if child == open_node and child.g > open_node.g:
continue
The continue will continue the inner for loop. Consequently, it does not have any effect. You are rather looking for something like this:
# Child is on the closed list
is_in_closed = False
for closed_child in closed_list:
if child == closed_child:
is_in_closed = True
break
if is_in_closed:
continue
# Child is already in the open list
is_in_open = False
for open_node in open_list:
if child == open_node and child.g > open_node.g:
is_in_open = True
break
if is_in_open:
continue
Two more comments:
Your distance measure only counts the number of steps. Therefore, a diagonal is as expensive as a horizontal / vertical step. You might want to change this and get the actual length or an approximation of it to find the truly shortest path.
Your heuristic is the squared distance to the target. This is not an admissible heuristic because it over-estimates the actual cost to the target. As a result, you might not find the correct shortest path. For your cost function (number of steps), a better and admissible heuristic would be max(child.position[0] - end_node.position[0], child.position[1] - end_node.position[1]) (you need at least this number of steps to get to the target).
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 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