2015-10-16 6 views
0

Используя заданный диапазон значений, я пытаюсь создать случайные экземпляры из трех смежных чисел.Использование bash для создания случайных смежных последовательностей чисел из заданного диапазона

Например, учитывая диапазон 1-100, и желая три (не перекрывающийся) случайные экземпляры трех смежных чисел, результат будет что-то вроде:

4 5 6 
50 51 52 
32 33 34 

Я пытался использовать команду shuf, например,

shuf -i 1-100 -n 3 

, но это не похоже, чтобы разрешить генерацию случайных последовательностей смежных чисел. Есть идеи?

ответ

1

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

Задача сводится к нахождению случайной последовательности размера к { & hellip; ak} from {1 & hellip; N − 2} так, чтобы минимальная разница между любыми двумя значениями подпоследовательности составляла не менее 3.(N − 2, поскольку значения, выбранные первые значения каждой тройки, так что по величине не может быть больше, чем Н − 2.)

Это может быть сделано, начиная со случайным упорядоченной подпоследовательности {в ' & hellip; a 'k} из {1 & hellip; N − ((к − 1) × 2 + 2)}, а затем установить каждый як ' я +2 ( я − 1). Наконец, последовательность может быть случайным образом перетасована.

Этого можно легко обобщить, чтобы найти кортежи размером m.

В Баш:

# tuples n k m 
tuples() { 
    local -i n=${1:-100} k=${2:-3} m=$((${3:-3}-1)) 
    if ((n < k*m + k)); then return 1; fi 
    local -i i=0 a 
    for a in $(shuf -i 1-$((n - k * m)) -n $k | sort -n); do 
     # -s' ' to work around a bug in coreutils 8.20 and 8.21 
     seq -s' ' $((a+i)) $((a+i+m)) 
     i+=m 
    done | shuf 
} 
1

Основным ответом является генерация трех отдельных случайных величин из диапазона 1 .. (100 - 3 + 1) или 1..98, а затем производится n, n + 1, n + 2 из каждого значения n.

Это просто оставляет вас с неперекрывающимся требованием. Вам нужно проверить, что абсолютное значение разрыва между любыми двумя из трех чисел составляет не менее 3; если нет, сгенерируйте новый номер. Вы должны решить, можно ли произвести (при условии, что «случайное генерирование» производится перестановка {1, 4, 7}):

1 2 3 
4 5 6 
7 8 9 

, или должен быть зазор между наборами чисел , Если должен быть пробел, то вы проверяете, что расстояние между парами генерируемых значений составляет не менее 4, а не 3.

Выбрав требуемый промежуток, по меньшей мере, один из наборов из 3 значений, я закончил с этот скрипт:

#!/bin/bash 

min=1   # Minimum value 
max=100   # Maximum value 
adj=3   # Number of adjacent values per set 
num=3   # Number of sets 

r_min=$min 
r_max=$(($max - $adj + 1)) 

base=() 
while [ ${#base[*]} -lt $num ] 
do 
    next=$(($RANDOM % ($r_max - $r_min + 1) + $r_min)) 
    ok=yes 
    for n in ${base[@]} 
    do 
     gap=$(($next - $n)) 
     [ $gap -lt 0 ] && gap=$((- $gap)) 
     if [ $gap -le $adj ] 
     then ok=no; break 
     fi 
    done 
    if [ $ok = yes ] 
    then base+=($next) 
    fi 
done 

for n in ${base[@]} 
do 
    for ((i = 0; i < $adj; i++)) 
    do printf "%4d" $(($n + $i)) 
    done 
    echo 
done 

Обратите внимание, что если число наборов точек и число точек в наборе ($num и $adj в коде) становится слишком большой, вы можете в конечном итоге с бесконечным циклом, как там Арен достаточно возможностей. Например, с $adj в 3, установка $num до 25 или более гарантирует бесконечные петли; вы можете легко столкнуться с проблемами задолго до этого.

Пример работает:

$ bash randcont.sh    
    16 17 18 
    92 93 94 
    6 7 8 
$ bash randcont.sh 
    81 82 83 
    40 41 42 
    13 14 15 
$ bash randcont.sh 
    61 62 63 
    71 72 73 
    23 24 25 
$ bash randcont.sh 
    54 55 56 
    7 8 9 
    46 47 48 
$ 

Существует предубеждение в механизме, используемого для генерации случайных чисел - смещение в сторону более низких цифр. Если это проблема, вы можете решить, как ее исправить.

Я не убежден, что это лучший метод; вероятно, существуют некоторые методы, которые позволяют использовать меньше грубой силы и невежества. Но он работает «ОК» на требованиях к образцу.