0

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
kriwet
  • 43
  • 3
  • How about changing the logic, so you have an outer loop over the rounds and an inner loop over the players to assign numbers for that round. For each player, you make a list of all numbers that haven't previously been assigned to this player or used in this round, then assign a random choice from that listed this player in this round. – Matthias Fripp Apr 10 '21 at 23:51

1 Answers1

2

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.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • Yes that would be easier if I only needed one round, but in addition to the player getting a unique ID each round, they can only get the same ID once. For example a football team playing 4 matches where each player rotate between the matches and don't play the same position twice. – kriwet Apr 11 '21 at 10:34
  • @kriwet sorry about that, I did not notice. Check my updated answer. – Marco Bonelli Apr 11 '21 at 10:58