Reputation: 19
I am attempting to create a random number generator that generates a number between 1 and 99 but not any number that has already been generated.
In the script array1 contains the numbers already generated. To make it easier to test I have reduced the random number range to 0 - 14 and manually created an array.
I am quite new to bash scripting and am picking it up with a couple of books and the internet.
I have tried a mixture of ideas, the one that seems to make most sense is
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
however I know the problem is on line 9 the shell sees the following code:
until [ $rnd != 1 2 3 6 7 8 9 10 11 12 13 ]
I know that the solution is that line 9 needs to be:
until [ $rnd != 1 ] && [ $rnd != 2 ] && [ $rnd != 3 ] && ...
I just don't know how to make this happen automatically from the array. The array does vary in length depending on how many numbers have been generated.
Any help will be greatly appreciated!
Upvotes: 1
Views: 1636
Reputation: 140227
As noted in one of the comments, using the Knuth Shuffle is an excellent way to do this
#!/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
Upvotes: 1
Reputation: 34914
This is something that I found difficulty doing in bash. The approach I came up with is to have func1() return true or false and modify the array to remove the number that has been picked.
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
Upvotes: 1
Reputation: 241758
You can also use the -R
switch to sort
, if your version of sort
supports it:
for x in {1..99} ; do echo $x ; done | sort -R
Upvotes: 0