我有一个数组值,我需要获得所有可能的组合。哪个使用 itertools.product 很容易。
EG。苹果可能是elppa,appel,lppae等。
然而,警告是双重的。
我需要将这个单词的所有组合与重复30次的字母组合在一起。 例如。 aaaaaaaaaaaaaaaaaaaaaaaaa apple , apple aaaaaaaaaaaaaaaaaaaa apple
显然我们在这里使用一个巨大的数据源,所以当我运行例如6-10次重复测试时,它是合理的快速(即一分钟之内)。当在夜间运行测试到30的幂时,它表明测试将需要数天才能完成。
我玩Numpy,这在StackOverflow上通常被建议使用更快/更轻的方法。但是我已经解决了这个问题,因为我发现的所有变化导致脚本杀死我的机器并使用磁盘空间,而速度慢(对于此测试来说太慢),但效率更高 itertools.product < / strong>即可。
此外,我不明白如何将所有这些数据拉入numty数组,然后计算以下内容,而不会产生系统开销。
最终
练习的重点是计算每行结果中 apple 一词的出现次数。但只有当它连续出现时。 这算得上:aaaaaaaaaaaaaaaaaaaaaaaaa apple 这不会:苹果 aaaaaaaaaaaaaaaaaaaa apple
以下代码在机器上没有太大的压力,但运行速度太慢。
由于
import itertools
import time
import numpy as np
apple = ['a','p','l','e']
occurences = 0
line = 0
arr_len = len(apple)
length = 30
squared = arr_len**length
start_time = time.time()
for string in itertools.imap(''.join, itertools.product(apple, repeat=length)):
line += 1
if (string.count('apple')==1):
occurences += 1
if occurences % 100000 == 0:
print occurences, ("--- %s seconds ---" % (time.time() - start_time)),squared, line
print ('Occurences : ',occurences)
print ('Last line no. ',line)
print ("--- %s seconds ---" % (time.time() - start_time))
答案 0 :(得分:1)
您尝试解决问题的方式本质上是指数级的。您需要使用动态编程。这个问题有一个多项式时间解决方案。如果您的单词中包含n个字符,则可以使用具有2n个状态的马尔可夫链。
import numpy as np
word = 'papal'
length = 10
word_chars = list(set(word))
n = len(word)
m = len(word_chars)
states = [0] * (2*n)
states[0] = 1
jumps = np.zeros((n, m), dtype=np.int)
for i in range(n):
for j in range(m):
# We've seen the first i characters of word, and we see character word_chars[j]
if word[i] == word_chars[j]:
value = i+1
else:
for k in range(i+1):
if word[k: i] + word_chars[j] == word[:i - k + 1]:
value = i - k + 1
break
else:
value = 0
jumps[i, j] = value
for i in range(length):
new_states = [0] * (2*n)
for j in range(n):
for jump in jumps[j]:
new_states[jump] += states[j]
if n+jump < 2*n:
new_states[n+jump] += states[n+j]
states = new_states
print(np.sum(states[n:]))
如果这个词是&#34; papa&#34;那么&#34; papapa&#34;匹配与否?如果没有,您应该删除马尔可夫链中的状态。
答案 1 :(得分:1)
稍微考虑一下,我们可以应用一些基本概率的计数技术来计算最多只出现一个单词的序列数。但是,动态编程解决方案可能更容易实现,并且对于小的序列大小可能运行得更快 - 下面的解决方案在序列长度上具有线性时间复杂度,但是没有针对速度进行优化,我只是发布了它在这里作为参考:
from scipy.misc import comb
def k(i, t, w):
"""Compute the number of occurrences.
Arguments
---------
i : int
The number of products.
w : int
Length of the word.
t : int
The number of characters in the alphabet.
"""
# consider all i - w + 1 ways of placing the word into `i` slots,
# and subtract the number of sequences with multiple occurrences (n_x, n_y)
r = i - w
tot = 0
for x in range(r + 1):
y = r - x
n_y = 0 if y < w else (y - w + 1) * t**(y - w)
n_x = 0 if x < w else (x - w + 1) * t**(x - w)
s = t**x * n_y + t**y * n_x
tot += t**r - s
# for i >= 15 we must compute a correction, because we are "double
# counting" some sequences with multiple occurrences. The correction
# turns out to be an alternating sequence of binomial coefficients
cor = 0
for c_k in range(2, i // w):
c_n = (c_k + 1) + i - w * (c_k + 1)
cor += (-1)**c_k * int(comb(c_n, c_k)) * n(i - w * c_k)
return tot + cor
这样
>>> for i in range(31): print(i, k(i, 4, 5))
0 0
1 0
2 0
3 0
4 0
5 1
6 8
7 48
8 256
9 1280
10 6142
11 28648
12 130880
13 588544
14 2613760
15 11491331
16 50102320
17 216924640
18 933629696
19 3997722880
20 17041629180
21 72361164720
22 306190089280
23 1291609627904
24 5433306572800
25 22798585569285
26 95447339991160
27 398767643035280
28 1662849072252416
29 6921972555609600
30 28768047528652794