Создайте наименьшее количество лотерейных билетов, чтобы иметь как минимум N хороших номеров

11

Это довольно сложный, но очень интересный предмет по математике (известный как «проблема покрытия» ),

И я хотел бы, чтобы вы помогли в его реализации.

Представьте себе лотерею, в которой каждый билет должен выбрать 5 случайных чисел в наборе из 50 чисел (от 1 до 50).

Достаточно легко узнать вероятность выигрышного билета или вероятность иметь 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)


Благодаря!

XEM
источник
Относящиеся .
Питер Тейлор
4
Этот вопрос нуждается в различных разъяснениях. Вы после программы, функции или или? Имеет ли значение выходной формат? Нужно ли индексировать числа от 1 или они могут быть проиндексированы от 0? И каково объективное условие победы?
Питер Тейлор
3
@ xem это почти принадлежит тогда Math SE. Где они, вероятно, докажут вам, что цифры не в вашу пользу (хотя существует какой-то джекпот, но стоит покупать билеты)
Cruncher
2
Что такое хороший номер?
DavidC
2
Я почти уверен, что можно доказать, что вы потеряете много денег, если действительно пойдете и купите билеты, полученные с помощью такой программы.
Майкл Хэмптон

Ответы:

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)генерирует гораздо больше решений, чем ОП.
Groo
Я знаю @Groo, я сказал, что знаю, что это не было оптимальным, но это была первая рабочая версия, которую я имел;) Любое предложение о том, как удалить «лишние» результаты?
Greuze
Привет Гроо, Привет, Грэйз, большое спасибо за эту первую попытку. У вас 21 балл (потому что вы сгенерировали 21 билет для (10,5,2)). Однако я не знаю, как удалить лишние результаты, поэтому я создал эту тему. Мне все еще интересно, как выглядит лучший алгоритм для выполнения этой работы.
xem
Вот несколько хороших материалов по этому вопросу: (1) dip.sun.ac.za/~vuuren/papers/lotery_artikel1oud.pdf , (2) goo.gl/Ex7Woa , (3) google.fr/…
xem
1
Это NP-полная проблема, поэтому я боюсь, что нет волшебного решения. Мы должны «грубой силой» вычислить все возможные тикеты и исключить излишних, сравнив каждую группу чисел со всеми другими тикетами. Это займет экспоненциальное время.
xem