0

与えられた値の範囲を使用して、3 つの連続した数値のランダムなインスタンスを生成しようとしています。

たとえば、 range が指定され、1-1003 つの連続する数値の 3 つの (重複しない) ランダムなインスタンスが必要な場合、出力は次のようになります。

4 5 6
50 51 52
32 33 34

shufたとえば、コマンドを使用しようとしましたが、

shuf -i 1-100 -n 3

しかし、これはランダムな連続数列の生成を許可していないようです。何か案は?

4

2 に答える 2

1

重複をテストして拒否する必要なく、均一にトリプルを生成することができます。

この問題は、{1… N −2} からサイズk { a 1a k }のランダムなシーケンスを見つけて、サブシーケンスの任意の 2 つの値の間の最小差が少なくとも 3 になるように縮小します。選択されるのは各トリプルの最初の値であるため、最大値はN −2を超えることはできません。)

これは、{1… N −(( k −1)×2+2)}からのランダムに順序付けられたサブシーケンス { a ' 1a ' k } で開始し、各a ia ' i +2に設定することによって実行できます。 ( i −1)。最後に、シーケンスをランダムにシャッフルできます。

これは、サイズmのタプルを見つけるために簡単に一般化できます。

バッシュで:

# 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 から 3 つの個別のランダム値を生成し、各値 n から n,n+1,n+2 を生成することです。

それだけで、重複しない要件が残ります。3 つの数値のうち任意の 2 つの数値の間のギャップの絶対値が少なくとも 3 であることをテストする必要があります。そうでない場合は、新しい番号を生成します。生成しても問題ないかどうかを判断する必要があります (「ランダム生成」が {1, 4, 7} の順列を生成したと仮定します):

1 2 3
4 5 6
7 8 9

または、数値のセット間にギャップが必要かどうか。ギャップが必要な場合は、生成された値のペア間の距離が 3 ではなく 4 以上であることを確認します。

3 つの値のセット間に少なくとも 1 のギャップを要求することを選択すると、次のスクリプトになりました。

#!/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コード) 内のポイントの数が大きくなりすぎると、十分な可能性がないため、無限ループに陥る可能性があることに注意してください。たとえば、$adjat 3 の場合、$num25 以上に設定すると無限ループが保証されます。ただし、そのずっと前に簡単にトラブルに遭遇する可能性があります。

実行例:

$ 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
$

乱数を生成するために使用されるメカニズムには偏りがあります — より低い数への偏りです。それが問題である場合は、それを修正する方法も考え出すことができます。

これが最善の方法であるとは確信していません。総当たりや無知を少なくする方法がいくつかあるでしょう。しかし、サンプル要件では「OK」に機能します。

于 2015-10-16T06:01:39.583 に答える