Bash генератор случайных чисел, где число не в массиве - PullRequest
1 голос
/ 03 января 2012

Я пытаюсь создать генератор случайных чисел, который генерирует число от 1 до 99, но не любое число, которое уже было сгенерировано.

В скрипте array1 содержит уже сгенерированные числа.Чтобы облегчить тестирование, я уменьшил диапазон случайных чисел до 0 - 14 и вручную создал массив.

Я довольно новичок в bash-скриптинге и собираюсь поднять его с помощью пары книг и интернета.

Я испробовал смесь идей, одна из которых, кажется, имеет смысл

array1=( 1 2 3 6 7 8 9 10 11 12 13 )
func1() {
    for var in "${array1[@]}"
    do
      echo $var
    done
}
rnd=$[ $RANDOM % 14 ]
until [ $rnd != func1 ]
    do
        rnd=$[ $RANDOM % 14 ]
    done
echo $rnd

однако я знаю, что проблема в строке 9, оболочка видит следующий код:

until [ $rnd != 1 2 3 6 7 8 9 10 11 12 13 ]

Я знаю, что решение заключается в том, что строка 9 должна быть:

until [ $rnd != 1 ] && [ $rnd != 2 ] && [ $rnd != 3 ] && ...

Я просто не знаю, как сделать это автоматически из массива.Длина массива зависит от количества сгенерированных чисел.

Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

1 голос
/ 03 января 2012

Как отмечается в одном из комментариев, использование Knuth Shuffle - отличный способ сделать это

#!/bin/bash

shuffle() {
   local i tmp size max rand
   # Code from http://mywiki.wooledge.org/BashFAQ/026
   # $RANDOM % (i+1) is biased because of the limited range of $RANDOM
   # Compensate by using a range which is a multiple of the array size.
   size=${#array[*]}
   max=$(( 32768 / size * size ))

   for ((i=size-1; i>0; i--)); do
      while (( (rand=$RANDOM) >= max )); do :; done
      rand=$(( rand % (i+1) ))
      tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp
   done
}

# Fill an array with values 1 to 99
array=({1..99});

# Shuffle the array at random
shuffle

# Echo shuffled array
echo ${array[@]}

выход

$ ./knuth
58 78 6 37 84 79 81 43 50 25 49 56 99 41 26 15 86 11 96 90 76 46 92 70 87 27 33 91 1 2 73 97 65 69 42 32 39 67 72 52 36 64 24 88 60 35 83 89 66 30 4 53 57 28 75 48 40 74 18 23 45 61 20 31 21 16 68 80 62 8 98 14 7 19 47 55 22 85 59 17 77 10 63 93 51 54 95 82 94 9 44 38 13 71 34 29 5 3 12
1 голос
/ 03 января 2012

Это то, что мне было трудно делать в bash.Подход, который я придумал, состоит в том, чтобы func1 () возвращала true или false и изменяла массив, чтобы удалить выбранное число.

array=( {1..15} )
func1() {
   local pick="$1"
   found=1
   total=${#array[@]}
   for ((i=0;i<total;i++)); do 
      if (( pick == ${array[i]} )); then
         echo $pick
         array=( ${array[@]:0:i} ${array[@]:((i + 1)):$total})
         found=0
         break
      fi
   done
   return $found
}
numbers=3
for ((x=0;x<numbers;x++)); do 
   until func1 $(( $RANDOM % ( ${#array[@]} ) )); do 
      continue 
   done 
done
0 голосов
/ 03 января 2012

Вы также можете использовать переключатель -R для sort, если ваша версия sort поддерживает это:

for x in {1..99} ; do echo $x ; done | sort -R
...