Question: I have a problem analog to: We have 20 balls each ball is unique and identified by a number from 1 to 20. The balls numbered from 1 to 5 are yellow, from 6 to 10 green, from 10 to 15 red and from 16 to 20 blue. Find a method to randomly shuffle the balls while respecting the constraint: "2 successive balls cannot have the same color". Example:  I have considered two methods that I am not satisfied with, and I am looking for a better one  draw a ball at random, then draw a ball at random among all the others having a different color from the previous one, etc.  Problem: we can fall in cases where it is impossible to finish the drawing, if there are only remaining balls of the same color for example.  divide the balls into 4 sets of 5 balls (1 per color), form 5 other sets of 4 balls by randomly drawing a ball of each color. Reassemble these 5 sets in order to respect the criterion (the first balls of the last set are permuted until the criterion is respected).  Problem some combinations are never drawn, for example red, yellow, red, yellow ... green, blue, green, blue. Edit: Here is an implementation of Unlikus solution. Many thanks to him. import enum import random Color = enum.Enum('Color', ['RED', 'GREEN', 'BLUE', "YELLOW"]) NB_PERMUTATION = { (Color.RED, 1, 0, 0, 0): 1, (Color.GREEN, 0, 1, 0, 0): 1, (Color.BLUE, 0, 0, 1, 0): 1, (Color.YELLOW, 0, 0, 0, 1): 1, (Color.RED, 0, 0, 0, 0): 0, (Color.GREEN, 0, 0, 0, 0): 0, (Color.BLUE, 0, 0, 0, 0): 0, (Color.YELLOW, 0, 0, 0, 0): 0, } def compute_nb_permutations(*args): try: return NB_PERMUTATION[args] except KeyError: second_colors = {1, 2, 3, 4} - {args[0].value} nb_ball = [args[1], args[2], args[3], args[4]] nb_ball[args[0].value - 1] -= 1 result = NB_PERMUTATION[args] = sum( compute_nb_permutations(Color(c), *nb_ball) for c in second_colors if nb_ball[c - 1] > 0 ) return result def arrange_color(): colors = {*Color} nb_ball = [5,5,5,5] # choose uniformly among colors for the first ball results = [random.choices(list(colors))[0]] nb_ball[results[-1].value - 1] -= 1 while nb_ball != [0,0,0,0]: candidates = list(colors - {results[-1]}) weights = [compute_nb_permutations(c, *nb_ball) for c in candidates] results.append(random.choices(candidates, weights=weights)[0]) nb_ball[results[-1].value - 1] -= 1 return results def draw(): numbers = { Color.RED: list(range(1,6)), Color.GREEN: list(range(6, 11)), Color.BLUE: list(range(11, 16)), Color.YELLOW: list(range(16, 21)), } for v in numbers.values(): random.shuffle(v) return {numbers[c].pop(): c.name for c in arrange_color()} 

Answer: It boils down to calculate the number of permutations which obey your constrains. See https://math.stackexchange.com/questions/1208392/ways-to-arrange-4-different-colour-balls-with-no-two-of-the-same-colour-next-to for an answer how to calculate the number of ways to arrange your balls with the first one being one particular color. (The answer deals with the last one, but the numbers are the same). You can calculate the values of f by dynamic programming. Now you sample your first color in proportion to f(5,5,5,5,red), f(5,5,5,5,green), f(5,5,5,5,blue), f(5,5,5,5, yellow). Suppose you have sampled red (the first color in f). You sample the second color in proportion to f(4,5,5,5,green), f(4,5,5,5,blue), f(4,5,5,5, yellow) and so on. You are guarantied that the sum of these 3 values is greater than 0, so there are still solutions left, otherwise f(5,5,5,5, red) would already be 0. If you have the colors right, the numbers are then easy.