命令式至函式(六)
函式得到的,不只是命令式外的程式重函式外的程式,重在於 思考方式的重,而影演算法的。
下面程式是解 排 列合 的例子:
def rotated(list, i, j):
lt = list[i:j + 1]
return list[0:i] + lt[-1:] + lt[0:-1] + list[j + 1:]
def perm(list, i, colt):
if i < len(list):
for j in range(i, len(list)):
perm(rotated(list, i, j), i + 1, colt)
else:
colt.append(list)
colt = []
perm([1, 2, 3, 4], 0, colt)
for list in colt:
print(list)
形式上,函式是不用到圈的,那就改:
def rotated(list, i, j):
lt = list[i:j + 1]
return list[0:i] + lt[-1:] + lt[0:-1] + list[j + 1:]
def perm(list, i, colt):
def doFor(j):
if j < len(list):
perm(rotated(list, i, j), i + 1, colt)
doFor(j + 1)
if i < len(list):
doFor(i)
else:
colt.append(list)
colt = []
perm([1, 2, 3, 4], 0, colt)
for list in colt:
print(list)
在修改到有些,首先那doFor只是重,不知道怎命名取的名。按照目的,doFor函式其是可以取 rotateAndPermSub之的名,不暗示了函式同作了件事,使得很函式有回值的方式;如果想doFor放著不 管,那也很perm改有回值的方式,而只能使用colt收集排列果。
函式思考重就是分解子。到,那doFor函式其同理了件事,所以要分解的,一定是明目。doFor作的事 有,旋list後某段,然後得到的新串列尾端(tail)排列, 作至要旋的段到list尾端止,而且可以看到,perm呼叫了doFor,而doFor又呼叫了perm,都是,演算上於 了。
於是重新思考一下,doFor作的事有,旋list某段,然後得到的 新串列尾端(tail)排列...旋...排列...旋...排列...旋...排列...那如果先得到所有旋後的新串列, 再一次所有新串列尾端行理呢?於是先一allRotated:
def allRotated(list):
def rotatedTo(i):
return [list[i]] + list[0:i] + list[i + 1:]
return [rotatedTo(i) for i in range(len(list))]
allRotated任意list,它的旋段0始,一直旋至list尾端止。一旦出,那perm就了,只要呼叫自己就好 了:
def perm(list):
if list == []:
return [[]]
else:
lts = allRotated(list)
return reduce(lambda a, b: a + b,
[[[lt[0]] + pl for pl in perm(lt[1:])] for lt in lts])
跟一始的程式比可以,位置用的索引i都不用了,因每次都是旋後的串列尾端作排列嘛!Python中只要lt[1:]就可以了。修改 後的全部程式就是:
from functools import reduce
def allRotated(list):
def rotatedTo(i):
return [list[i]] + list[0:i] + list[i + 1:]
return [rotatedTo(i) for i in range(len(list))]
def perm(list):
if list == []:
return [[]]
else:
lts = allRotated(list)
return reduce(lambda a, b: a + b,
[[[lt[0]] + pl for pl in perm(lt[1:])] for lt in lts])
for list in perm([1, 2, 3, 4]):
print(list)
以函式思考重之後,就算回命令式,也是清楚多。例如:
def allRotated(list):
def rotatedTo(i):
rotated = []
rotated.append(list[i])
rotated.extend(list[0:i])
rotated.extend(list[i + 1:])
return rotated
all = []
for i in range(len(list)):
all.append(rotatedTo(i))
return all
def perm(list):
pls = []
if list == []:
pls.append([])
else:
for lt in allRotated(list):
for tailPl in perm(lt[1:]):
pl = []
pl.append(lt[0])
pl.extend(tailPl)
pls.append(pl)
return pls
for list in perm([1, 2, 3, 4]):
print(list)
一始命令式的程式比一下,是清楚多了。然用Python回作有聊,不於不若Python具有多函式相元素的程式言, 像是Java就很重要了,用Java一始看到的那演算,以及用Java最後程式,可以看出可性性相差甚多。