【问题标题】:Using Bash to Generate Lotto Numbers使用 Bash 生成乐透号码
【发布时间】:2014-02-15 02:34:36
【问题描述】:

我有一个简单的 bash 脚本,它生成以下内容:

These are your winning lottery numbers: 
 27  6   29  17  15  47
 19  16  33  15  20  14
 29  34  48  19  33  40

这是它的代码:

#!/bin/bash

tickets="$1"

function get_tickets { printf "How many tickets are you going to get? "; read tickets;}

function gen_numbers { printf "\nThese are your winning lottery numbers: \n"; 

    for ((z=1 ; z<=tickets ; z++)); do
         for ((i=0; i<6; i++ )); do 
            x=`echo $[ 1 + $[ RANDOM % 49 ]]`; 
            printf "\t $x"; 
         done;
         printf "\n" 
    done; 
    printf "\n"; }


############################
if [[ -z $tickets ]]  ; then
    get_tickets
    gen_numbers
else
    gen_numbers
fi

我的问题是,有谁知道如何修改它以防止每行出现重复的数字?我想我会使用 uniq 和一个数组,但不确定它会是什么样子。任何意见,将不胜感激;谢谢!

  • 这只是一个有趣的脚本。

【问题讨论】:

  • 避免按行重复(票证?)或根本不重复?
  • 是的;避免在一行中重复数字(按票)。

标签: arrays bash uniq


【解决方案1】:

你的尝试很不错。但是,我认为使用shuf 命令获取随机值会更容易、更安全:

$ shuf -i 1-49 -n18 | xargs -n6
39 42 43 7 14 23
10 27 5 13 49 8
31 36 19 47 28 4

shuf -i X-Y -nZ 在 X 和 Y 之间给出 Z 个随机数。然后xargs -nT 将它们格式化为每行 T 个数的组。


更新

现在我看到了评论:

是的;避免在一行中重复数字(按票)。

在这种情况下,您只需执行 shuf -i 1-49 -n6 即可获得 6 个随机数。输出是行分隔的,因此您可以使用tr '\n' ' ' 使其以空格分隔。

如果您想要很多行,例如 5 行,您可以这样做:

for i in {1..5}; do shuf -i 1-49 -n6; done | xargs -n6

样本输出:

$ for i in {1..5}; do shuf -i 1-49 -n6; done | xargs -n6
4 45 12 42 37 46
42 20 29 22 12 5
40 41 14 28 4 2
35 24 16 22 2 39
14 46 47 20 21 41

【讨论】:

  • 查看 shuf 的手册页;这会防止重复吗?它如何更安全?
  • 我也对它有疑问,所以我做了很多shuf -i 1-49 -n18 | uniq -c的尝试,它总是显示每个号码有1个匹配项。您会看到,如果将 -n 增加到 49,则每个数字只显示一次。
  • 啊,真的很好听,很有口才。我也喜欢您的解决方案,尤其是因为它如此简洁。谢谢。
【解决方案2】:

为避免按行重复,请使用数组来标记使用的值。这是您的脚本的修改版本:

for ((z = 1; z<=tickets ; z++)); do
     i=0
     used=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
     for (( ; i<6;  )); do 
        x=`echo $[ 1 + $[ RANDOM % 49 ]]`; 
        if [ ${used[$x]} -eq 0 ]
        then
            printf "\t $x"; 
            i=$((i + 1))
            used[$x]=1
        fi
     done;
     printf "\n" 
done; 
printf "\n"; }

编辑:解释。

思路很简单,我们用数组来标记那些已经使用过的值。

最初,数组的所有元素(50 个元素对应于值 [0, 49])都设置为零,即所有数字都可用。

对于每个随机数 x,我们检查该数字是否可用(used[x] = 0),如果是,我们增加计数器 i 并标记该值( used[x] = 1) 避免重复。

如果该值已被使用,只需反复尝试,直到找到未使用的值。

【讨论】:

  • 非常有趣;谢谢 - 在我确切了解它在数组中的工作原理之前,我将不得不对其进行一段时间的审查,但它似乎可以解决问题!
  • 非常感谢;非常感谢。
【解决方案3】:

检查这个,它是仅使用 JavaScript 实现乐透号码生成器的一个很好的例子:https://lotto6aus49online.de/#zaufallszahlen;您可以通过单击每个数字来停止生成器,这会为算法增加额外的随机性。希望你喜欢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多