生成最少的彩票以拥有至少N个好数字


11

这是一个相当复杂但非常有趣的数学学科(称为“覆盖问题”),

我希望您能帮助您实施它。

想象一下一个彩票游戏,其中每张彩票必须从50个数字(从1到50)中选择5个随机数字。

很容易知道中奖的概率,或者拥有1、2、3或4个好数字的概率。

“生成”具有1、2、3、4个良好数字的所有票证也很容易。

我的问题(和代码挑战)与此有关,但略有不同:

我想买一些彩票(尽可能少的),例如我的至少一张彩票有3个好数字。

挑战

您的目标是以任何语言实现这样的通用解决方案(作为程序或只是函数):

// Input: 3 prameters
min_lottery_tickets(total_numbers_to_choose_from, how_many_numbers_to_choose, how_many_good_numbers_i_want)

对于上面的示例,只需调用:

min_lottery_tickets(50, 5, 3)

该程序将生成最小的票证集合以实现此目标。


例:

 min_lottery_tickets(10, 5, 2)

将输出7张票,例如:

1   2   3   4   5
5   6   7   8   9
10  1   2   6   7
10  3   4   8   9
3   4   6   7   8
1   2   3   8   9
1   4   9   5   10

因为这样的票足以覆盖从1到10的任何一对数字。


输出量

文字,每张票一行,表格或数字之间的空格


谁赢

效率最高的程序获胜(即,针对上述参数生成票证最少的程序):

min_lottery_tickets(50, 5, 3)


谢谢!



4
这个问题需要各种澄清。您是追求程序,功能还是两者中的一个?输出格式重要吗?数字是否必须从1开始索引,还是可以从0开始索引?客观的获胜条件是什么?
彼得·泰勒

3
@xem这几乎属于Math SE了。他们可能会向您证明这些数字对您不利(尽管确实存在一些中奖号码,值得购买门票)
Cruncher

2
什么是数字?
DavidC

2
我很确定,如果您实际去购买该程序输出的票证,您将损失很多钱。
迈克尔·汉普顿

Answers:


1

我知道这不是最佳方法,但这是node.js中的代码:

function min_lottery_tickets(total_numbers_to_choose_from, how_many_numbers_to_choose, how_many_good_numbers_i_want) {
    c(function(result) {
        var other = result[result.length - 1];
        while (result.length < how_many_numbers_to_choose) {
            other++;
            var already = false;
            for (var i = 0; i < result.length; i++) {
                if (other === result[i]) {
                    already = true;
                    break;
                }
            }
            if (!already) {
                result.push(other);            
            }
        }
        if (other <= total_numbers_to_choose_from) {
            // Print results
            console.log(result);
        }
    }, total_numbers_to_choose_from, how_many_good_numbers_i_want);
}

function c(next, total_numbers, length, start, results) {
    if (!start) start = 1;
    if (!results) results = [];

    for (var i = start; i <= total_numbers + 1 - length; i++) {
        var resultsNew = results.slice(0);
        resultsNew.push(i);
        if (length > 1) {
            c(next, total_numbers, length - 1, i + 1, resultsNew);
        } else {
            next(resultsNew);
        }
    }
}

一些示例结果:

> min_lottery_tickets(5, 3, 2)
[ 1, 2, 3 ]
[ 1, 3, 4 ]
[ 1, 4, 5 ]
[ 2, 3, 4 ]
[ 2, 4, 5 ]
[ 3, 4, 5 ]

其他:

> min_lottery_tickets(10, 5, 2)
[ 1, 2, 3, 4, 5 ]
[ 1, 3, 4, 5, 6 ]
[ 1, 4, 5, 6, 7 ]
[ 1, 5, 6, 7, 8 ]
[ 1, 6, 7, 8, 9 ]
[ 1, 7, 8, 9, 10 ]
[ 2, 3, 4, 5, 6 ]
[ 2, 4, 5, 6, 7 ]
[ 2, 5, 6, 7, 8 ]
[ 2, 6, 7, 8, 9 ]
[ 2, 7, 8, 9, 10 ]
[ 3, 4, 5, 6, 7 ]
[ 3, 5, 6, 7, 8 ]
[ 3, 6, 7, 8, 9 ]
[ 3, 7, 8, 9, 10 ]
[ 4, 5, 6, 7, 8 ]
[ 4, 6, 7, 8, 9 ]
[ 4, 7, 8, 9, 10 ]
[ 5, 6, 7, 8, 9 ]
[ 5, 7, 8, 9, 10 ]
[ 6, 7, 8, 9, 10 ]

其他:

> min_lottery_tickets(10, 5, 3)
[ 1, 2, 3, 4, 5 ]
[ 1, 2, 4, 5, 6 ]
[ 1, 2, 5, 6, 7 ]
[ 1, 2, 6, 7, 8 ]
[ 1, 2, 7, 8, 9 ]
[ 1, 2, 8, 9, 10 ]
[ 1, 3, 4, 5, 6 ]
[ 1, 3, 5, 6, 7 ]
[ 1, 3, 6, 7, 8 ]
[ 1, 3, 7, 8, 9 ]
[ 1, 3, 8, 9, 10 ]
[ 1, 4, 5, 6, 7 ]
[ 1, 4, 6, 7, 8 ]
[ 1, 4, 7, 8, 9 ]
[ 1, 4, 8, 9, 10 ]
[ 1, 5, 6, 7, 8 ]
[ 1, 5, 7, 8, 9 ]
[ 1, 5, 8, 9, 10 ]
[ 1, 6, 7, 8, 9 ]
[ 1, 6, 8, 9, 10 ]
[ 1, 7, 8, 9, 10 ]
[ 2, 3, 4, 5, 6 ]
[ 2, 3, 5, 6, 7 ]
[ 2, 3, 6, 7, 8 ]
[ 2, 3, 7, 8, 9 ]
[ 2, 3, 8, 9, 10 ]
[ 2, 4, 5, 6, 7 ]
[ 2, 4, 6, 7, 8 ]
[ 2, 4, 7, 8, 9 ]
[ 2, 4, 8, 9, 10 ]
[ 2, 5, 6, 7, 8 ]
[ 2, 5, 7, 8, 9 ]
[ 2, 5, 8, 9, 10 ]
[ 2, 6, 7, 8, 9 ]
[ 2, 6, 8, 9, 10 ]
[ 2, 7, 8, 9, 10 ]
[ 3, 4, 5, 6, 7 ]
[ 3, 4, 6, 7, 8 ]
[ 3, 4, 7, 8, 9 ]
[ 3, 4, 8, 9, 10 ]
[ 3, 5, 6, 7, 8 ]
[ 3, 5, 7, 8, 9 ]
[ 3, 5, 8, 9, 10 ]
[ 3, 6, 7, 8, 9 ]
[ 3, 6, 8, 9, 10 ]
[ 3, 7, 8, 9, 10 ]
[ 4, 5, 6, 7, 8 ]
[ 4, 5, 7, 8, 9 ]
[ 4, 5, 8, 9, 10 ]
[ 4, 6, 7, 8, 9 ]
[ 4, 6, 8, 9, 10 ]
[ 4, 7, 8, 9, 10 ]
[ 5, 6, 7, 8, 9 ]
[ 5, 6, 8, 9, 10 ]
[ 5, 7, 8, 9, 10 ]
[ 6, 7, 8, 9, 10 ]

1
min_lottery_tickets(10, 5, 2)与OP相比,您生成的解决方案要多得多。
Groo 2014年

我知道@Groo,我说我知道它不是最佳的,但这是我的第一个工作版本;)关于如何删除“冗余”结果的任何建议吗?
greuze 2014年

嗨,格罗,嗨,格劳兹,非常感谢您的首次尝试。您的分数为21(因为您为(10,5,2)生成了21张票)。我不知道如何删除多余的结果,所以才创建了这个主题。我仍然想知道执行此工作的最佳算法是什么样的。
xem 2014年

下面是一些关于这个问题好读数:(1)dip.sun.ac.za/~vuuren/papers/lotery_artikel1oud.pdf,(2)goo.gl/Ex7Woa,(3)google.fr/...
XEM

1
这是一个NP完全问题,所以恐怕没有神奇的解决方案。我们必须“蛮力”计算所有可能的票证,并通过将每个数字组与所有其他票证进行比较来消除那些多余的票证。那将花费指数时间。
xem 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.