Shell脚本实现不放回抽签
一次偶然的机会,博主进入大乐透投注站,观察到投注机具有随机选号功能,寻思着如果让我用shell实现该功能,应该要怎么写呢。
思路
基本思路就是产生随机数,将随机数与特定的值域联系起来,最后每取出一位数,值域中将该数剔除,保证抽取到值域内剩下的数的概率与实际相同。
代码如下
#!/bin/bash
big_redball_num=5
big_blueball_num=2
big_red_ball=(1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35)
big_blue_ball=(1 2 3 4 5 6 7 8 9 11 12)
double_redball_num=6
double_blueball_num=1
double_red_ball=(1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33)
double_blue_ball=(1 2 3 4 5 6 7 8 9 11 12 13 14 15 16)
function pick_the_ball #$1是抽取的数组,使用该参数必须用""标注 $2是不放回抽取的个数
{
#将传入的数组用中间数组承接,方便操作
arr_temp=(${1})
for((i=0;i<${2};i++))
do
num=$[RANDOM%${#arr_temp[@]}]
arr_last[i]=${arr_temp[${num}]}
#删除已经抽中的元素,注意:这里的unset让改位置元素变为空,实际还是占有该位置,
unset arr_temp[${num}]
#重新构造arr_temp数组(将没有变为空的元素重新组合起来替换掉原来的数组)
arr_temp=(${arr_temp[@]})
done
#冒泡排序
for((i=0;i<${#arr_last[@]}-1;i++))
do
for((j=0;j<${#arr_last[@]}-1-${i};j++))
do
if [ ${arr_last[j]} -gt ${arr_last[j+1]} ];then
x=${arr_last[j]}
arr_last[j]=${arr_last[j+1]}
arr_last[j+1]=${x}
fi
done
done
#打印
for((j=0;j<${2};j++))
do
printf "%02d " ${arr_last[j]}
done
}
#红
echo -ne "Big :"
pick_the_ball "${big_red_ball[*]}" "${big_redball_num}"
echo -ne "+ "
#蓝
pick_the_ball "${big_blue_ball[*]}" "${big_blueball_num}"
echo -ne "\n"
#红
echo -ne "Double:"
pick_the_ball "${double_red_ball[*]}" "${double_redball_num}"
echo -ne "+ "
#蓝
pick_the_ball "${double_blue_ball[*]}" "${double_blueball_num}"
echo -ne "\n"
代码执行一次结果:
代码中unset处详解
比如unset arr_temp[2],将arr_temp[2]的内容变为空,但是arr_temp[3]的值还是在arr_temp[3],并不会移位到arr_temp[2],所以如果下次再抽中arr_temp[2],会打印空。
测试例子
#!/bin/bash
arr=(1 2 3 4 5 6 7 8 9)
echo ${arr[2]}
unset arr[2]
echo ${arr[@]}
echo ${!arr[@]}
echo ${arr[2]}
unset arr[2]
echo ${arr[@]}
echo ${!arr[@]}
测试结果
初次写博客,若有不对的地方请大家指正。