102 lines
3.3 KiB
Python
102 lines
3.3 KiB
Python
import psyco; psyco.full()
|
|
|
|
class Content: elems= """Beer Coffee Milk Tea Water
|
|
Danish English German Norwegian Swedish
|
|
Blue Green Red White Yellow
|
|
Blend BlueMaster Dunhill PallMall Prince
|
|
Bird Cat Dog Horse Zebra""".split()
|
|
class Test: elems= "Drink Person Color Smoke Pet".split()
|
|
class House: elems= "One Two Three Four Five".split()
|
|
|
|
for c in (Content, Test, House):
|
|
c.values = range(len(c.elems))
|
|
for i, e in enumerate(c.elems):
|
|
exec "%s.%s = %d" % (c.__name__, e, i)
|
|
|
|
def finalChecks(M):
|
|
def diff(a, b, ca, cb):
|
|
for h1 in House.values:
|
|
for h2 in House.values:
|
|
if M[ca][h1] == a and M[cb][h2] == b:
|
|
return h1 - h2
|
|
assert False
|
|
|
|
return abs(diff(Content.Norwegian, Content.Blue,
|
|
Test.Person, Test.Color)) == 1 and \
|
|
diff(Content.Green, Content.White,
|
|
Test.Color, Test.Color) == -1 and \
|
|
abs(diff(Content.Horse, Content.Dunhill,
|
|
Test.Pet, Test.Smoke)) == 1 and \
|
|
abs(diff(Content.Water, Content.Blend,
|
|
Test.Drink, Test.Smoke)) == 1 and \
|
|
abs(diff(Content.Blend, Content.Cat,
|
|
Test.Smoke, Test.Pet)) == 1
|
|
|
|
def constrained(M, atest):
|
|
if atest == Test.Drink:
|
|
return M[Test.Drink][House.Three] == Content.Milk
|
|
elif atest == Test.Person:
|
|
for h in House.values:
|
|
if ((M[Test.Person][h] == Content.Norwegian and
|
|
h != House.One) or
|
|
(M[Test.Person][h] == Content.Danish and
|
|
M[Test.Drink][h] != Content.Tea)):
|
|
return False
|
|
return True
|
|
elif atest == Test.Color:
|
|
for h in House.values:
|
|
if ((M[Test.Person][h] == Content.English and
|
|
M[Test.Color][h] != Content.Red) or
|
|
(M[Test.Drink][h] == Content.Coffee and
|
|
M[Test.Color][h] != Content.Green)):
|
|
return False
|
|
return True
|
|
elif atest == Test.Smoke:
|
|
for h in House.values:
|
|
if ((M[Test.Color][h] == Content.Yellow and
|
|
M[Test.Smoke][h] != Content.Dunhill) or
|
|
(M[Test.Smoke][h] == Content.BlueMaster and
|
|
M[Test.Drink][h] != Content.Beer) or
|
|
(M[Test.Person][h] == Content.German and
|
|
M[Test.Smoke][h] != Content.Prince)):
|
|
return False
|
|
return True
|
|
elif atest == Test.Pet:
|
|
for h in House.values:
|
|
if ((M[Test.Person][h] == Content.Swedish and
|
|
M[Test.Pet][h] != Content.Dog) or
|
|
(M[Test.Smoke][h] == Content.PallMall and
|
|
M[Test.Pet][h] != Content.Bird)):
|
|
return False
|
|
return finalChecks(M)
|
|
|
|
def show(M):
|
|
for h in House.values:
|
|
print "%5s:" % House.elems[h],
|
|
for t in Test.values:
|
|
print "%10s" % Content.elems[M[t][h]],
|
|
print
|
|
|
|
def solve(M, t, n):
|
|
if n == 1 and constrained(M, t):
|
|
if t < 4:
|
|
solve(M, Test.values[t + 1], 5)
|
|
else:
|
|
show(M)
|
|
return
|
|
|
|
for i in xrange(n):
|
|
solve(M, t, n - 1)
|
|
M[t][0 if n % 2 else i], M[t][n - 1] = \
|
|
M[t][n - 1], M[t][0 if n % 2 else i]
|
|
|
|
def main():
|
|
M = [[None] * len(Test.elems) for _ in xrange(len(House.elems))]
|
|
for t in Test.values:
|
|
for h in House.values:
|
|
M[t][h] = Content.values[t * 5 + h]
|
|
|
|
solve(M, Test.Drink, 5)
|
|
|
|
main()
|