Work the Shell - 一锤定音!
我承认,我的孩子们和我经常发现自己身处当地的街机游戏厅玩电子游戏。 现在的街机游戏厅似乎有两种基本类型:一种是玩游戏赢取免费游戏和获得高分的,另一种是基于票券的,在游戏中表现出色会产生票券,您可以兑换成廉价的小饰品或极其廉价的毛绒玩具。
我们倾向于去后一种,其中一款引起我注意的游戏是热门电视节目Deal or No Deal的视频版。 这让我开始思考赔率和概率以及这些游戏实际上是如何运作的。
游戏非常简单:您被告知一系列奖品隐藏在公文包中,您选择要淘汰哪些,并赢得最后一个公文包中剩下的东西。 这并不是太令人兴奋,除非在您进行的过程中,您有机会获得特定的现金奖励而不是继续游戏。
在电视节目中,有 26 个箱子,奖品范围从 0.01 美元到 1,000,000.00 美元不等。 迷人的模特拿着每个箱子,游戏的典型流程是玩家猜测一堆要淘汰的箱子,成组进行。 如果被淘汰的箱子里的奖品价值较低,那是好事——因此,更有可能赢得大笔资金。 如果里面有高价值的奖品,那就不好了。
在每组箱子被淘汰后,庄家会向玩家提供“交易”,以停止玩游戏——支付的金额高于最低未识别的奖品,但显然低于最高未识别的奖品。
奖品为 0.01、1、5、10、25、50、75、100、200、300、400、500 和 750 美元,然后是较大的价值:1,000、5,000、10,000、25,000、50,000、75,000、100,000、200,000、300,000、400,000、500,000、750,000 和 1,000,000 美元。
计算平均支出,假设您在游戏开始时有平等的机会选择每个箱子,这很容易:将它们加起来并除以 26。结果是 131,477.54 美元。 如果他们给我 13 万美元而不是玩游戏? 即使它比平均预期支出略低,我也会接受。 成交!
假设我们已经完成了大部分游戏,并且 20 个可能的奖品已被淘汰。 剩下的是 0.01、50、300、1,000 和 250,000 美元。 您选择 250,000 美元奖品箱子的机会? 五分之一。
预期支出为 50,270 美元,如果这就是您获得的报价,那么它明显优于您面临的五种可能结果中的四种。 我的建议? 成交!
事实证明,在“交易”中加入了一些随机因素,因此在游戏本身中,它们会在百分位值上下浮动。
为了以 shell 脚本的形式对此进行实验(是的,我只用了半个专栏才写到我的第一行代码),我们需要使用数组——这确实有点令人困惑。 以下是我们如何定义 26 个公文包的方法
declare -a cases=(0.01 1 5 10 25 50 75 100 200 300 400 500 750 1000 5000 10000 25000 50000 75000 100000 200000 300000 400000 500000 750000 1000000)
这可能是您第一次在 shell 中看到 declare 语句。 在这种情况下,-a 标志将变量声明为数组。 然而,它的用法不是强制性的——可以通过简单地使用数组赋值语法(括号内的值列表)来隐式声明数组。
您可以使用 $var[index] 引用单个数组元素,但由于 shell 解析内容的方式,这里有一个转折。 您需要做的是实际上用花括号将其括起来:${var[index]}。 添加 #,您将获得数组中元素的数量,如下所示
echo Total number of array elements is ${#cases[*]}
打印的值将是 26,这正是我们想要的 Deal or No Deal。 要查看值 #11,您可以使用${cases[11]},但这不对。 为什么? 因为 shell 数组的索引从零开始,所以箱子 #11 实际上是 ${cases[10]},是的,这非常令人困惑。
让我们从编写可以计算在您从集合中选择单个公文包之前的预期支出的代码片段开始
for (( val=0 ; $val < ${#cases[*]} ; val+=1 )) ; do sum=$(( $sum+${cases[$val]} )) done echo sum = $sum, payout = $(( $sum / ${#cases[*]} ))
坏消息? 事实证明,0.01 的值确实会把事情搞砸,因为我们无法使用非整数值进行整数数学运算。 因此,由于 0.01 的值实际上证明对事情没有太大影响,我将用值 0 替换它。 这是输出
sum = 3418416, payout = 131477
这相当准确。 我们之前的计算结果是 131,477.54。 对于游戏工作来说足够接近了!
现在,让我们随机选出 22 个箱子,计算预期支出,并根据剩余价值提供“交易”。
首先,选出一些箱子
for (( picked=1 ; $picked <= 22 ; )) ; do pick=$(( RANDOM % 26 )) if [ ${cases[$pick]} -ne -1 ] ; then cases[$pick]=-1 picked=$(( $picked + 1 )) fi done
通过将其值设置为 -1,可以将除四个箱子之外的所有箱子都移出游戏(记住我们使用 0 来表示 0.01 美元)。 要查看游戏中还剩下什么并仅计算剩余值的预期支出,请执行以下操作
for (( val=0 ; $val < ${#cases[*]} ; val+=1 )) ; do if [ ${cases[$val]} -ne -1 ] ; then echo \(Still in the game: a prize \ worth \$${cases[$val]}\) sum=$(( $sum+${cases[$val]} )) cnt=$(( $cnt+1 )) fi done echo Win \$$(( $sum / $cnt )) if you stop. \ Deal, or no deal\? exit 0
运行代码,这是一个示例输出
(Still in the game: a prize worth $50) (Still in the game: a prize worth $1000) (Still in the game: a prize worth $5000) (Still in the game: a prize worth $400000) Win $101512 if you stop. Deal, or no deal?
您会接受交易,还是尝试 400,000 美元的箱子?
Dave Taylor 自 1980 年首次登录 ARPAnet 以来一直参与 UNIX。 这意味着,是的,他即将迎来 30 周年。 您几乎可以在任何在线地方找到他,但请从这里开始:www.DaveTaylorOnline.com。