I am trying to find k random numbers in the range 1..n such that none of the k numbers are contiguous. The code I came up with is
def noncontiguoussample(n,k):
import random
numbers = range(n)
samples = []
for _ in range(k):
v = random.choice(numbers)
samples.append(v)
for v in range(v-1, v+2):
try:
numbers.remove(v)
except ValueError:
pass
return samples
Update: I know this function won’t return the samples with uniform probability. Based on my limited testing, Amber’s solution below satisfies both the condition (a) individual elements of the sample are non-contiguous, and (b) all possible k samples (from 1…n) are generated with uniform probability.
The code is simpler if you use a
set.However, as Michael Anderson points out in the comments, this algorithm can fail sometimes in cases where
n < 3*k.A better algorithm that can’t fail (and is also faster!) might look like this:
The math-fu at the end there is this:
index), to account for that picked numberThus the result will always increase by at least 2 for each iteration through the loop.