找回密码
 加入
搜索
查看: 9598|回复: 28

[效率算法] 关于依照表取得随机值的问题

 火.. [复制链接]
发表于 2010-5-1 13:49:59 | 显示全部楼层 |阅读模式
本帖最后由 rolaka 于 2010-5-4 17:26 编辑
一日 sxd叫儿子去超市打酱油 结账时候拿到一张抽奖卷 到柜台抽奖

柜台前的广告是这么写的:

- 50%拿到 餐巾纸 塑料袋 橡皮筋 中的随机一样

- 12%拿到 糖果 饼干 中的随机一样

- 5%拿到 优惠卷

- 1%拿到 猫粮

- 剩下就是谢谢惠顾了


现需要用au3 来模拟出这个抽奖箱 算法以执行10W次最后统计出来的结果准确度来衡量
(检验方法 算出10W次的结果->统计各类各项奖品在总抽奖次数里的比)

要求:
1.物品列表是可以修改的
2.单次执行时间控制在200ms以内
3.越短越好...!

初级题了...我蛋疼我自重...其实我写的代码太多...想看看有没有更加短的...

200ms的含义:生成一次结果所花费时间...


引起公愤了啊......下面是我自己的...
#include <Array.au3>

$data = StringSplit(StringReplace(FileRead("list.txt"), @CR, ""), @LF, 2)
Dim $list[1][1]
For $i = 0 To UBound($data)-1
        $spilt = StringSplit($data[$i], ",", 2)
        $flag = False
        For $n = 0 To UBound($list)-1
                If $list[$n][0] == Int($spilt[0]) Then
                        $flag = True
                        ExitLoop
                EndIf
        Next
        If $flag Then
                $list[$n][1] = $list[$n][1] & "," & $spilt[1]
        Else
                ReDim $list[$n+1][2]
                $list[$n][0] = Int($spilt[0])
                $list[$n][1] = $spilt[1]
        EndIf
Next

_ArrayDisplay($list)

$time = TimerInit()
$r = luckyBox($list)
MsgBox(0, TimerDiff($time), $r)

;~ For $i = 0 To 100000
;~         FileWriteLine("test",luckyBox($list))
;~ Next

;$list
Func luckyBox(ByRef $list)
        $rate = Floor(Random(0, 99999, 1)/1000)
        $weighting = 0
        While 1
                For $i = 1 To UBound($list)-1
                        If ($rate+$weighting) == $list[$i][0] Then
                                Return $list[$i][1]
                        EndIf
                Next
                $weighting += 1
        WEnd
EndFunc
list.txt
12,糖果
50,餐巾纸
50,塑料袋
50,橡皮筋
12,饼干
5,优惠卷
1,猫粮
100,谢谢惠顾
测试下来 基本在比例上把(有浮动是很正常的 像p版说的情况是允许少量出现的)... 测试10w次是为了看值的稳定性...
单次平均0.40ms左右...
发表于 2010-5-1 22:16:32 | 显示全部楼层
只来帮项!!!!!
$a=6.3  ;随机值能不能在这里控制呢?
For $b=1 To 10 Step $a
MsgBox(0,"",$b)
Next
不知道用这个方法能行通不? 这里只是一个例子,语句还有很多的变通哦
发表于 2010-5-2 10:01:22 | 显示全部楼层
LZ有没有例子?
个人想法,先按比例生成含有10w个元素的数组,再随机不重复的读取这10W个元素
发表于 2010-5-2 10:19:17 | 显示全部楼层
- 50%拿到 餐巾纸 塑料袋 橡皮筋 中的随机一样

- 12%拿到 糖果 饼干 中的随机一样

- 5%拿到 优惠卷

- 1%拿到 猫粮

- 剩下就是谢谢惠顾了

按这个百分比随机存取就可以了
发表于 2010-5-2 15:28:27 | 显示全部楼层
来个笨办法,只是统计没中奖的次数。
Local $number[5]
Local $a, $d = "优惠卷", $e = "猫粮"
Local $b[3] = ["餐巾纸", "塑料袋", "橡皮筋"]
Local $c[2] = ["糖果", "饼干"]
;Local
For $i = 1 To 100000
        $a = Random(1, 100)
        If $a < 50 Then ; Returns a value between 0 and 1.
                $msg = $b[Random(0, 2, 1)]
                If $a < 12 Then
                        $msg = $c[Random(0, 1, 1)]
                        If $a < 5 Then
                                $msgbox = $d
                                If $a < 1 Then
                                        $msg = $e
                                EndIf
                        EndIf
                EndIf
        Else
                $msg = "谢谢惠顾"
                $number[4] += 1
        EndIf
Next
MsgBox(0, 0, "谢谢惠顾次数" & $number[4])
发表于 2010-5-3 03:02:11 | 显示全部楼层
呵呵,学习了
发表于 2010-5-3 16:49:02 | 显示全部楼层
想到蛋疼,只计算了1万次笨方法。请大家指教
#include <array.au3>
Local $arr[100], $arr3[1]
Local $a, $bb = 0, $d = "优惠卷", $e = "猫粮"
Local $b[3] = ["餐巾纸", "塑料袋", "橡皮筋"]
Local $c[2] = ["糖果", "饼干"]
$begin = TimerInit()

For $m = 0 To 99;这里定义计算次数/100,只计算100次得到 1万次抽奖的数组
        Dim $arr2[100]
        For $n = 0 To 99
                $arr2[$n] = $n
        Next

        For $i = 0 To 99
                $rannumber = UBound($arr2) - 1
                $ran = Random(0, $rannumber, 1)
                $arr[$i] = $arr2[$ran]
                Select
                        Case $arr[$i] <= 49
                                $arr[$i] = $b[Random(0, 2, 1)]
                        Case $arr[$i] <= 61 And $arr[$i] > 49
                                $arr[$i] = $c[Random(0, 1, 1)]
                        Case $arr[$i] <= 66 And $arr[$i] > 61
                                $arr[$i] = $d
                        Case $arr[$i] = 67
                                $arr[$i] = "猫粮"
                        Case $arr[$i] > 67
                                $arr[$i] = "未中奖"
                EndSelect
                _ArrayDelete($arr2, $ran)

        Next

        _ArrayConcatenate($arr3, $arr)
Next
;_ArraySort($arr3)
_ArrayDelete($arr3,0)
$dif = TimerDiff($begin)
_ArrayDisplay($arr3,$dif)

评分

参与人数 1威望 +2 金钱 +20 收起 理由
afan + 2 + 20

查看全部评分

发表于 2010-5-3 17:20:55 | 显示全部楼层

运行10W次的效率实在是太肉了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-5-3 17:36:54 | 显示全部楼层
3mile 很热心的说,倒是LZ…
发表于 2010-5-3 17:49:21 | 显示全部楼层
3mile 很热心的说,倒是LZ…
afan 发表于 2010-5-3 17:36

是啊!撂个问题在这里也不来过问。
前辈最近很忙吧?忙什么呢?
发表于 2010-5-3 18:00:35 | 显示全部楼层
是啊!撂个问题在这里也不来过问。
前辈最近很忙吧?忙什么呢?
水木子 发表于 2010-5-3 17:49


忙着睡大觉,天太热,不敢出门,呵呵~

运行10W次的效率实在是太肉了
3mile 发表于 2010-5-3 17:20


我想LZ的运行10W次仅是为了检验结果,而实际应用应该只是单次的抽奖,那样应该可以是很快的~ 所以我也在3#提出先按比例生成10W奖池(就不存在再验证了),再每次随机不重复读取奖池的元素
发表于 2010-5-3 18:58:24 | 显示全部楼层
本帖最后由 pusofalse 于 2010-5-3 20:18 编辑

10万次和100次有何区别?——貌似这是涉及到统计学的问题。 - -||

先生成一个100个元素的1维数组。
前50赋值为1,表示餐巾纸;
再12赋值为2,表示糖果;
其次的5赋值为3,为优惠券;
再1赋值为4,为猫粮;
余下的元素全部赋值为5,表示未中奖;

循环100次,取一个介于0-99之间的随机数,作为数组的索引序号,获取数组中该元素的值,并记录获取该值的次数,循环完毕,最后对比1/2/3/4/5各自的获取次数。
#include <Array.au3>

$iTimer = TimerInit()

Local $aVar[1000], $aOutput[1000]

_AssignVar(0, 499, "餐巾纸")
_AssignVar(500, 619, "糖果")
_AssignVar(620, 669, "优惠券")
_AssignVar(670, 679, "猫粮")

For $i = 0 To 999
        $aOutput[$i] = $aVar[Random(0, 999, 1)]
Next
_Arraydisplay($aOutput, TimerDiff($iTimer))

Func _AssignVar($iFrom, $iStop, $sVar)
        For $i = $iFrom To $iStop
                $aVar[$i] = $sVar
        Next
EndFunc        ;==>_AssignVar
此题可看作编程解生活中的应用题,在想是否应该打乱数组的顺序,更加接近于生活中人的逻辑。
记得很小的时候去抽奖,抽了10次,结果连续10次都中了,用1块钱买来了10块钱的东西,原因在于所有的奖品分布都集中在了一点,只是凭感觉依次从左至右连续抽了个遍。现在想想上面的代码可能会重现那次的情形。

评分

参与人数 1金钱 +30 收起 理由
水木子 + 30 方法学习了!

查看全部评分

发表于 2010-5-3 20:06:37 | 显示全部楼层
10万次和100次有何区别?

先生成一个100个元素的1维数组。
前50赋值为1,表示餐巾纸;
再12赋值为2,表 ...
pusofalse 发表于 2010-5-3 18:58


呵呵,学习了。
我的想法和P大有些雷同。但应该P大的效率更高吧
发表于 2010-5-3 20:56:02 | 显示全部楼层
Dim $arr[5][2]
$arr[0][0] = "餐巾纸 塑料袋 橡皮筋 中的随机一样"
$arr[1][0] = "糖果 饼干 中的随机一样"
$arr[2][0] = "优惠卷"
$arr[3][0] = "猫粮"
$arr[4][0] = "谢谢惠顾了"
$arr[0][1] = 0
$arr[1][1] = 0
$arr[2][1] = 0
$arr[3][1] = 0
$arr[4][1] = 0
$begin = TimerInit()
For $i=1 To 100000
        $t = Random(1,100)
        If $t < 51 Then
                $arr[0][1] += 1
        ElseIf $t < 63 Then
                $arr[1][1] += 1       
        ElseIf $t < 68 Then
                $arr[2][1] += 1       
        ElseIf $t< 69 Then
                $arr[3][1] += 1       
        Else
                $arr[4][1] += 1       
        EndIf               
Next
$dif = TimerDiff($begin)
MsgBox(0,"时间差",$dif)
$arr[0][1] = Round ($arr[0][1]/1000)
$arr[1][1] = Round ($arr[1][1]/1000)
$arr[2][1] = Round ($arr[2][1]/1000)
$arr[3][1] = Round ($arr[3][1]/1000)
$arr[4][1] = Round ($arr[4][1]/1000)
_ArrayDisplay($arr, "各类各项奖品在总抽奖次数里的比")
超200ms
发表于 2010-5-3 20:58:55 | 显示全部楼层
本帖最后由 C.L 于 2010-5-3 21:15 编辑
现需要用au3 来模拟出这个抽奖箱 算法以执行10W次最后统计出来的结果准确度来衡量
(检验方法 算出10W次的结果->统计各类各项奖品在总抽奖次数里的比)


LZ好象是要统计中奖的比率,我也来做个练习,10万次超200MS,修改了下,耗时少了点,但还是离200MS有点远~~
$t = TimerInit()

Dim $zhi=0,$tang=0,$juan=0,$liang=0
For $i=0 To 100000
        $s = Random (1,100,1)
        Switch $s
                Case $s<51
                        $zhi +=1
                Case $s>=51 And $s<63
                        $tang += 1
                Case $s>=63 And $s < 68
                        $juan += 1
                Case $s = 68
                        $liang += 1
        EndSwitch
Next

MsgBox (0,TimerDiff ($t),"餐巾纸中了"&$zhi&"次,中奖比率为:"&$zhi/1000&@CRLF& _
                "糖果中了"&$tang&"次,中奖比率为:"&$tang/1000&@CRLF& _
                "优惠券"&$juan&"次,中奖比率为:"&$juan/1000&@CRLF& _
                "猫粮"&$liang&"次,中奖比率为:"&$liang/1000&@CRLF)
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-11-16 09:22 , Processed in 0.089384 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表