Related
This question already has answers here:
Listing words randomly without repeating them
(2 answers)
Closed 1 year ago.
I am a complete amateur and know there probably is easier ways to do this, but this isn't an important project, just a superquick code. For some reason it seems like it gets stuck in a loop because random.choice gives the same number over and over again. It works sometimes, I just have to give it a couple of tries, and as I increase the range the more difficult it is.
The code is supposed to allocate a unique number to each "player" every round, without giving the same player the same number twice.
import random
A = []
B = []
C = []
D = []
E = []
F = []
G = []
H = []
I = []
J = []
K = []
lt = [A, B, C, D, E, F, G, H, I, J, K]
lit = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
ALT = 0
for e in range(5):
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
for i in lt:
while True:
add = random.choice(lst)
if add not in i:
i.append(add)
lst.remove(add)
break
else:
print('fant ingenting')
ALT += 1
print(ALT)
tot = 0
for k in lt:
print(str(lit[tot]) + ' = ' + str(k))
tot += 1
So you have a list of 11 players and you want to assign 11 unique IDs (from 1 to 11) to them. Why not just shuffle() the list of IDs once and be done with it?
lit = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
random.shuffle(lst)
for player, player_id in zip(lit, lst):
print("player", player, "has id", player_id)
If you want to give random IDs multiple times without repeating, a very simple way to do this would be to just rotate them:
lit = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
random.shuffle(lst)
for round in range(5):
print("Round", round)
for player, player_id in zip(lit, lst):
print("> player", player, "has id", player_id)
lst = lst[1:] + lst[:1]
Note that that last step of rotating using lst = lst[1:] + lst[:1] is ok with small lists, but can be really inefficient for large lists, since it creates a new copy of the entire list every time. If you are working with larger lists, you can use a deque:
lit = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
random.shuffle(lst)
lst = deque(lst)
for round in range(5):
print("Round", round)
for player, player_id in zip(lit, lst):
print("> player", player, "has id", player_id)
lst.rotate(1)
One caveat of this solution is that since players are ordered, the IDs will be distributed each round in order. So, for example, you already know that if the IDs are initially 1, 2, 3 for players A, B, C the player C will get IDs 2 and 1 in the next two rounds. In order to avoid this and get more unpredictable IDs you could also shuffle the list of players first:
random.shuffle(lit)
random.shuffle(lst)
# ... same code as above ...
This way you will not have a predictable "next player" to get a specific ID.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am about a week into learning Python and I am very confused about making dictionaries (or if I should even be using a dictionary for this). I've searched all over for a similar problem, but it's possible I just don't understand well enough to recognize an applicable answer.
What I am trying to do is to associate a letter with a unique "score" (this score is a number). So for a toy example, for ABCA with scores of 1, 20, 10, 5...the first A = 1, B = 20, C = 10, last A = 5. The end goal is to then remove the letters with the low "scores"/numbers.
My data in a list is something like this:
x_list = ['ABCDEABCDE10 2 3 4 5 6 7 8 9 1', 'EDCABB6 9 8 8 8 6 9', etc.]
Similar to the toy example, I want A = 10, B = 2, C = 3, etc. in the first string and E = 6, D = 8, C = 8, etc. in the second string. So I think I want to make a dictionary were the letters are keys and numbers are values? And then a list of dictionaries? What I am thinking is something like:
dictionary1 = {A:10, B:2, C:3, D:4, E:5, A:6, B:7, C:8, D:9, E:1}
dictionary2 = {E:9, D:8, C:8, A:8, B:6, B:9}
dictionary_list = (dictionary1, dictionary2)
And then be able to remove all of the values lower than 5 from the original list.
final_list = []
for each_list in dictionary_list:
if value > 5 in each_list:
final_list.append(each_list)
final_list = [[A,A,B,C,D], [E,D,C,A,B,B]]
I've tried looping through x_list with for loops to get the result, but I can't figure out how to get the numbers to line up with the values without using a dictionary.
Any help is very much appreciated!
(This is also my first time posting so please let me know if I make any newbie errors either in coding or if I shouldn't be using dictionaries at all for this.)
*Edited to improve clarity
I'm not sure I understand the problem you are trying to solve correctly, so let me try to rephrase it. Let's focus on a single list for now. If I understand correctly, you are looking at lists that look like this.
l = ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E', 1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
Here I assume that we have exactly as many letters (or strings) as we have numbers (or integers).
You then want to associate each letter in the first half of the list with a number from the second half of the list. So you want to look at pairs of letters and numbers. As is it turns out, Python supports tuples as a data type and pairs are just tuples with two elements. To match up the letters with the numbers, you could do the following:
letters = l[:len(l)//2] # = ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E']
numbers = l[len(l)//2:] # = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
pairs = list(zip(letters, numbers)) # = [('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5), ('A', 6), ('B', 7), ('C', 8), ('D', 9), ('E', 1)]
In the first two lines I use slices (see for example here) to split the list into two halves. Then I use zip to create pairs from the resulting lists.
To then get all letters that are associated with an integer less than k, you could do the following.
k = 5 # or whatever you choose
result = [letter for letter, number in pairs if number < k] # = ['A', 'B', 'C', 'D', 'E']
Here, I am using a list comprehension to generate the result list.
To do all of this on a list of lists, you can wrap the code in a function:
def f(input_list, threshold):
letters = input_list[:len(input_list)//2]
numbers = input_list[len(input_list)//2:]
pairs = list(zip(letters, numbers))
return [letter for letter, number in pairs if number < threshold]
You can then use another list comprehension to apply the function to each list in a list of lists.
l = [['A', 'B', 100, 2], ['C', 'D', 12, 42]]
threshold = 32
result = [f(input_list, threshold) for input_list in l] # = [['B'], ['C']]
Finally, dictionaries are probably not the right data structure for this particular problem. In a dictionary, you associate keys with values and each key can only have exactly one value. In your example above, you have two different occurrences of the letter 'A' and you associate them with the numbers 1 and 6, respectively. Therefore, using dictionaries wouldn't be very natural. (That said, you could define the value associated with the key 'A' to be a list or set of numbers, but I don't think that would necessarily lead to a better solution of your problem.)
You can convert each character to an ascii integer value using ord. In ascii, all of the characters values are right next to eachother, so something like ord('B') > ord('A') will always be true. You can use this to filter the list. e.g.
>>> [c for c in 'ABCDEFGHIJK' if ord(c) > ord('E')]
['F', 'G', 'H', 'I', 'J', 'K']
In dictionary, key are immutable. so, you can't create dictionary with repeated keys. Instead of that, you can create list of dictionary like this,
[{'A': [2, 7], 'B': [3, 8], 'C': [4, 9], 'D': [5, 1], 'E': [6]}, {'E': [9], 'D': [8], 'C': [8], 'A': [8], 'B': [6, 9]}]
you can achieve it by following code ;
x_list = [['ABCDEABCDE1', 2, 3, 4, 5, 6, 7, 8, 9, 1], ['EDCABB6', 9, 8, 8, 8, 6, 9]]
result=[]
for i in x_list:
string=i[0]
print(string)
l=i[1:]
print
d={}
for i,j in zip(string,l):
d.setdefault(i,[]).append(j)
result.append(d)
print(result)
after that, to get filtered list ;
final_result=[]
for i in result:
l1=[]
for key,val in i.items():
for v in val:
if v>=5:
l1.append(key)
final_result.append(l1)
print(final_result)
output:
[['A', 'B', 'C', 'D', 'E'], ['E', 'D', 'C', 'A', 'B', 'B']]
I’m currently completing a go fish program and python and am struggling to determine how to “check” if there are 4 cards of the same rank (ace, 2, etc) in one hand and remove them. My current code is as follows,
def check(hand, score):
for i in range(len(hand)- 1):
j = hand[i]
if j == 4:
print("you have completed a set :)")
for j in range(4):
hand.remove[j]
score += 1
else:
print("no sets have been found ☹")
Any suggestions?
You could use a set to get unique cards in your checked hand and then count the number of occurrences:
def check(hand):
score = 0
for card in set(hand):
count = len([x for x in hand if (x == card)])
if count >= 4:
score += 1
print("you have completed a set of '{}' :)".format(card))
for j in range(count):
hand.remove(card)
if score == 0:
print("no sets have been found ☹")
return score
h1 = [i for i in range(12)]
h2 = [i for i in (['A', 'A', 'A', 'A', 7, 7, 7, 'J'] + h1)]
print(h1)
print('Score: {}\n'.format(check(h1)))
print(h2)
print('Score: {}'.format(check(h2)))
Result:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
no sets have been found ☹
Score: 0
['A', 'A', 'A', 'A', 7, 7, 7, 'J', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
you have completed a set of '7' :)
you have completed a set of 'A' :)
Score: 2
I am trying to order a user input, set of cards (Not deck) from lowest to highest A-K. I am not very experienced with python, and don't know much of the terminology and functions. I am trying to keep the code simple and basic.
Here is what I have:
A = 1
J= 11
Q = 12
K = 13
alist = sorted(input("Type your card set: "))
#it prints 1,11,12,and 13 instead of A,K,Q,J
print(alist)
How do I change 1,11,12,13 back to A,K,Q,J before printing?
use dict
d={'A': 1,
'J': 11,
'Q' : 12,
'K': 13}
alist ='7,6,5,4,3,2,A,K,Q,J,10,9,8'
alist=alist.split(',')
Creating the new list based on the input if it is a digit (like 1,2) then we do not need to refer to the dict else if it is like('A','K'etc.) we need the mapping from the dict defined above and then sort the new dict form
new_list=sorted([int(i) if i.isdigit() else d[i] for i in alist]) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
To convert back to 'A.J,k' Create a new dict with keys as 1 as values as 'A' etc
d_new=dict(zip(d.values(),d.keys()))
Replace the values. Do an iteration similar to one we did earlier if the value is 1 or 11 then lookup in d_new dict for the corresponding mapping
for i,value in enumerate(new_list,0):
if value in d_new.keys():
new_list[i]=d_new[value]
print(new_list) # ['A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
I'm using the nltk library's movie_reviews corpus which contains a large number of documents. My task is get predictive performance of these reviews with pre-processing of the data and without pre-processing. But there is problem, in lists documents and documents2 I have the same documents and I need shuffle them in order to keep same order in both lists. I cannot shuffle them separately because each time I shuffle the list, I get other results. That is why I need to shuffle the at once with same order because I need compare them in the end (it depends on order). I'm using python 2.7
Example (in real are strings tokenized, but it is not relative):
documents = [(['plot : two teen couples go to a church party , '], 'neg'),
(['drink and then drive . '], 'pos'),
(['they get into an accident . '], 'neg'),
(['one of the guys dies'], 'neg')]
documents2 = [(['plot two teen couples church party'], 'neg'),
(['drink then drive . '], 'pos'),
(['they get accident . '], 'neg'),
(['one guys dies'], 'neg')]
And I need get this result after shuffle both lists:
documents = [(['one of the guys dies'], 'neg'),
(['they get into an accident . '], 'neg'),
(['drink and then drive . '], 'pos'),
(['plot : two teen couples go to a church party , '], 'neg')]
documents2 = [(['one guys dies'], 'neg'),
(['they get accident . '], 'neg'),
(['drink then drive . '], 'pos'),
(['plot two teen couples church party'], 'neg')]
I have this code:
def cleanDoc(doc):
stopset = set(stopwords.words('english'))
stemmer = nltk.PorterStemmer()
clean = [token.lower() for token in doc if token.lower() not in stopset and len(token) > 2]
final = [stemmer.stem(word) for word in clean]
return final
documents = [(list(movie_reviews.words(fileid)), category)
for category in movie_reviews.categories()
for fileid in movie_reviews.fileids(category)]
documents2 = [(list(cleanDoc(movie_reviews.words(fileid))), category)
for category in movie_reviews.categories()
for fileid in movie_reviews.fileids(category)]
random.shuffle( and here shuffle documents and documents2 with same order) # or somehow
You can do it as:
import random
a = ['a', 'b', 'c']
b = [1, 2, 3]
c = list(zip(a, b))
random.shuffle(c)
a, b = zip(*c)
print a
print b
[OUTPUT]
['a', 'c', 'b']
[1, 3, 2]
Of course, this was an example with simpler lists, but the adaptation will be the same for your case.
I get a easy way to do this
import numpy as np
a = np.array([0,1,2,3,4])
b = np.array([5,6,7,8,9])
indices = np.arange(a.shape[0])
np.random.shuffle(indices)
a = a[indices]
b = b[indices]
# a, array([3, 4, 1, 2, 0])
# b, array([8, 9, 6, 7, 5])
from sklearn.utils import shuffle
a = ['a', 'b', 'c','d','e']
b = [1, 2, 3, 4, 5]
a_shuffled, b_shuffled = shuffle(np.array(a), np.array(b))
print(a_shuffled, b_shuffled)
#random output
#['e' 'c' 'b' 'd' 'a'] [5 3 2 4 1]
Shuffle an arbitray number of lists simultaneously.
from random import shuffle
def shuffle_list(*ls):
l =list(zip(*ls))
shuffle(l)
return zip(*l)
a = [0,1,2,3,4]
b = [5,6,7,8,9]
a1,b1 = shuffle_list(a,b)
print(a1,b1)
a = [0,1,2,3,4]
b = [5,6,7,8,9]
c = [10,11,12,13,14]
a1,b1,c1 = shuffle_list(a,b,c)
print(a1,b1,c1)
Output:
$ (0, 2, 4, 3, 1) (5, 7, 9, 8, 6)
$ (4, 3, 0, 2, 1) (9, 8, 5, 7, 6) (14, 13, 10, 12, 11)
Note:
objects returned by shuffle_list() are tuples.
P.S.
shuffle_list() can also be applied to numpy.array()
a = np.array([1,2,3])
b = np.array([4,5,6])
a1,b1 = shuffle_list(a,b)
print(a1,b1)
Output:
$ (3, 1, 2) (6, 4, 5)
Easy and fast way to do this is to use random.seed() with random.shuffle() . It lets you generate same random order many times you want.
It will look like this:
a = [1, 2, 3, 4, 5]
b = [6, 7, 8, 9, 10]
seed = random.random()
random.seed(seed)
a.shuffle()
random.seed(seed)
b.shuffle()
print(a)
print(b)
>>[3, 1, 4, 2, 5]
>>[8, 6, 9, 7, 10]
This also works when you can't work with both lists at the same time, because of memory problems.
You can store the order of the values in a variable, then sort the arrays simultaneously:
array1 = [1, 2, 3, 4, 5]
array2 = ["one", "two", "three", "four", "five"]
order = range(len(array1))
random.shuffle(order)
newarray1 = []
newarray2 = []
for x in range(len(order)):
newarray1.append(array1[order[x]])
newarray2.append(array2[order[x]])
print newarray1, newarray2
This works as well:
import numpy as np
a = ['a', 'b', 'c']
b = [1, 2, 3]
rng = np.random.default_rng()
state = rng.bit_generator.state
rng.shuffle(a)
# use same seeds for a & b!
rng.bit_generator.state = state # set state to same state as before
rng.shuffle(b)
print(a)
print(b)
Output:
['b', 'a', 'c']
[2, 1, 3]
You can use the second argument of the shuffle function to fix the order of shuffling.
Specifically, you can pass the second argument of shuffle function a zero argument function which returns a value in [0, 1). The return value of this function fixes the order of shuffling. (By default i.e. if you do not pass any function as the second argument, it uses the function random.random(). You can see it at line 277 here.)
This example illustrates what I described:
import random
a = ['a', 'b', 'c', 'd', 'e']
b = [1, 2, 3, 4, 5]
r = random.random() # randomly generating a real in [0,1)
random.shuffle(a, lambda : r) # lambda : r is an unary function which returns r
random.shuffle(b, lambda : r) # using the same function as used in prev line so that shuffling order is same
print a
print b
Output:
['e', 'c', 'd', 'a', 'b']
[5, 3, 4, 1, 2]