我的脚本执行以下操作:我有一个带拼字游戏的文本文件及其“值”:
BYZZZZĄ -8.038175
BYZZZĄŹ -14.072675
BYZZZĄŻ -1.238175
BYZZĄŹŻ -3.588175
BZZZZZĄ -13.938175
BZZZZĄŹ -9.738175
BZZZZĄŻ -10.538175
BZZZĄŹŻ -19.072675
CCCDDĄĆ -16.088175
CCCDEĄĆ -4.288175
CCCDĄĆĘ -5.588175
CCCDFĄĆ -16.788175
CCCDGĄĆ -10.338175
现在我想生成一个部分机架列表及其值。部分机架的值是可以使用它创建的所有可能完整机架的加权总和。因此,对于一个6个字母的机架CCCDDA
,它将是(CCCDDAA*8+CCCDDAB*2+CCCDDAD*1+CCCDDAE*7)/N
,其中N是所有机架的编号。乘数等于包中剩余的字母数,例如总共有9个A,但CCCDDA
中已有一个,所以我们只乘以8。
字母分布如下(第四栏):
A a 1 9 1
Ą ą 5 1 1
B b 3 2 0
C c 2 3 0
Ć ć 6 1 0
D d 2 3 0
E e 1 7 1
Ę ę 5 1 1
F f 5 1 0
G g 3 2 0
H h 3 2 0
I i 1 8 1
J j 3 2 0
K k 2 3 0
L l 2 3 0
Ł ł 3 2 0
M m 2 3 0
N n 1 5 0
Ń ń 7 1 0
O o 1 6 1
Ó ó 5 1 1
P p 2 3 0
R r 1 4 0
S s 1 4 0
Ś ś 5 1 0
T t 2 3 0
U u 3 2 1
W w 1 4 0
Y y 2 4 1
Z z 1 5 0
Ź ź 9 1 0
Ż ż 5 1 0
blank 0 2
有11M个可能的机架,因此计算所有部分值非常耗时。这是我目前的方法(也可在github上获得):
#-*- coding: utf-8 -*-
import io
import itertools
import time
def loadAlphabet(filename):
fil = io.open(filename, encoding="utf-8")
lines = fil.readlines()
letters = {}
for line in lines:
line = line.split()
if line[0] == 'blank':
letters[u'?'] = int(line[2])
else:
letters[u'%s' % line[0]] = int(line[3])
fil.close()
return letters
def adjustBag(rack, bag):
newBag = bag.copy()
for letter in rack:
newBag[letter] -= 1
return newBag
def partialValue(rackLen):
bag = loadAlphabet("../data/alphabets/polish.quackle_alphabet")
racks = io.open("racks%d.txt" % rackLen, encoding='utf-8').read().splitlines()
leaveList = io.open("leavesSorted.txt", encoding='utf-8').read().splitlines()
leaves = {}
# create a dictionary of leave:value
for line in leaveList:
(lv, val) = line.split()
leaves[lv] = float(val)
outFile = io.open("rack%doutput.txt" % rackLen, 'w', encoding='utf-8')
for r in racks:
smallerBag = adjustBag(r, bag)
bagList = []
for letter in smallerBag:
bagList += smallerBag[letter]*letter
combs= itertools.combinations(bagList, 7-rackLen)
combSet = set(combs)
sumVals = 0.0
i = 0.0
avgVal = 0.0
for elem in combSet:
multiplier = 1.0
for letter in elem:
multiplier *= smallerBag[letter]
fullrack = u''.join(sorted(r + u''.join(elem)))
sumVals += leaves[fullrack]*multiplier
i+= multiplier
avgVal = sumVals / i
outFile.write(u'%s %f\n' % (r, avgVal))
partialValue(5)
我已经通过迭代整个itertools.combinations
生成器(old code)到从生成器创建一个集合然后计算乘数来加速它。我也可以通过仅使用唯一组合创建一个生成器来改进它(所以我可以跳过set()生成),但我没有找到内置函数。
如何在速度方面优化代码?(欢迎提供其他提示)