私はAWKを使用して1から6の間の値を生成します。この値はランダムな順序で表示する必要があります。正しい数値範囲を生成するロジックをクリーンアップしましたが、重複した数値が出力されるのを防ぐために配列に読み込むのが困難です。現在私のコードには次のものがあります。
BEGIN{
FS=""
}{
for (i=1; i<=6; ++i) {
v=(int (rand()*6)+1
print v }
現在6つの数字を出力していますが、2、2、6、1、4、2の重複が表示されます。 1、4、2、5、6、3などの出力が必要です。
私のAWKプログラムの配列の側面に役立つ人がいますか?
非常にありがとう
答え1
awk
少なくともほとんどのUnixシステムでは、以下を使用する必要があります。
$ seq 6 | shuf
5
2
3
4
1
6
または@ StéphaneChazelasがコメントで述べたようにshuf -i 1-6
。
本当にawkを使用したい場合は、awkを使用する方法があります。クヌスシャッフル:
$ cat tst.awk
function shuf(arr, i, j, n, tmp) {
n = length(arr)
for (i=n; i>1; i--) {
j = int( 1 + rand()*i )
tmp = arr[i]
arr[i] = arr[j]
arr[j] = tmp
}
}
BEGIN {
srand()
for (i=1; i<=n; i++) { arr[i] = i }
shuf(arr)
for (i=1; i<=n; i++) { print arr[i] }
}
$ awk -v n=6 -f tst.awk
3
1
5
4
6
2
必要な値で配列を入力し、配列内の各インデックスに格納されている値をランダムに選択した別のインデックスに格納されている値に置き換えて、配列を印刷します。
上記の関数はshuf()
配列の単一パスで機能します。
答え2
ただあなたが欲しいと思います。シャッフル再生1 ~ 6 の数字です。
ほとんどの実装には「ランダム」順序付けオプションがsort
あります-R
(このオプションは標準ではありません)。ほとんどのシェルには、範囲内で文字列または数値の組み合わせを生成するための「中括弧拡張」があります(中括弧拡張は標準ではありません)。
$ printf '%s\n' {1..6} | sort -R
6
2
3
4
5
1
答え3
6つの項目(数字1〜6を含む)を配置する方法には、720種類(= 6!(6階乗) = 1×2×3×4×5×6)のものがあります。したがって、1つの方法は1から6の乱数を生成することです! (実際には0から6!-1の間)これを対応する順列にマップします。
BEGIN {
n = 6
srand()
# Compute n! (n factorial) and create an array of numbers.
f = 1
for (i = 1; i <= n; i++) {
f *= i;
nums[i] = i;
}
# Get random number between 0 and n!-1.
r = int(rand()*f)
# Deconstruct it.
for (i = n; i > 0; i--) {
remainder = r % i + 1
print nums[remainder]
# Remove it from the array.
for (j = remainder; j < n; j++) nums[j] = nums[j+1]
r = int(r/i)
}
}
これはうまく拡張できません。
- 私のawkバージョンは22を計算することができます!しかし、23を計算することはできません!
- アルゴリズムはO(N2)。つまり、大きな値を扱う場合N、 N=6000は百万倍長くかかりますN=6。
利点:
rand()
一度だけ呼び出されるので、高価な仮想世界で上記を使用したい場合がありますrand()
。- このアルゴリズムは、同じ数値シーケンス番号を繰り返し簡単に生成できます(
r
任意の値ではなく既知の値に設定することによって)。