我使用 AWK 生成 1 - 6 之间的值,这些值需要以随机顺序出现。我已经设法理清了创建正确数字范围的逻辑,但正在努力将它们读入数组以防止输出重复的数字。目前我的代码有这个;-
BEGIN{
FS=""
}{
for (i=1; i<=6; ++i) {
v=(int (rand()*6)+1
print v }
当前输出六个数字,但显示重复的 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
“随机”排序的选项(此选项不是标准的)。大多数 shell 都有“大括号扩展”来生成字符串或范围内的数字的组合(大括号扩展不是标准的):
$ printf '%s\n' {1..6} | sort -R
6
2
3
4
5
1
答案3
有 720 (= 6!(6 阶乘) = 1 × 2 × 3 × 4 × 5 × 6) 种不同的方式来排列 6 个不同的事物(包括数字 1 到 6)。所以一种方法是生成一个 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
为已知值而不是随机值)。