In [27]:
from __future__ import division
# we have 13 virtual mice, mouse number 0,4,8 are "empty" mice.
wine_groups_for_virtual_mice = [set() for i in range(13)]
for i in range(1000):
    i0 = i%80
    i1 = i0%4
    i2 = (i0//4)%4
    i3 = i0//16
    wine_groups_for_virtual_mice[i1].add(i)
    wine_groups_for_virtual_mice[4+i2].add(i)
    wine_groups_for_virtual_mice[8+i3].add(i)
In [28]:
encodings=[0]*1000
j = 1
for i in range(13):
    if i not in [0,4,8]:
        for w in wine_groups_for_virtual_mice[i]:
            encodings[w]|=j
        j<<=1
print(encodings)
[0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140, 144, 145, 146, 148, 160, 161, 162, 164, 256, 257, 258, 260, 264, 265, 266, 268, 272, 273, 274, 276, 288, 289, 290, 292, 512, 513, 514, 516, 520, 521, 522, 524, 528, 529, 530, 532, 544, 545, 546, 548, 0, 1, 2, 4, 8, 9, 10, 12, 16, 17, 18, 20, 32, 33, 34, 36, 64, 65, 66, 68, 72, 73, 74, 76, 80, 81, 82, 84, 96, 97, 98, 100, 128, 129, 130, 132, 136, 137, 138, 140]
In [29]:
wine_groups_for_real_mice=[ set() if i in [0,4,8] else wine_groups_for_virtual_mice[i] for i in range(13)]
In [30]:
def test_result(poison_wine):
    return [bool(poison_wine&w) for w in wine_groups_for_real_mice]
In [31]:
def make_decision(result):
    r = result[:]
    r[0] = sum(r[:4])<2
    r[4] = sum(r[4:8])<2
    r[8] = sum(r[8:])<2
    g1, g2, g3 = set(), set(), set()
    for i in range(4):
        if r[i]:
            g1 |= wine_groups_for_virtual_mice[i]
    for i in range(4,8):
        if r[i]:
            g2 |= wine_groups_for_virtual_mice[i]
    for i in range(8,13):
        if r[i]:
            g3 |= wine_groups_for_virtual_mice[i]
    return g1 & g2 & g3

def verify(poison_wine, decision):
    return poison_wine <= decision
    
In [34]:
m = 0
for i in range(999):
    if i%10==0:
        print(i,m)
    for j in range(i,1000):
        poison = {i,j}
        result = test_result(poison)        
        decision = make_decision(result)
        if len(decision) > 104 or not verify(poison, decision):
            print(i,j, len(decision))        
            break
        m = max(len(decision), m)
print("done")
(0, 0)
(10, 104)
(20, 104)
(30, 104)
(40, 104)
(50, 104)
(60, 104)
(70, 104)
(80, 104)
(90, 104)
(100, 104)
(110, 104)
(120, 104)
(130, 104)
(140, 104)
(150, 104)
(160, 104)
(170, 104)
(180, 104)
(190, 104)
(200, 104)
(210, 104)
(220, 104)
(230, 104)
(240, 104)
(250, 104)
(260, 104)
(270, 104)
(280, 104)
(290, 104)
(300, 104)
(310, 104)
(320, 104)
(330, 104)
(340, 104)
(350, 104)
(360, 104)
(370, 104)
(380, 104)
(390, 104)
(400, 104)
(410, 104)
(420, 104)
(430, 104)
(440, 104)
(450, 104)
(460, 104)
(470, 104)
(480, 104)
(490, 104)
(500, 104)
(510, 104)
(520, 104)
(530, 104)
(540, 104)
(550, 104)
(560, 104)
(570, 104)
(580, 104)
(590, 104)
(600, 104)
(610, 104)
(620, 104)
(630, 104)
(640, 104)
(650, 104)
(660, 104)
(670, 104)
(680, 104)
(690, 104)
(700, 104)
(710, 104)
(720, 104)
(730, 104)
(740, 104)
(750, 104)
(760, 104)
(770, 104)
(780, 104)
(790, 104)
(800, 104)
(810, 104)
(820, 104)
(830, 104)
(840, 104)
(850, 104)
(860, 104)
(870, 104)
(880, 104)
(890, 104)
(900, 104)
(910, 104)
(920, 104)
(930, 104)
(940, 104)
(950, 104)
(960, 104)
(970, 104)
(980, 104)
(990, 104)
done
In [ ]: