【发布时间】:2019-10-17 20:24:37
【问题描述】:
目标
给定一个二维数组A,我必须不断将每列第一行的值加 +1,直到列的总和等于相同的值,例如 28。
我的解决方案
这可能不是最好的解决方案,但考虑到我想提出的观点,它会做到的。这是一个简化的例子。在原始版本中,它基于概率分布是第一行还是第二行获得+1,并且在列之间有所不同。另外,它必须一个一个地完成,因为概率分布会因列的第一行或第二行在前一个周期中获得 +1 而发生变化。所以列的总和和迭代是必要的。
import numpy as np
A = np.arange(20).reshape(2, 10)
print(A)
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
while np.any(MASK):
LUCKYROW = np.repeat(0, np.count_nonzero(MASK))
A[LUCKYROW, MASK] += 1
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
print(A)
让我们看看输出:
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]]
[ True True True True True True True True True False]
[ True True True True True True True True True False]
[ True True True True True True True True False False]
[ True True True True True True True True False False]
[ True True True True True True True False False False]
[ True True True True True True True False False False]
[ True True True True True True False False False False]
[ True True True True True True False False False False]
[ True True True True True False False False False False]
[ True True True True True False False False False False]
[ True True True True False False False False False False]
[ True True True True False False False False False False]
[ True True True False False False False False False False]
[ True True True False False False False False False False]
[ True True False False False False False False False False]
[ True True False False False False False False False False]
[ True False False False False False False False False False]
[ True False False False False False False False False False]
[False False False False False False False False False False]
[[18 17 16 15 14 13 12 11 10 9]
[10 11 12 13 14 15 16 17 18 19]]
好吧,它可以工作,但为什么我要计算每个循环中每一列的总和?根据之前的周期,我知道哪一列的总和已经达到目标值。如果我利用这些信息,也许可以节省时间。
我的第二个解决方案
import numpy as np
A = np.arange(20).reshape(2, 10)
print(A)
MASK = A.sum(axis=0) < 28
print(A.sum(axis=0) < 28)
while np.any(MASK):
LUCKYROW = np.repeat(0, np.count_nonzero(MASK))
A[LUCKYROW, MASK] += 1
MASK[MASK] = A[:, MASK].sum(axis=0) < 28
print(A[:, MASK].sum(axis=0) < 28)
print(A)
还有输出:
[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]]
[ True True True True True True True True True False]
[ True True True True True True True True True]
[ True True True True True True True True]
[ True True True True True True True True]
[ True True True True True True True]
[ True True True True True True True]
[ True True True True True True]
[ True True True True True True]
[ True True True True True]
[ True True True True True]
[ True True True True]
[ True True True True]
[ True True True]
[ True True True]
[ True True]
[ True True]
[ True]
[ True]
[]
[[18 17 16 15 14 13 12 11 10 9]
[10 11 12 13 14 15 16 17 18 19]]
它似乎工作。虽然出现了一个问题。它不比第一个解决方案快。我尝试使用 25000 列和 74998 作为目标值,但它们在时间上大致相等。
我的请求
我想我可能对 ndarray 操作或 ndarray 索引有一个基本的误解。第二种解决方案应该在每个循环中进行越来越少的计算,因此我预计性能会显着提高。我找不到解释。我的思路哪里出错了?
【问题讨论】:
-
应用蒙版与求和一样昂贵。我们必须做更详细的计时,但我的猜测是总和是一个小步骤,对总和的长度不敏感。
标签: python python-3.x performance numpy numpy-ndarray