Using a given range of values, I'm trying to generate random instances of three contiguous numbers.
For example, given the range 1-100
, and desiring three (non-overlapping) random instances of three contiguous numbers, the output would be something like:
4 5 6
50 51 52
32 33 34
I've been trying to use the command shuf
, for example,
shuf -i 1-100 -n 3
but this doesn't seem to permit the generation of random contiguous number sequences. Any ideas?
It is possible to generate the triples uniformly and without the need for testing and rejecting overlaps.
The problem reduces to finding a random sequence of size k {a1…ak} from {1…N−2} such that the minimum difference between any two values of the subsequence is at least 3. (N−2 because the values selected are the first values of each triple, so the largest cannot be greater than N−2.)
This can be done by starting with a random ordered subsequence {a'1…a'k} from {1…N−((k−1)×2+2)} and then setting each ai to a'i+2(i−1). Finally, the sequence can be randomly shuffled.
This can be easily be generalized to find tuples of size m.
In bash:
# tuples n k m
tuples () {
local -i n=${1:-100} k=${2:-3} m=$((${3:-3}-1))
if ((n < k*m + k)); then return 1; fi
local -i i=0 a
for a in $(shuf -i 1-$((n - k * m)) -n $k | sort -n); do
# -s' ' to work around a bug in coreutils 8.20 and 8.21
seq -s' ' $((a+i)) $((a+i+m))
i+=m
done | shuf
}