0

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?

4

2 回答 2

1

可以统一生成三元组,而无需测试和拒绝重叠。

问题归结为从 {1... N -2} 中找到大小为k { a 1 ... a k }的随机序列,使得子序列的任何两个值之间的最小差异至少为 3。(N -2 因为这些值选择的是每个三元组的第一个值,因此最大值不能大于N -2。)

这可以通过从 {1... N -(( k -1)×2+2)} 中的随机有序子序列 { a ' 1 ... a ' k } 开始,然后将每个a i设置为a ' i +2 ( i -1)。最后,序列可以随机打乱。

这可以很容易地推广到找到大小为m的元组。

在 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
}
于 2015-10-16T17:24:30.220 回答
1

基本答案是从 1 .. (100 - 3 + 1) 或 1..98 范围内生成三个独立的随机值,然后从每个值 n 生成 n,n+1,n+2。

这只会给您留下不重叠的要求。您需要测试三个数字中任意两个之间的差距的绝对值至少为 3;如果没有,则生成一个新号码。您需要确定是否可以生成(假设“随机生成”生成了 {1, 4, 7} 的排列):

1 2 3
4 5 6
7 8 9

或者这组数字之间是否必须存在间隙。如果必须存在间隙,则检查生成值对之间的距离是否至少为 4,而不是 3。

选择要求 3 个值的集合之间至少有一个间隙,我最终得到了这个脚本:

#!/bin/bash

min=1           # Minimum value
max=100         # Maximum value
adj=3           # Number of adjacent values per set
num=3           # Number of sets

r_min=$min
r_max=$(($max - $adj + 1))

base=()
while [ ${#base[*]} -lt $num ]
do
    next=$(($RANDOM % ($r_max - $r_min + 1) + $r_min))
    ok=yes
    for n in ${base[@]}
    do
        gap=$(($next - $n))
        [ $gap -lt 0 ] && gap=$((- $gap))
        if [ $gap -le $adj ]
        then ok=no; break
        fi
    done
    if [ $ok = yes ]
    then base+=( $next )
    fi
done

for n in ${base[@]}
do
    for ((i = 0; i < $adj; i++))
    do printf "%4d" $(($n + $i))
    done
    echo
done

请注意,如果点集的数量和点集($num以及$adj代码中)的数量太大,您可能会因为没有足够的可能性而导致无限循环。例如,设置为$adj3 时,设置$num为 25 或更多可确保无限循环;不过,在那之前的很长一段时间内,您很容易遇到麻烦。

示例运行:

$ bash randcont.sh               
  16  17  18
  92  93  94
   6   7   8
$ bash randcont.sh
  81  82  83
  40  41  42
  13  14  15
$ bash randcont.sh
  61  62  63
  71  72  73
  23  24  25
$ bash randcont.sh
  54  55  56
   7   8   9
  46  47  48
$

用于生成随机数的机制存在偏差——偏向于较低的数字。如果这是一个问题,您也可以找出解决方法。

我不相信这是最好的方法。可能有一些方法可以使用较少的蛮力和无知。但它在样本要求上确实“正常”。

于 2015-10-16T06:01:39.583 回答