저는 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에서 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
임의 값이 아닌 알려진 값으로 설정하여).