Python Get Random Unique N Pairs

Say I have a range(1, n + 1). I want to get m unique pairs.

What I found is, if the number of pairs is close to n(n-1)/2 (maxiumum number of pairs), one can't simply generate random pairs everytime because they will start overriding eachother. I'm looking for a somewhat lazy solution, that will be very efficient (in Python's world).

My attempt so far:

def get_input(n, m):

    res = str(n) + "\n" + str(m) + "\n"
    buffet = range(1, n + 1)
    points = set()

    while len(points) < m:
        x, y = random.sample(buffet, 2)
        points.add((x, y)) if x > y else points.add((y, x)) # meeh

    for (x, y) in points:
        res += "%d %d\n" % (x, y);

    return res

Here is an approach which works by taking a number in the range 0 to n*(n-1)/2 - 1 and decodes it to a unique pair of items in the range 0 to n-1. I used 0-based math for convenience, but you could of course add 1 to all of the returned pairs if you want:

import math
import random

def decode(i):
    k = math.floor((1+math.sqrt(1+8*i))/2)
    return k,i-k*(k-1)//2

def rand_pair(n):
    return decode(random.randrange(n*(n-1)//2))

def rand_pairs(n,m):
    return [decode(i) for i in random.sample(range(n*(n-1)//2),m)]

For example:

>>> >>> rand_pairs(5,8)
[(2, 1), (3, 1), (4, 2), (2, 0), (3, 2), (4, 1), (1, 0), (4, 0)]

The math is hard to easily explain, but the k in the definition of decode is obtained by solving a quadratic equation which gives the number of triangular numbers which are <= i, and where i falls in the sequence of triangular numbers tells you how to decode a unique pair from it. The interesting thing about this decode is that it doesn't use n at all but implements a one-to-one correspondence from the set of natural numbers (starting at 0) to the set of all pairs of natural numbers.

This is a function which generates random pairs using [code ]itertools.combinations[/code] [1] with [code ]random.shuffle[/code] [2] : [code]import random import itertools def get_random_pairs(numbers): # Generate all possible


You can use combinations to generate all pairs and use sample to choose randomly. Admittedly only lazy in the "not much to type" sense, and not in the use a generator not a list sense :-)

from itertools import combinations
from random import sample

n = 100
sample(list(combinations(range(1,n),2)),5)

If you want to improve performance you can make it lazy by studying this Python random sample with a generator / iterable / iterator

the generator you want to sample from is this: combinations(range(1,n)

Method #1 : Using random.choice() + list() + items() The combination of above methods can be used to perform this task. The choice function performs the task of random value selection and list method is used to convert the pairs accessed using items() into a list over which choice function can work.


I don't think any thing on your line can improve. After all, as your m get closer and closer to the limit n(n-1)/2, you have thinner and thinner chance to find the unseen pair.

I would suggest to split into two cases: if m is small, use your random approach. But if m is large enough, try

 pairs = list(itertools.combination(buffet,2))
 ponits = random.sample(pairs, m)

Now you have to determine the threshold of m that determines which code path it should go. You need some math here to find the right trade off.

The best approach is to use the inbuilt function from itertools module. combinations () produces an iterator over tuples of all combinations of n elements in inputs. We make the use of these combinations and output those having ‘k’ difference.


Python’s NumPy module has a numpy.random package to generate random data. To create a random multidimensional array of integers within a given range, we can use the following NumPy methods: randint() random_integers() np.randint(low[, high, size, dtype]) To get random integers array from low (inclusive) to high (exclusive).


Time Complexity: Time complexity of the above implementation is O(n 2 Log n). We can optimize it to O(n 2) using unordered_set with user defined hash function. Efficient approach: First find out the number of unique elements in an array. Let the number of unique elements be x. Then, the number of unique pairs would be x 2. This is because each unique element can form a pair with every other unique element including itself.


")) # Add 1 to num_players to make the number correct num_players += 1 # Create the list of players from "1" to number entered in input my_list = list(range(1, num_players)) l = my_list # Create pairs pairs = {} while len(l) > 1: #Using the randomly created indices, respective elements are popped out r1 = random.randrange(0, len(l)) elem1 = l.pop(r1) r2 = random.randrange(0, len(l)) elem2 = l.pop(r2) # now the selected elements are paired in a dictionary pairs[elem1] = elem2 #The variable