독 와인 테스트 스케줄러 구축


16

최근 Puzzling.SE에서는 두 구성 요소를 모두 마신 경우 독이 활성화 될 때 더 큰 수의 두 병이 독에 빠지는 지 결정하는 문제가있었습니다. 결국 대부분의 사람들이 완전히 다른 알고리즘을 사용하여 18 명 또는 19 명의 죄수에게 줄 수있었습니다.

원래 문제점 설명은 다음과 같습니다.

당신은 파티를 던지는 것을 좋아하는 중세 왕국의 통치자입니다. 지난번에 당신의 와인 병 중 하나를 독살하려고했던 구단은 단 10 명의 죄수와 1,000 명 중 그가 어느 병에 독을 넣었는지 알아 내는데 분노했습니다.

이번에는 조금 더 똑똑합니다. 그는 복합 독을 개발했다 P. 이물질은 2 개의 개별적으로 무해한 성분이 섞일 때만 치명적이다. 이것은 에폭시의 작동 방식과 유사합니다. 그는 1,000 병의 또 다른 상자를 보냈습니다. 한 병에는 구성 요소가 C_a있고 다른 병에는 구성 요소 가 있습니다 C_b. ( P = C_a + C_b)

두 성분을 모두 마시는 사람은 하루 중 언제 액체를 흡수했는지에 관계없이 최종 성분을 마신 밤 자정에 사망합니다. 각 독 성분은 두 번째 성분이 활성화 될 때까지 몸에 남아 있기 때문에 하루에 한 성분을 마시고 다음 날에 다른 성분을 마시면 둘째 날이 끝날 자정에 죽습니다.

다음 파티는 이틀 전에 있습니다. 오염 된 2 개의 병을 식별하기 위해 테스트에 사용해야하는 최소 포로 수는 몇 명이며,이 수의 포로와 함께 어떤 알고리즘을 따라야합니까?


보너스
추가로, 당신이 처분 할 때 20 명의 죄수들이 고정 된 한계를 가지고 있다고 가정하면, 이론적으로 테스트 할 수있는 최대 병의 수는 얼마이며 어떤 병이 영향을 받았는지에 대한 정확한 결론을 내립니까?

당신의 임무는 보너스 문제를 해결하기 위해 프로그램을 구축하는 것입니다. 을 감안할 때 n포로가, 프로그램이 중 두 중독 병을 감지 할 수있을 것입니다 테스트 일정을 수립한다 m병을, 어디에서 m가능한 한 크다.

당신의 프로그램은 처음에는 숫자 N, 죄수의 수를 입력으로 받습니다. 그런 다음 출력됩니다.

  • M, 테스트하려는 병의 수. 이 병은에서 (으)로 레이블이 지정 1됩니다 M.

  • N 각 죄수가 마실 병의 라벨이 들어있는 라인.

그러면 여러분의 프로그램은 첫날에 죄수들이 사망 한 입력을 취하고 첫 번째 줄에있는 죄수 1는 다음 줄이됩니다 2. 그런 다음 다음과 같이 출력됩니다 :

  • N각 죄수가 마실 병의 라벨이 들어있는 더 많은 줄. 죽은 죄수는 빈 줄을 가질 것입니다.

귀하의 프로그램은 포로가 두 번째 날에 죽은 입력 및 출력이 개 숫자로 걸릴 것입니다 AB프로그램이 생각이 병은 독을 포함하는 표현.

병과 독에 중독 된 경우 2 명의 죄수와 4 병의 입력 예 는 다음 13같습니다.

> 2      // INPUT: 2 prisoners
4        // OUTPUT: 4 bottles
1 2 3    // OUTPUT: prisoner 1 will drink 1, 2, 3
1 4      // OUTPUT: prisoner 2 will drink 1, 4
> 1      // INPUT: only the first prisoner died
         // OUTPUT: prisoner 1 is dead, he can't drink any more bottles
3        // OUTPUT: prisoner 2 drinks bottle 3
> 2      // INPUT: prisoner 2 died
1 3      // OUTPUT: therefore, the poisoned bottles are 1 and 3.

The above algorithm may not actually work in all
cases; it's just an example of input and output.

프로그램의 테스트 일정은 유효한 병이 되려면 가능한 한 쌍의 독병을 성공적으로 결정해야합니다.

프로그램은 다음 기준에 따라 순서대로 채점됩니다.

  • 케이스를 식별 할 수있는 최대 병 수 N = 20.

  • 사례에 대한 병 수 N = 21, 그 이후에 계속해서 더 높은 사례.

  • 코드 길이 (짧은 코드가 승리합니다.)


하루에 한 명 이상의 피구금자가 죽으면 어떻게 입력이 나타 납니까? 귀하의 예 중 어느 것도 그러한 경우를 다루지 않으며 사양은 나에게 모호합니다.
ESultanik

공백으로 구분 된 포로 목록이있는 한 줄입니까?
ESultanik

더 짧은 코드가 병 수보다 더 중요합니까? 최근 편집에서했던 것처럼 코드 길이를 늘려 병을 하나 더 처리하는 것이 생산적입니까?
pppery

병의 수가 우선합니다. 더 많은 병을 짜기 위해 코드를 더 길고 복잡하게 만들면 생산성이 높아집니다.
Joe Z.

원래 문제에서이 문제를 해결하는 데 2 ​​일밖에 걸리지 않았습니다. 그것도 도전의 규칙입니까? (가능한 솔루션을
심각

답변:


7

Python 2.7.9 — 21 병

ESultanik의 추측이 다수의 포로가 사망 할 때 투입량에 대한 권리가 있다고 가정

r=raw_input;s=str;j=s.join;p=int(r());z=range;q=z(p);x=z(p+1)
print s(p+1)+"\n"+j("\n",(j(" ",(s(a) for a in x if a!=b)) for b in q))
v=r().split();d=[s(a) for a in q if s(a) not in v];d+=[p]if len(d)==1 else [];
print "\n"*p,;r();print j(" ",[s(a) for a in d])

알고리즘 : 모든 죄수는 번호를 제외한 모든 병에서 마신다 (첫 번째 죄수는 첫 번째 병을 마시지 않음). 그들이 죽지 않으면, 그들의 병은 독에 중독됩니다. 한 명의 죄수 만 생존하면 여분의 병이 중독됩니다.


3

펄 5 , 66 병

(21 명의 죄수를위한 72 병)

죄수들은 최적의 두 그룹으로 나뉩니다. 병은 세트로 그룹화됩니다.

그룹 1의 각 죄수는 한 세트를 제외한 모든 세트에서 마신다. 1 ~ 2 명의 생존자가 있습니다. 그들에 의해 마시지 않은 1 또는 2 세트는 2 일까지 계속됩니다.

2 일째에 남은 죄수들 (생존자 포함)은 한 병을 제외한 나머지 병에서 마신다.
죄수 2 명이 살아남 으면 그들이 마시지 않은 병은 독에 중독됩니다.
죄수가 1 명만 남아 있으면 병을 모두 마신 것 또한 의심 스럽다.

이 코드에는 테스트를 용이하게하는 추가 기능이 포함되어 있습니다. poisened 병이 추가 매개 변수로 추가되면 누가 사망했는지에 대한 입력을 요구하지 않습니다.

($p,$f,$l)=@ARGV;
$p=9if!$p;
$m=$p-(2*int($p/4))+1;
$n=$p-$m+2;
$b=$m*(($n+1)/2);
@M=(1..$m);
print"Prisoners: $p\nBottles: $b\n";
# building the sets of items
for$x(@M){
    $j=$k+1;$k+=($n+1)/2;
    $s=join",",($j..$k);
    $A[$x]=$s
}
# assigning the sets to the actors
for$x(@M){
    @T=();
    for$j(@M){if($x!=$j){push@T,split/,/,$A[$j]}}
    print"Prisoner $x drinks @T\n";
    $B[$x]=join",",@T
}
if(!$f||!$l){
    # manual input
    print"Who dies: ";
    $_=<STDIN>;chomp;
    @D=split/ /;
    %h=map{($_,1)}@D;
    @S=grep{!$h{$_}}(@M)
} 
else{
    # calculate who dies based on the parameters
    for$x(@M){
        $d=0;
        map{if($_==$f||$_==$l){$d++}}split/,/,$B[$x];
        if($d>1){push@D,$x}else{push@S,$x}
    }
}
for(@D){print"Prisoner $_ dies\n"}

# calculate the remaining items
for(@S){push@R,split/,/,$A[$_]}@R=sort{$a<=>$b}grep{!$g{$_}++}@R;

# different set of actors if there were 1 or 2 sets remaining
if(@S>1){@S=($S[0],$m+1..$p,$S[1],0)}else{@S=($m+1..$p)};

$i=0;@B=@D=();
# assign an item to each actor
for$x(@S){
    @T=();
    for($j=0;$j<@R;$j++){
        if($i!=$j){push@T,$R[$j]}
    }$i++;
    print"Prisoner $x drinks @T\n"if$x>0;
    $B[$x]=join",",@T
}

if(!$f||!$l){
    # manual input
    print"Who dies: ";
    $_=<STDIN>;chomp;
    @D=sort split/ /;
    if(@D<@S-1){push@D,0} # because the set that noone drinks isn't manually put in
    %h=map{($_,1)}@D;
    @L=grep{!$h{$_}}(@S);
}
else{
    # calculate who dies based on the parameters
    @D=();
    for$x(@S){
        $d=0;
        map{if($_==$f||$_==$l){$d++}}split/,/,$B[$x];
        if($d>1){push@D,$x}else{push@L,$x}
    }
}

for(@D){print"Prisoner $_ dies\n"if$_>0}

# calculate the remaining items
for(@L){push@F,split/,/,$B[$_]}
map{$c{$_}++}@F;
for(keys%c){push(@Z,$_)if$c{$_}==1}
@R=sort{$a<=>$b}@Z;

print"Suspected bottles: @R"

테스트

$ perl poisened_bottles.pl 20
Prisoners: 20
Bottles: 66
Prisoner 1 drinks 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 2 drinks 1 2 3 4 5 6 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 3 drinks 1 2 3 4 5 6 7 8 9 10 11 12 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 4 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 5 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 6 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 7 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 8 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 9 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 55 56 57 58 59 60 61 62 63 64 65 66
Prisoner 10 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 61 62 63 64 65 66
Prisoner 11 drinks 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
Who dies: 2 3 4 5 6 7 8 9 10
Prisoner 2 dies
Prisoner 3 dies
Prisoner 4 dies
Prisoner 5 dies
Prisoner 6 dies
Prisoner 7 dies
Prisoner 8 dies
Prisoner 9 dies
Prisoner 10 dies
Prisoner 1 drinks 2 3 4 5 6 61 62 63 64 65 66
Prisoner 12 drinks 1 3 4 5 6 61 62 63 64 65 66
Prisoner 13 drinks 1 2 4 5 6 61 62 63 64 65 66
Prisoner 14 drinks 1 2 3 5 6 61 62 63 64 65 66
Prisoner 15 drinks 1 2 3 4 6 61 62 63 64 65 66
Prisoner 16 drinks 1 2 3 4 5 61 62 63 64 65 66
Prisoner 17 drinks 1 2 3 4 5 6 62 63 64 65 66
Prisoner 18 drinks 1 2 3 4 5 6 61 63 64 65 66
Prisoner 19 drinks 1 2 3 4 5 6 61 62 64 65 66
Prisoner 20 drinks 1 2 3 4 5 6 61 62 63 65 66
Prisoner 11 drinks 1 2 3 4 5 6 61 62 63 64 66
Who dies: 1 12 14 15 16 17 18 20 11
Prisoner 1 dies
Prisoner 11 dies
Prisoner 12 dies
Prisoner 14 dies
Prisoner 15 dies
Prisoner 16 dies
Prisoner 17 dies
Prisoner 18 dies
Prisoner 20 dies
Suspected bottles: 3 63

수동 입력없이 테스트

$ perl poisened_bottles.pl 7 2 5
Prisoners: 7
Bottles: 12
Prisoner 1 drinks 3 4 5 6 7 8 9 10 11 12
Prisoner 2 drinks 1 2 5 6 7 8 9 10 11 12
Prisoner 3 drinks 1 2 3 4 7 8 9 10 11 12
Prisoner 4 drinks 1 2 3 4 5 6 9 10 11 12
Prisoner 5 drinks 1 2 3 4 5 6 7 8 11 12
Prisoner 6 drinks 1 2 3 4 5 6 7 8 9 10
Prisoner 2 dies
Prisoner 4 dies
Prisoner 5 dies
Prisoner 6 dies
Prisoner 1 drinks 2 5 6
Prisoner 7 drinks 1 5 6
Prisoner 3 drinks 1 2 6
Prisoner 1 dies
Suspected bottles: 2 5

2

전통과 마찬가지로 마지막 참조 답변을 게시합니다.

파이썬 — 7 병

prisoners = int(raw_input())

bottles = 0
while (bottles * (bottles + 1) / 2 - 1) <= prisoners:
    bottles += 1

print bottles

pairs = []
for i in range(bottles):
    for j in range(i + 1, bottles):
        pairs += [str(i + 1) + " " + str(j + 1)]

for i in range(prisoners):
    if i < len(pairs):
        print pairs[i]
    else:
        print

dead_prisoner = raw_input()

for i in range(prisoners):
    print
raw_input() # discard the second day entirely

if dead_prisoner == "":
    print pairs[-1]
else:
    print pairs[int(dead_prisoner) - 1]

각 죄수는 마지막 두 병을 제외한 가능한 한 병의 병을 마신다. 죄수가 죽으면 그 죄수가 마신 쌍은 독살 된 사람들이었습니다. 그렇지 않으면, 그것은 마지막으로 중독 된 두 병이었습니다.

최소한 n(n-1)/2 - 1죄수의 배정을 위해 , 당신은 n병 까지 할 수 있습니다 . 의 n = 7경우이 하한은 20입니다.

우리는 실제로 필요로 일이 솔루션을 하루. 비슷한 범위의 2 일 솔루션은에 대해 최대 20 병을 얻을 수 N = 20있지만 사소한 답변에는 너무 많은 작업이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.