최소한 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에서 색인화 할 수 있습니까? 그리고 객관적인 승리 조건은 무엇입니까?
Peter Taylor

3
@xem 이것은 대부분 Math SE에 속합니다. 그들은 아마도 당신에게 숫자가 당신에게 유리하지 않다는 것을 증명할 것입니다 (티켓 구매 가치가있는 대박 번호가 있지만)
Cruncher

2
좋은 숫자 는 무엇입니까 ?
DavidC

2
실제로 그러한 프로그램으로 티켓을 구매하면 많은 돈을 잃을 가능성이 있다고 확신합니다.
Michael Hampton

답변:


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

나는 @Groo를 알고있다. 나는 그것이 그것이 최적이 아니라는 것을 안다고 말했다. 그러나 이것은 내가 가지고있는 최초의 작업 버전이었다.
greuze

안녕하세요 Groo, 안녕하세요,이 첫 번째 시도에 감사드립니다. (10,5,2)에 대해 21 개의 티켓을 생성했기 때문에 점수는 21입니다. 그러나 중복 결과를 제거하는 방법을 모르므로이 주제를 작성했습니다. 나는이 작업을 수행하는 가장 좋은 알고리즘이 어떻게 보이는지 아직도 궁금합니다.
xem


1
그것은 NP가 완전한 문제이므로 마법의 해결책이 없을 것 같습니다. 우리는 가능한 모든 티켓의 계산과 각 숫자 그룹을 다른 모든 티켓과 비교하여 중복되는 사람들을 제거해야합니다. 기하 급수적으로 시간이 걸립니다.
xem
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.