Jump to 0 top | 1 navigation | 2 content | 3 extra information (sidebar) | 4 footer | 5 toolbar


Content

让我们从游戏开始──点灯(2)

第一天
对于这样的问题,我们最直接的想法就是穷举法:把所有的组合都试一次,有此来找到所有可能的解。
那么我们怎么的到这所有的组合呢?让我们来回想一下前面理论分析的内容。所有灯的状态都用0和1来表示,如果我们把这个4×4的二维数组组合成一个0、1序列,那么我们这个得到的0、1序列的是[0, 2^16)中所有的整数.我们用如下的语句得到这个整数序列:

  1. [x for x in xrange(2**16)]#由于数量比较大,我们没有使用range。两者之间的额区别google一下就可以了。

现在我们把这些整数变成二进制!由于python里面没有直接的函数可以转换,所有我们要自己完成:

  1. bstr = lambda n, l=16: n<0 and binarystr((2L<>1).lstrip('0')+str(n&1) or '0'

>>>bstr(5)
‘101′

注意一下返回的是一个字符串(这个是肯定的,想想就知道了)。zfill可以补齐我们需要的位数。那么生成序列的语句就出来了:

  1. [bstr(x).zfill(16) for x in xrange(2**16)]

现在我们把得到的序列变成数组。numarray是不错的选择。

>>> import numarray.strings as nastr
>>> a=nastr.array(’101010101′, itemsize=1)
>>> a
CharArray([’1′, ‘0′, ‘1′, ‘0′, ‘1′, ‘0′, ‘1′, ‘0′, ‘1′])
>>> numarray.reshape(a,3,3)
CharArray([[’1′, ‘0′, ‘1′],
[’0′, ‘1′, ‘0′],
[’1′, ‘0′, ‘1′]]))

还要把字符转换成数字,用eval就好了。
Hoho, 看来我们需要的东西基本已经齐全了,我们现在先把得到的东西都组合一下。得到下面的代码:

  1. from numarray import *
  2. import numarray.strings as nastr
  3. PosSol=[reshape(nastr.array(bstr(x).zfill(16), itemsize=1),4,4).eval() for x in xrange(2**16)]#PosSol:Possible Solutions

当然,我们现在是限定一个4×4的情况,如果要解n×n,小小改动一下就可以了。如果你对上面的代码的结果有些怀疑,那试试2×2的情况,代码怎么修改相信你应该很清楚,看看结果吧。好了,让我们继续吧。
现在我们有了开关状态的所有组合,那么我们就要根据这些组合计算出灯泡状态。让我们想想灯泡状态的代码要怎么写。我们用x(表示列),y(表示行)表示给 定的灯泡位置,我们根据开关状态计算它是否被点亮。相信很多人的第一想法就是按照给定的x,y得到x+1,x-1,y+1,y-1这些,还要自己判断是否 在给定的元素处于数组的边界……天,我不要再想这种方法了。虽然很直接,但是一点都不好。让我们在脑子里面最后想想这种充满臭味的代码,你难道忍心你的代 码是这样的吗?看来我们要用其他的方法来作,至少看上去要聪明一些的方法。
不如我们不考虑边界的问题,这样不就简单了。:)由于我们计算的是“1”的个数,所以我们把一个4×4的数组加一个由“0”组成的边框。这样就没有“出界”问题了。由于我们的数组是4×4,那么我们这么写:

  1. tmpArray=zeros((6,6))
  2. tmpArray[1:5,1:5]=PosSol.copy()

然后把我们需要的3×3的“抠出来”:

  1. TxT=take(take(tmpArray, [x,x+1,x+2]),[y,y+1,y+2], axis=1)#TxT:Three X Three Square

好了,现在我们只要去掉四个角的数,然后求和判断是不是奇数就知道灯泡是不是点亮了:

  1. putmask(TxT,[1,0,1,0,0,0,1,0,1],0)
  2. value=sum(sum(finalSquare),1)

现在我们全部汇总就得到了游戏的解法,顺便作些小的改动就得到了n×n的算法了:

  1. #!/usr/bin/python
  2. # -*- coding: gb2312 -*-
  3. #Filename:first.py


  4. from numarray import *
  5. import numarray.strings as nastr
  6. from bin import bstr

  7. def light(n):
  8. PosSol=[reshape(nastr.array(bstr(x).zfill(n*n), itemsize=1),n,n).eval() for x in xrange(2**(n*n))]#PosSol:Possible Solutions
  9. tmpArray=zeros((n+2,n+2))
  10. for i in PosSol:
  11. tmpArray[1:n+1,1:n+1]=i.copy()
  12. Neg=False
  13. for x in range(n):
  14. if Neg:
  15. break
  16. for y in range(n):
  17. if Neg:
  18. break
  19. TxT=take(take(tmpArray, [x,x+1,x+2]),[y,y+1,y+2], axis=1)#TxT:Three X Three Square
  20. putmask(TxT, [1,0,1,0,0,0,1,0,1], [0])
  21. value=sum(sum(TxT))
  22. if not (value%2):#找到一个没有点亮就不用判断剩余的了
  23. Neg=True
  24. if not Neg:
  25. print i
  26. print "Total steps:%d" % sum(sum(i))

  27. tests = [2, 3, 4]
  28. for xx in tests
  29. print "solution for %d*%d" % (xx,xx)
  30. light(xx)

太晚了,趁还没下班先把东西收拾了,下班回家睡觉。:)

  • No ratings
  • No ratings
  • No ratings
  • No ratings
  • No ratings
  • 0 ratings

Leave a comment


Already have a login?