[python-chinese] 谁养鱼的问题.

1. GreyRoar

纯属抛砖引玉. 在啄木鸟上贴我写的这个版本之前,我也给hoxide看过,希望他能够写出更好的程序。 这个是用遍历做的,25号写的第一个版本。27号做出了一些优化,重写了mulitarg()、pailie5(),调整了一下遍历时条件判断的位置和顺序。 代码的确写得很烂,不过功能确实实现了。关于代码书写与功能实现的关系,我在我的页里谈到了一下(GreyRoar)

1.1. Einstein.py

   1 # -*- coding: cp936 -*-
   2 data=[["黄房子","蓝房子","白房子","红房子","绿房子"],["挪威人","英国人","德国人","丹麦人","瑞典人"],["DUNHILL","PRINCE","混合烟", "PALL MALL","BLUE MASTER"],["咖啡","矿泉水","茶","牛奶","啤酒"],["鱼","猫","马", "鸟","狗"]]
   3 def mulitarg(x,y):
   4     return [[0 for col in range(x)] for row in range(y)]
   5 def pailie5():
   6     a=range(5)
   7     def newlist(i,oldlist):
   8         return [x for x in oldlist if x!=i]
   9     return [[x,y,z,i,m] for x,y,z,i,m in [(x,y,z,i,m) for x in a for y in newlist(x,a) for z in newlist(y,newlist(x,a)) for i in newlist(z,newlist(y,newlist(x,a))) for m in newlist(i,newlist(z,newlist(y,newlist(x,a))))]]
  10 answer=mulitarg(5,5)
  11 g=pailie5()
  12 for i in range(120):
  13     if data[0][g[i][1]]=="蓝房子":
  14         answer[0]=[data[0][g[i][0]],data[0][g[i][1]],data[0][g[i][2]],data[0][g[i][3]],data[0][g[i][4]]]
  15         if answer[0].index("白房子")-answer[0].index("绿房子")==1:
  16             for j in range(120):
  17                 if data[1][g[j][0]]=="挪威人":
  18                     answer[1]=[data[1][g[j][0]],data[1][g[j][1]],data[1][g[j][2]],data[1][g[j][3]],data[1][g[j][4]]]
  19                     if answer[0][answer[1].index("英国人")]=="红房子":
  20                         for k in range(120):
  21                             answer[2]=[data[2][g[k][0]],data[2][g[k][1]],data[2][g[k][2]],data[2][g[k][3]],data[2][g[k][4]]]
  22                             if answer[1][answer[2].index("PRINCE")]=="德国人":
  23                                 if answer[0][answer[2].index("DUNHILL")]=="黄房子":
  24                                     for l in range(120):
  25                                         if data[3][g[l][2]]=="牛奶":
  26                                             answer[3]=[data[3][g[l][0]],data[3][g[l][1]],data[3][g[l][2]],data[3][g[l][3]],data[3][g[l][4]]]
  27                                             if answer[2][answer[3].index("啤酒")]=="BLUE MASTER":
  28                                                 if answer[1][answer[3].index("茶")]=="丹麦人":
  29                                                     if answer[0][answer[3].index("咖啡")]=="绿房子":
  30                                                         import math
  31                                                         if int(math.fabs(answer[3].index("矿泉水")-answer[2].index("混合烟")))==1:
  32                                                             for m in range(120):
  33                                                                 answer[4]=[data[4][g[m][0]],data[4][g[m][1]],data[4][g[m][2]],data[4][g[m][3]],data[4][g[m][4]]]
  34                                                                 if answer[2][answer[4].index("猫")]!="混合烟":
  35                                                                     if int(math.fabs(answer[2].index("混合烟")-answer[4].index("猫")))==1:
  36                                                                         if int(math.fabs(answer[4].index("马")-answer[2].index("DUNHILL")))==1:
  37                                                                             if answer[1][answer[4].index("狗")]=="瑞典人":
  38                                                                                 if answer[2][answer[4].index("鸟")]=="PALL MALL":
  39                                                                                     for i in range(5):
  40                                                                                         print answer[i][answer[4].index("鱼")],
  41                                                                                     print

2. Hoxide

粗略讲一下,用了生成器在所有可能的状态空间里进行搜索, times变量用来计算搜索的节点个数, 大概2.9k个节点. 这里看更详细的解释EinsteinHoxide

2.1. EinsteinHoxide.py

   1 data=[['Yellow','Blue','White','Red','Green'],
   2       ['Norwegian','Brit','German','Dane','Swede'],
   3       ['Dunhill','Prince','Blends', 'PallMall','BlueMaster'],
   4       ['Coffee','Water','Tea','Milk','Beer'],
   5       ['Fish','Cat','Horse', 'Bird','Dog']
   6       ]
   7 
   8 def walk(gens):
   9     times=0
  10     ST=[None]*(5*5)
  11     FS=[]
  12     g=gens[0](ST)
  13     FS.append(g)
  14     while FS:
  15         times+=1
  16         #print ST
  17         #print len(FS)
  18         try:
  19             ST=FS[-1].next()
  20             if len(FS)<len(gens):
  21                 g=gens[len(FS)](ST)
  22                 FS.append(g)
  23         except StopIteration:
  24             del FS[-1]
  25     print times
  26 
  27 def geti(v):
  28     global data
  29     for i in range(5):
  30         if data[i].count(v)>0:
  31             return i
  32     print 'error', v
  33     raise EXP
  34 
  35 def setitmpl(t, assert_):
  36     j ,v= assert_
  37     i = geti(v)
  38     if (t[i*5+j] is not None) and t[i*5+j] != v:
  39         return
  40     else:
  41         tt=t+[]
  42         tt[i*5+j] = v
  43         yield tt
  44 
  45 def eqtmpl(t, assert_):
  46     (iv, jv) = assert_
  47     i, j = geti(iv), geti(jv)
  48     ic, jc = t.count(iv), t.count(jv)
  49     if ic==0 and jc==1:
  50         i, j, ic, jc, iv, jv = j, i, jc, ic, jv, iv
  51     if ic==1 and jc==0:
  52         k = t.index(iv) - i*5
  53         if t[j*5+k] is None:
  54             tt=t+[]
  55             tt[j*5+k] = jv
  56             yield tt
  57     elif ic==1 and jc==1:
  58         if t.index(iv)==t.index(jv):
  59             yield t
  60     elif ic==0 and jc==0:
  61         for k in range(5):
  62             if (t[i*5+k] is None) and (t[j*5+k] is None):
  63                 tt = t+[]
  64                 tt[i*5+k], tt[j*5+k] = iv, jv
  65                 yield tt
  66 
  67 def lefttmpl(t,  assert_):
  68     (iv, jv) = assert_
  69     i, j = geti(iv), geti(jv)
  70     ic, jc = t.count(iv), t.count(jv)
  71     if ic==0 and jc==1:
  72         k = t.index(jv) -1 - j*5
  73         if k>=0 and (t[i*5+k] is None):
  74             tt=t+[]
  75             tt[i*5+k] = iv
  76             yield tt
  77     elif ic==1 and jc==0:
  78         k = t.index(iv)+1 - i*5
  79         if k<5 and (t[j*5+k] is None):
  80             tt=t+[]
  81             tt[j*5+k] = jv
  82             yield tt
  83     elif ic==1 and jc==1:
  84         if t.index(iv)+1 ==t.index(jv):
  85             yield t
  86     elif ic==0 and jc==0:
  87         for k in range(4):
  88             if (t[i*5+k] is None) and (t[j*5+k] is None):
  89                 tt = t+[]
  90                 tt[i*5+k], tt[j*5+k+1] = iv, jv
  91                 yield tt
  92 
  93 def nexttmpl(t,  assert_):
  94     (iv, jv) = assert_
  95     i, j = geti(iv), geti(jv)
  96     ic, jc = t.count(iv), t.count(jv)
  97     if ic==0 and jc==1:
  98         i, j, ic, jc, iv, jv = j, i, jc, ic, jv, iv
  99     if ic==1 and jc==0:
 100         k = t.index(iv)+1 - i*5
 101         if k<5 and (t[j*5+k] is None):
 102             tt=t+[]
 103             tt[j*5+k] = jv
 104             yield tt
 105         k = t.index(iv)-1 - i*5
 106         if k>=0 and (t[j*5+k] is None):
 107             tt=t+[]
 108             tt[j*5+k] = jv
 109             yield tt
 110     elif ic==1 and jc==1:
 111         if (t.index(iv)-t.index(jv))**2 == 1:
 112             yield t
 113     elif ic==0 and jc==0:
 114         for k in range(4):
 115             if t[i*5+k]==None and t[j*5+k+1]==None:
 116                 tt = t+[]
 117                 tt[i*5+k], tt[j*5+k+1] = iv, jv
 118                 yield tt
 119             if t[i*5+k+1]==None and t[j*5+k]==None:
 120                 tt = t+[]
 121                 tt[i*5+k+1], tt[j*5+k] = iv, jv
 122                 yield tt
 123 
 124 def magicgen(t):
 125     for i in range(5):
 126         print t[i*5:(i+1)*5]
 127     print
 128     yield None
 129 
 130 gens = [ lambda t: setitmpl(t, (2, 'Milk')),
 131          lambda t: setitmpl(t, (0, 'Norwegian')),
 132          lambda t: eqtmpl(t, ('Red', 'Brit')),
 133          lambda t: eqtmpl(t, ('Swede', 'Dog')),
 134          lambda t: eqtmpl(t, ('Dane', 'Tea')),
 135          lambda t: eqtmpl(t, ('Green', 'Coffee')),
 136          lambda t: eqtmpl(t, ('PallMall', 'Bird')),
 137          lambda t: eqtmpl(t, ('Yellow', 'Dunhill')),
 138          lambda t: eqtmpl(t, ('BlueMaster', 'Beer')),
 139          lambda t: eqtmpl(t, ('German', 'Prince')),
 140          lambda t: lefttmpl(t, ('Green', 'White')),
 141          lambda t: nexttmpl(t, ('Blends', 'Cat')),
 142          lambda t: nexttmpl(t, ('Horse', 'Dunhill')),
 143          lambda t: nexttmpl(t, ('Norwegian', 'Blue')),
 144          lambda t: nexttmpl(t, ('Blends', 'Water')),
 145          lambda t: magicgen(t)
 146          ]
 147 
 148 from time import *
 149 start=clock()
 150 walk(gens)
 151 end=clock()
 152 print end-start

3. Nicholas Ding(Prolog)

  • 将 fish.pl,放到你的~/目录下。
  • 装上SWI-Prolog;进去之后使用

    ?- [fish].
    ?- einstein(Houses, Fish_Owner).
    

就看到答案了。

3.1. fish.pl

next_to(X, Y, List) :- iright(X, Y, List).
next_to(X, Y, List) :- iright(Y, X, List).

iright(L, R, [L | [R | _]]).
iright(L, R, [_ | Rest]) :- iright(L, R, Rest).


einstein(Houses, Fish_Owner) :-
  =(Houses, [[house, norwegian, _, _, _, _], _, [house, _, _, _, milk, _], _, _]),
  member([house, brit, _, _, _, red], Houses),
  member([house, swede, dog, _, _, _], Houses),

  member([house, dane, _, _, tea, _], Houses),
  iright([house, _, _, _, _, green], [house, _, _, _, _, white], Houses),
  member([house, _, _, _, coffee, green], Houses),
  member([house, _, bird, pallmall, _, _], Houses),

  member([house, _, _, dunhill, _, yellow], Houses),
  next_to([house, _, _, dunhill, _, _], [house, _, horse, _, _, _], Houses),
  member([house, _, _, _, milk, _], Houses),
  next_to([house, _, _, marlboro, _, _], [house, _, cat, _, _, _], Houses),

  next_to([house, _, _, marlboro, _, _], [house, _, _, _, water, _], Houses),
  member([house, _, _, winfield, beer, _], Houses),
  member([house, german, _, rothmans, _, _], Houses),
  next_to([house, norwegian, _, _, _, _], [house, _, _, _, _, blue], Houses),

  member([house, Fish_Owner, fish, _, _, _], Houses).