Secret Santa generator with IF condition - if-statement

I´m new at this, trying to make in python a secret santa generator, but i want to make condition that some family members cant give to each other (Example : parents and own children | only gift other relatives)
I have some code and it does the random generation, but I can´t make the condition that I want.
Can someone help?
def Santa(names, draw):
matches= []
while names:
giver = names.pop() #chooses giver and removes name
receiver = random.choice(draw) #picks random to receive
if giver != receiver:
matches.append([giver, receiver]) #adds pair
draw.remove(receiver) #removes person from receiving list
if giver
else:
names.append(giver) #if names are the same, adds name back to list
return matches
family1=['Carlos', 'Minda', 'Ana', 'Catarina']
family2=['Paulo','Alexandre','Luquinhas']
family3=['Ivone','Lucas','Susana','Pedro']
family4=['Tia Ângela','Mãezinha Avó']

Related

How do I create an unknown number of variables based on user input in python 2.7 (i.e. player names based on number of players)?

I'm a noob, working on making the Yahtzee game I programmed multiplayer. In Python 2.7, I want to have a prompt where a user can enter the number of players, i.e. 2, 3,4, 2007 etc., after which for the number of players entered, i.e. 3, the user will enter the names of the players, i.e. Mike, Tom, Jim, which I can then use in my program to keep score (i.e. Mike's score is 7, he's pretty bad, Jim has 250, he's pretty good etc.). I've seen suggestions to use dictionaries, classes and arrays, but I'm lost as to which one is best, and worst still, can't make what I'm trying to do work.
from collections import defaultdict
d = defaultdict(int)
d = {}
players = raw_input('How many players?')
players = int(players)
for i in range (1,players+1):
d = raw_input('Enter player name')
print d
my code on Repl.it is here
In your for loop you are assigning whatever the player types in as a name to be equal to d. d is therefore instantly no longer referring to any dictionary, but a string.. whatever the name was. A particular variable can only refer to one object at a time. Logically this is straight-forward if you think about what happens when you re-assign a variable to something new, how could the interpreter possibly differentiate between multiple possible objects when all it's provided is the label d..
Try something like this, a dict seems good to me:
players_dict = {}
num_players = raw_input("Enter number of players: ")
for i in num_players:
name = raw_input("Enter name for player %s:" % i)
# set initial score to 0
players_dict[name] = 0
Thanks all for the help. With your help, I figured out the following code (using a list and appending to it), which worked:
player_names = []
input_players = int(raw_input('how many players?'))
for i in range(0,input_players):
name = raw_input('enter player name')
name = name.upper()
player_names.append(name)
#using my new player names to iterate through turns:
for i in range(0,13):
for i in player_names:
print i # placeholder for my turn function

compare two dictionary, one with list of float value per key, the other one a value per key (python)

I have a query sequence that I blasted online using NCBIWWW.qblast. In my xml blast file result I obtained for a query sequence a list of hit (i.e: gi|). Each hit or gi| have multiple hsp. I made a dictionary my_dict1 where I placed gi| as key and I appended the bit score as value. So multiple values for each key.
my_dict1 = {
gi|1002819492|: [437.702, 384.47, 380.86, 380.86, 362.83],
gi|675820360| : [2617.97, 2614.37, 122.112],
gi|953764029| : [414.258, 318.66, 122.112, 86.158],
gi|675820410| : [450.653, 388.08, 386.27] }
Then I looked for max value in each key using:
for key, value in my_dict1.items():
max_value = max(value)
And made a second dictionary my_dict2:
my_dict2 = {
gi|1002819492|: 437.702,
gi|675820360| : 2617.97,
gi|953764029| : 414.258,
gi|675820410| : 450.653 }
I want to compare both dictionary. So I can extract the hsp with the highest score bits. I am also including other parameters like query coverage and identity percentage (Not shown here). The finality is to get the best gi| with the highest bit scores, coverage and identity percentage.
I tried many things to compare both dictionary like this :
First code :
matches[]
if my_dict1.keys() not in my_dict2.keys():
matches[hit_id] = bit_score
else:
matches = matches[hit_id], bit_score
Second code:
if hit_id not in matches.keys():
matches[hit_id]= bit_score
else:
matches = matches[hit_id], bit_score
Third code:
intersection = set(set(my_dict1.items()) & set(my_dict2.items()))
Howerver I always end up with 2 types of errors:
1 ) TypeError: list indices must be integers, not unicode
2 ) ... float not iterable...
Please I need some help and guidance. Thank you very much in advance for your time. Best regards.
It's not clear what you're trying to do. What is hit_id? What is bit_score? It looks like your second dict is always going to have the same keys as your first if you're creating it by pulling the max value for each key of the first dict.
You say you're trying to compare them, but don't really state what you're actually trying to do. Find those with values under a certain max? Find those with the highest max?
Your first code doesn't work because I'm assuming you're trying to use a dict key value as an index to matches, which you define as a list. That's probably where your first error is coming from, though you haven't given the lines where the error is actually occurring.
See in-code comments below:
# First off, this needs to be a dict.
matches{}
# This will never happen if you've created these dicts as you stated.
if my_dict1.keys() not in my_dict2.keys():
matches[hit_id] = bit_score # Not clear what bit_score is?
else:
# Also not sure what you're trying to do here. This will assign a tuple
# to matches with whatever the value of matches[hit_id] is and bit_score.
matches = matches[hit_id], bit_score
Regardless, we really need more information and the full code to figure out your actual goal and what's going wrong.

How to add an unlimited number of class instances with user input in python

I am trying to use
class reader
def __init__(self, name, booksread)
self.name = name
self.booksread = booksread
while True
option = input("Choose an option: ")
if option = 1:
#What to put here?
I want to create an unlimited number of instances of the reader class, But I could only figure out how to do it a limited number of times by using variables for the class. I also need to call the info later (without losing it). Is it possible to do this with a class? Or would I be better off with a list, or dictionary?
First: if option == 1: is always false in python 3, input only reads strings there.
Second: python lists can be expanded until you run out of RAM.
So the solution would be to create a list in the surrounding code and call append on that every time you have a new item:
mylist = []
while True:
mylist.append(1)
It's perfectly possibly to populate a data structure (such as a list or dict) with instances of a class, given your code example you could put the instances into a list:
class reader
def __init__(self, name, booksread)
self.name = name
self.booksread = booksread
list = []
while True:
option = input("Choose an option: ")
if option == 1:
list.append(reader(name,booksread))
Note: I don't know how you are obtaining the values for 'name' or 'booksread', so their values in the list.append() line are just placeholders
To access the instances in that list, you can then iterate over it, or access elements by their indexes, e.g.
# access each element of the list and print the name
for reader in list:
print(reader.name)
#print the name of the first element of the list
print(list[0].name)

Iterating over a large unicode list taking a long time?

I'm working with the program Autodesk Maya.
I've made a naming convention script that will name each item in a certain convention accordingly. However I have it list every time in the scene, then check if the chosen name matches any current name in the scene, and then I have it rename it and recheck once more through the scene if there is a duplicate.
However, when i run the code, it can take as long as 30 seconds to a minute or more to run through it all. At first I had no idea what was making my code run slow, as it worked fine in a relatively low scene amount. But then when i put print statements in the check scene code, i saw that it was taking a long time to check through all the items in the scene, and check for duplicates.
The ls() command provides a unicode list of all the items in the scene. These items can be relatively large, up to a thousand or more if the scene has even a moderate amount of items, a normal scene would be several times larger than the testing scene i have at the moment (which has about 794 items in this list).
Is this supposed to take this long? Is the method i'm using to compare things inefficient? I'm not sure what to do here, the code is taking an excessive amount of time, i'm also wondering if it could be anything else in the code, but this seems like it might be it.
Here is some code below.
class Name(object):
"""A naming convention class that runs passed arguments through user
dictionary, and returns formatted string of users input naming convention.
"""
def __init__(self, user_conv):
self.user_conv = user_conv
# an example of a user convention is '${prefix}_${name}_${side}_${objtype}'
#staticmethod
def abbrev_lib(word):
# a dictionary of abbreviated words is here, takes in a string
# and returns an abbreviated string, if not found return given string
#staticmethod
def check_scene(name):
"""Checks entire scene for same name. If duplicate exists,
Keyword Arguments:
name -- (string) name of object to be checked
"""
scene = ls()
match = [x for x in scene if isinstance(x, collections.Iterable)
and (name in x)]
if not match:
return name
else:
return ''
def convert(self, prefix, name, side, objtype):
"""Converts given information about object into user specified convention.
Keyword Arguments:
prefix -- what is prefixed before the name
name -- name of the object or node
side -- what side the object is on, example 'left' or 'right'
obj_type -- the type of the object, example 'joint' or 'multiplyDivide'
"""
prefix = self.abbrev_lib(prefix)
name = self.abbrev_lib(name)
side = ''.join([self.abbrev_lib(x) for x in side])
objtype = self.abbrev_lib(objtype)
i = 02
checked = ''
subs = {'prefix': prefix, 'name': name, 'side':
side, 'objtype': objtype}
while self.checked == '':
newname = Template (self.user_conv.lower())
newname = newname.safe_substitute(**subs)
newname = newname.strip('_')
newname = newname.replace('__', '_')
checked = self.check_scene(newname)
if checked == '' and i < 100:
subs['objtype'] = '%s%s' %(objtype, i)
i+=1
else:
break
return checked
are you running this many times? You are potentially trolling a list of several hundred or a few thousand items for each iteration inside while self.checked =='', which would be a likely culprit. FWIW prints are also very slow in Maya, especially if you're printing a long list - so doing that many times will definitely be slow no matter what.
I'd try a couple of things to speed this up:
limit your searches to one type at a time - why troll through hundreds of random nodes if you only care about MultiplyDivide right now?
Use a set or a dictionary to search, rather than a list - sets and dictionaries use hashsets and are faster for lookups
If you're worried about maintining a naming convetion, definitely design it to be resistant to Maya's default behavior which is to append numeric suffixes to keep names unique. Any naming convention which doesn't support this will be a pain in the butt for all time, because you can't prevent Maya from doing this in the ordinary course of business. On the other hand if you use that for differntiating instances you don't need to do any uniquification at all - just use rename() on the object and capture the result. The weakness there is that Maya won't rename for global uniqueness, only local - so if you want to make unique node name for things that are not siblings you have to do it yourself.
Here's some cheapie code for finding unique node names:
def get_unique_scene_names (*nodeTypes):
if not nodeTypes:
nodeTypes = ('transform',)
results = {}
for longname in cmds.ls(type = nodeTypes, l=True):
shortname = longname.rpartition("|")[-1]
if not shortname in results:
results[shortname] = set()
results[shortname].add(longname)
return results
def add_unique_name(item, node_dict):
shortname = item.rpartition("|")[-1]
if shortname in node_dict:
node_dict[shortname].add(item)
else:
node_dict[shortname] = set([item])
def remove_unique_name(item, node_dict):
shortname = item.rpartition("|")[-1]
existing = node_dict.get(shortname, [])
if item in existing:
existing.remove(item)
def apply_convention(node, new_name, node_dict):
if not new_name in node_dict:
renamed_item = cmds.ls(cmds.rename(node, new_name), l=True)[0]
remove_unique_name(node, node_dict)
add_unique_name ( renamed_item, node_dict)
return renamed_item
else:
for n in range(99999):
possible_name = new_name + str(n + 1)
if not possible_name in node_dict:
renamed_item = cmds.ls(cmds.rename(node, possible_name), l=True)[0]
add_unique_name(renamed_item, node_dict)
return renamed_item
raise RuntimeError, "Too many duplicate names"
To use it on a particular node type, you just supply the right would-be name when calling apply_convention(). This would rename all the joints in the scene (naively!) to 'jnt_X' while keeping the suffixes unique. You'd do something smarter than that, like your original code did - this just makes sure that leaves are unique:
joint_names= get_unique_scene_names('joint')
existing = cmds.ls( type='joint', l = True)
existing .sort()
existing .reverse()
# do this to make sure it works from leaves backwards!
for item in existing :
apply_convention(item, 'jnt_', joint_names)
# check the uniqueness constraint by looking for how many items share a short name in the dict:
for d in joint_names:
print d, len (joint_names[d])
But, like i said, plan for those damn numeric suffixes, maya makes them all the time without asking for permission so you can't fight em :(
Instead of running ls for each and every name, you should run it once and store that result into a set (an unordered list - slightly faster). Then check against that when you run check_scene
def check_scene(self, name):
"""Checks entire scene for same name. If duplicate exists,
Keyword Arguments:
name -- (string) name of object to be checked
"""
if not hasattr(self, 'scene'):
self.scene = set(ls())
if name not in self.scene:
return name
else:
return ''

comparing a list to a tuple, python 3.x - having problems getting the correct position to print

I'm a new programmer and I'm having a difficult time finishing up my 4th program. The premise was to create a program that would take input from the user, creating a list then compares this list to a tuple. After it prints a statement letting the user know which items they chose correspond to the items in the tuple and also in which position they are in the tuple.
The problem I'm having is the last part, I can't get the correct position to print right and I fail to understand why. For example, if someone chose GPS correctly during their guesses, it should print position 0, but it doesn't. If water is chosen, it says it's in position 13...but it should be 5.
#here is the code I have so far:
number_items_input = 0
guessed_inventory_list = [] #this is the variable list that will be input by user
survival_gear = () #this is the tuple that will be compared against
survival_gear = ("GPS","map","compass","firstaid","water","flashlight","lighter","blanket","rope","cell phone","signal mirror")
#block bellow takes input from the user
print("Please choose one by one, which top 10 items do you want with you in case of a survival situation, think Bear Grylls. Once chosen, your list will be compared to the top 10 survival items list.")
while number_items_input < 10:
print("Please choose.")
guessed_items = input()
guessed_inventory_list.append(guessed_items)
number_items_input = number_items_input + 1
print ("You have chosen the following:", guessed_inventory_list)
#block of code below here compares the input to the tuple
t = 1
while t < 1:
t = t + 1
for individual_items in guessed_inventory_list:
for top_items in survival_gear:
if individual_items == top_items:
#finally the print statements below advise the user if they guessed an item and which position it's in.
print ("You have chosen wisely", top_items)
print ("It's in position", t, "on the survival list")
t = t + 1
The reason you are getting a wrong index is because of the wrong nesting of loops , your outer loop should be the tuple you wish to compare and the inner loop should be the list generated from the input where as in this case it is reverse, see the below corrected code snippet
Code snippet:
for top_items in survival_gear:
for individual_items in guessed_inventory_list:
if individual_items == top_items:
#finally the print statements below advise the user if they guessed an item and which position it's in.
print ("You have chosen wisely", top_items)
print ("It's in position", t, "on the survival list")
t = t + 1
The above code snippet should solve your problem , but your code contains
while loop which can be avoided using the range built in function
Incrementing the variable t manually can be avoided by using enumerate built in function
The nested forloop and if loop can be replaced by using the "in" membership test operator
Find the below updated code:
#!/usr/bin/python
number_items_input = 0
guessed_inventory_list = [] #this is the variable list that will be input by user
survival_gear = ("GPS","map","compass","firstaid","water","flashlight","lighter","blanket","rope","cell phone","signal mirror")
#block bellow takes input from the user
print("Please choose one by one, which top 10 items do you want with you in caseof a survival situation, think Bear Grylls.Once chosen, your list will be compared to the top 10 survival items list.")
# One can use range functions to loop n times in this case 10 times
for i in range(0,10):
guessed_items = raw_input("Please choose:")
guessed_inventory_list.append(guessed_items)
print ("You have chosen the following:", guessed_inventory_list)
# Enumerate is one of the built-in Python functions.
# It returns an enumerate object.
# In this case that object is a list of tuples (immutable lists),
# each containing a pair of count/index and value.
# like [(1, 'GPS'), (2, 'map'), (3, 'compass'),...,(6, 'signal mirror')]
# in the below for loop the list of tuple will be
#unpacked in to t and individual_items for each iteration
for t,individual_items in enumerate(survival_gear,start=1):
#the "in" is a membership test operator which will test whether
#individual_items is in list guessed_inventory_list
if individual_items in guessed_inventory_list:
#finally the print statements below advise the user if they guessed an item and which position it's in.
print("You have chosen wisely", individual_items)
print("It's in position", t, "on the survival list")