第一天
对于这样的问题,我们最直接的想法就是穷举法:把所有的组合都试一次,有此来找到所有可能的解。
那么我们怎么的到这所有的组合呢?让我们来回想一下前面理论分析的内容。所有灯的状态都用0和1来表示,如果我们把这个4×4的二维数组组合成一个0、1序列,那么我们这个得到的0、1序列的是[0, 2^16)中所有的整数.我们用如下的语句得到这个整数序列:
- [x for x in xrange(2**16)]#由于数量比较大,我们没有使用range。两者之间的额区别google一下就可以了。
现在我们把这些整数变成二进制!由于python里面没有直接的函数可以转换,所有我们要自己完成:
- bstr = lambda n, l=16: n<0 and binarystr((2L<>1).lstrip('0')+str(n&1) or '0'
>>>bstr(5)
‘101′
注意一下返回的是一个字符串(这个是肯定的,想想就知道了)。zfill可以补齐我们需要的位数。那么生成序列的语句就出来了:
- [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, 看来我们需要的东西基本已经齐全了,我们现在先把得到的东西都组合一下。得到下面的代码:
- from numarray import *
- import numarray.strings as nastr
- 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,那么我们这么写:
- tmpArray=zeros((6,6))
- tmpArray[1:5,1:5]=PosSol.copy()
然后把我们需要的3×3的“抠出来”:
- TxT=take(take(tmpArray, [x,x+1,x+2]),[y,y+1,y+2], axis=1)#TxT:Three X Three Square
好了,现在我们只要去掉四个角的数,然后求和判断是不是奇数就知道灯泡是不是点亮了:
- putmask(TxT,[1,0,1,0,0,0,1,0,1],0)
- value=sum(sum(finalSquare),1)
现在我们全部汇总就得到了游戏的解法,顺便作些小的改动就得到了n×n的算法了:
- #!/usr/bin/python
- # -*- coding: gb2312 -*-
- #Filename:first.py
-
-
- from numarray import *
- import numarray.strings as nastr
- from bin import bstr
-
- def light(n):
- PosSol=[reshape(nastr.array(bstr(x).zfill(n*n), itemsize=1),n,n).eval() for x in xrange(2**(n*n))]#PosSol:Possible Solutions
- tmpArray=zeros((n+2,n+2))
- for i in PosSol:
- tmpArray[1:n+1,1:n+1]=i.copy()
- Neg=False
- for x in range(n):
- if Neg:
- break
- for y in range(n):
- if Neg:
- break
- TxT=take(take(tmpArray, [x,x+1,x+2]),[y,y+1,y+2], axis=1)#TxT:Three X Three Square
- putmask(TxT, [1,0,1,0,0,0,1,0,1], [0])
- value=sum(sum(TxT))
- if not (value%2):#找到一个没有点亮就不用判断剩余的了
- Neg=True
- if not Neg:
- print i
- print "Total steps:%d" % sum(sum(i))
-
- tests = [2, 3, 4]
- for xx in tests
- print "solution for %d*%d" % (xx,xx)
- light(xx)
太晚了,趁还没下班先把东西收拾了,下班回家睡觉。:)

Leave a comment