I wan't to create a program that select 2 random items from two different dictionaries. Now I wan't to check if the sum of those items is equal to the value provided by the User. And i wan't to perform this action until i find 2 random items from different dictionaries that add up to the number entered by the User.
Here is what i tried to do:
import random
credit=int(raw_input("Please enter your amount: "))
food=dict([(10, 'Lays'), (10,'Pepsi'), (10,'Burger')])
toys=dict([(10, 'Car'), (10,'Train'), (10,'Chess')])
ranf=random.choice(food.keys())
rant=random.choice(toys.keys())
while int(ranf)+int(rant)!=credit:
ranf=random.choice(food.keys())
rant=random.choice(toys.keys())
print(ranf)
print(food[ranf])
print(rant)
print(food[rant])
When i try to run this code it fails to print those two random items. I'm not getting any error message. Please run this code and help me out.
Thank You
The problem lies within the fact, that you create your dictionaries with duplicate keys - effectively, your food dictionary contains only (10,'Burger') and your toys dictionary has only (10,'Chess') item (they both contain only most recently added item, which replaced all the previous ones). The simplest and quickest fix would be to abandon the usage of a dictionary:
import random
credit=20
food=[(10, 'Lays'), (10,'Pepsi'), (10,'Burger')]
toys=[(10, 'Car'), (10,'Train'), (10,'Chess')]
ranf=random.choice(food)
rant=random.choice(toys)
while int(ranf[0])+int(rant[0])!=credit:
ranf=random.choice(food)
rant=random.choice(toys)
print(ranf)
print(rant)
food.keys() only returns unique keys. So, essentially the only list of keys returned by the food.keys() function is [10].
ex if you make a dictionary like food = dict([(10, 'Lays'), (15,'Pepsi'), (15,'Burger')])
then the list returned by food.keys() will be [10,15] and not [10,15,15] which is what you expect. So, in your code, if ranf = 10, then interpreter takes up the latest value assigned to that key.
Therefore, the random.choice() you are using goes in vain.
Also, there is a silly mistake in your code, you wrote print(food[rant]) instead of writing print(toys[rant]).
It would be better if you don't use a list, otherwise, make the keys different.
Related
I am writing a program which saves the last 3 scores in a text file for each user of my game. I have already written the code that saves it I am now bringing the data back into the program which will work out the users high scores . I also already have the scores saved in separate lists All users 1st score saved in 1 list all users 2nd score in another and the same for 3rd score. I am trying to put these in their own high score list so when I joint the lists with the names(in another list) I will be able to sort by score but will be attached to name.
Bellow is the code I have written:
for i in range (2):
if score1[i] > score2[i] or score1[i]> score3[i]:
highscores.append(score1[i])
elif score2[i] > score1[i] or score2[i] > score3[i]:
highscores.append(score2[i])
elif score3[i] > score1[i] or score3[i] > score2[i]:
highscores.append(score3[i])
By the way it is in a for loop for i in range 2 as their are currently only 2 users. I know I'm being incredibly stupid by having the or as it means only one event needs to be true for it to work but when I tried and it didn't work either. Please work along these lines as my tutor said 'I had the right idea' I also hope this helps anyone else which is comparing list items with integers in python as I couldn't find anything on the internet .
Thanks,
I await guidance
You want to use and, not or.
You can also use a < b < c syntax instead of using and.
What you should really do is use Python's built-in max function. A clean, single-liner instead of that 6-line if-elif block.
highscores.append(max(score1[i], score2[i], score3[i]))
Probably not allowed for this assignment, but for others who need to do something similar, the easy/fast way to select the top 3 values from a large sequence of values is to use heapq.nlargest. If you have multiple sequences, you can itertools.chain them to avoid concatenating (avoid increases in peak memory usage). You can even attach the names (with zip and itertools.repeat) to each input sequence so the selected high scores include the associated user:
from heapq import nlargest
from itertools import chain, repeat
highscores = nlargest(3, chain(zip(score1, repeat('user1')),
zip(score2, repeat('user2')),
zip(score3, repeat('user3'))))
highscores would then be a list with three elements (from highest to lowest score, ties broken by user name), each element being a tuple of the form (score, username).
This question already has answers here:
TypeError: unhashable type: 'dict', when dict used as a key for another dict [duplicate]
(2 answers)
Closed 6 years ago.
I was writing a basic uno-type card game, and wanted to be able to (while making 7 cards for the player) check if the value was already in the player's deck (I used random). I got an unhashable dict error, and some other questions were about the same error, but in different parts of code. Anyways, here's my code.
def CardGame():
nm=8
clist=["Red","Blue","Green","Yellow"]
nlist=[]
for i in range(0,10):
nlist.append(i)
pd={}
deck={"Red":0,"Red":1,"Red":2,"Red":3,"Red":4,"Red":5,"Red":6,"Red":7,"Red":8,"Red":9,"Blue":0,"Blue":1,"Blue":2,"Blue":3,"Blue":4,"Blue":5,"Blue":6,"Blue":7,"Blue":8,"Blue":9,"Green":0,"Green":1,"Green":2,"Green":3,"Green":4,"Green":5,"Green":6,"Green":7,"Green":8,"Green":9,"Yellow":0,"Yellow":1,"Yellow":2,"Yellow":3,"Yellow":4,"Yellow":5,"Yellow":6,"Yellow":7,"Yellow":8,"Yellow":9}
for i in range(1,nm):
c=random.choice(clist)
d=random.choice(nlist)
if ({c:d}) in deck:
pd.update({c:d})
del deck[c:d]
else:
nm=nm+1
print("%s %s"%(c,d))
With if ({c:d}) in deck:, you are checking if the dictionary {c:d} is present as a key in the dictionary deck. Dictionaries are unhashable (as mutable data types generally are), and a dictionary key must be hashable, so instead of just telling you "no," it throws the error you saw. A dictionary will never be present as a key in a dictionary.
Also, as noted in the comments, dictionary keys are unique, so the dictionary you made cannot exist as it appears. Consider a different data structure, like a list of tuples (e.g. [('Red', 1), ('Red', 2),...), or a dictionary with list values (e.g. {'Red':[1, 2, 3,...], 'Blue':[1, 2, 3,...],...}).
Your specific error comes from how you're trying to check for member ship in the dictionary. The in operator checks if a give key exists, but you're passing a one-element dictionary rather than just a key (you get that specific exception because dictionaries are not valid keys since they can't be hashed).
However, as Kevin commented above, you've also got a larger issue where your deck dictionary doesn't contain what you want it to contain, since you're reusing the same keys repeatedly. A dictionary can only have a single value for a given key (though the value could be a list or tuple, or some other type that contains additional items).
There are a variety of ways you can fix this issue. A set containing 2-tuples would work sort of like how you wanted your dict to work. You can add and remove elements, and efficiently check if a tuple is in the set or not with the in operator.
However, looking at what you're actually doing, I think a larger change to your algorithm will be much better. Rather than randomly picking a color and number and then checking if it is still in your deck, you should instead just select a random element from the collection directly. Rather than looping to select multiple values, use random.sample to select all the values at once. Or, if you're going to be taking more random values from the deck later, shuffle it and take a slice.
Here's a version of the code that uses random.shuffle on a list of 2-tuples, then slices off 10 of them from the end to become the pd list.
import itertools
import random
def CardGame():
nm=8
clist = ["Red","Blue","Green","Yellow"]
nlist = list(range(0,10)) # this is easier than looping to append the values
deck = list(itertools.product(clist, nlist)) # much easier than naming them all
random.shuffle(deck)
pd = deck[-10:] # slice 10 items from the end
del deck[-10:] # and then remove them from the list (fairly efficient at the end)
I was working on a dictionary, but I came up with an issue. And the issue is, I want to be able to use more than 1 number in order to reference a key in a dictionary.
For example, I want the range of numbers between 1 and 5 to be all assigned to, let's say, "apple". So I came up with this:
my_dict['apple'] = range(1,5)
At the program's current state, its far from being able to run, so testing is an issue, but I do not receive any issues from my editor. I was just wondering, is this the correct way to go about this? Or is there a better way?
Thanks.
EDIT:
A little more info: I want to make a random integer with the randint function. Then, after Python has generated that number, I want to use it to call for the key assigned to the value of the random integer. Thing is, I want to make some things more common than others, so I want to make the range of numbers I can call it with larger so the chance of the key coming up becomes likelier. Sorry if it doesn't make much sense, but at the current state, I really don't even have code to show what I'm trying to accomplish.
You have the dictionary backwards. If you want to be able to recall, e.g., 'apple' with any of the numbers 1-5, you'd need the numbers to be the keys, not the values.
for i in range(1,6): # range(a,b) gives [a,b)
my_dict[i] = 'apple'
etc. Then, my_dict[4] == 'apple' and the same is true for the other values in the range.
This can create very large dictionaries with many copies of the same value.
Alternately, you can use range objects as dictionary keys, but the testing will be a bit more cumbersome unless you create your own class.
my_dict[range(1,6)] = 'apple'
n = random.randint(1, 5)
for key in my_dict:
if n in key:
print(my_dict[key])
...prints apple.
The value in a dictionary can be any arbitrary object. Whether it makes sense to use a given type or structure as a value only makes sense in the context of the complete script, so it is impossible to tell you whether it is the correct solution with the given information.
I am very new to python and my apologies is this has already been answered. I can see a lot of previous answers to 'sort' questions but my problem seems a little different from these questions and answers.
I have a list of keys, with each key contained in a tuple, that I am trying to sort. Each key is derived from a subset of the columns in a CSV file, but this subset is determined by the user at runtime and can't be hard coded as it will vary from execution to execution. I also have a datetime value that will always form part of the key as the last item in the tuple (so there will be at least one item to sort on - even if the user provides no additional items).
The tuples to be sorted look like:
(col0, col1, .... colN, datetime)
Where col0 to colN are based on the values found in columns in a CSV file, and the 'N' can change from run to run.
In each execution, the tuples in the list will always have the same number of items in each tuple. However, they need to be able to vary from run to run based on user input.
The sort looks like:
sorted(concurrencydict.keys(), key=itemgetter(0, 1, 2))
... when I do hard-code the sort based on the first three columns. The issue is that I don't know in advance of execution that 3 items will need to be sorted - it may be 1, 2, 3 or more.
I hope this description makes sense.
I haven't been able to think of how I can get itemgetter to accept a variable number of values.
Does anyone know whether there is an elegant way of performing a sort based on a variable number of items in python where the number of sort items is determined at run time (and not based on fixed column numbers or attribute names)?
I guess I'll turn my comment into an answer.
You can pass a variable number of arguments (which are packed into an iterable object) by using *args in the function call. In your specific case, you can put your user-supplied selection of column numbers to sort by into a sort_columns list or tuple, then call:
sorted_keys = sorted(concurrencydict.keys(), key=itemgetter(*sort_columns))
I have a dictionary (index2) of 3-item lists, organized by key from 0-150 or so. I need to sort it into another dictionary, with the following constraints:
1.) all items attached to one key must stay together in the second dictionary
2.) length of items in the second dictionary must all be the same. To help with this one, I divided the total number of items in the first dictionary by the number of keys in the second and attached it to a variable so it can be used as a limiting factor.
This is what I have so far, however when I run it, it doesn't actually append anything to the target dictionary.
for key,runs in index2.iteritems():
for a in mCESrange:
if index2[key][0] in mCESdict[a]:
pass
elif len(mCESdict[a]) < mCESlength:
pass
else:
mCESdict[a].extend(index2[key])
Your problem description isn't really clear, and non-working code rarely helps to clarify, but I suspect that this line is your problem: elif len(dict[a]) < length.