【发布时间】:2021-12-18 06:56:01
【问题描述】:
我的“任务”的第一部分是找到一个数字(在我的例子中是 365)的所有加数 (partition) 以及这些序列的所有可能排列。
例如:对于数字 3,我们有三个可能的加数序列 (3) (1;2) (1;1;1) 但我的方法给出 (3) (1;2) (2;1) (1; 1;1) 根据我的需要。
IEnumerable<int[]> SplitAddends(int n) {
for (int i = 1; i < n; i++) {
var part = SplitAddends(n - i);
foreach (var array in part) {
var newArray = new int[array.Length + 1];
newArray[0] = i;
Array.Copy(array, 0, newArray, 1, array.Length);
yield return newArray;
}
}
yield return new []{n};
}
此方法在不到 1 毫秒的时间内给出结果,并且是正确的。问题是这项任务的第二部分。我需要对每个元素进行一些计算。 例如:
void ExampleMethod(int N) {
var partition = SplitAddends(N); // < 1ms execution time
foreach (var variant in partition) { // problematic line
var someResult = 0f;
foreach (var item in variant) {
someResult += SomeEquation(item);
}
SendToCompare(someResult);
}
}
对于像 15-25 这样的数字需要几秒钟(对于 N=20 分区有 524288 个序列),对于像 35-50 这样的数字需要几个小时。
我已经尝试过Parallel.ForEach、while(partition.MoveNext()) 和更改集合类型。即使partition.Count() 也需要数年才能执行。
我知道一种解决方法。计算可能会放在SplitAppends 方法中并在堆栈的顶层执行,但这种方式似乎很棘手。
【问题讨论】:
-
我们无法优化故事,顺便说一句,我们不会阅读数论 wiki 并为您编写算法(大部分情况下)。如果您真的对答案感兴趣,您需要minimal reproducible example。但是,除非您对一组特定的优化有特别的担忧,否则您最好将其提交给 CodeReview。再一次,您需要minimal reproducible example
-
其次,您需要确信您的实际算法是最有效的解决方案。也许你可以试试 MathOverflow
-
@TheGeneral 我的朋友。特别是对你 dotnetfiddle.net/ukdcYF 。这是我帖子中的代码(没有额外的行)。长话短说 - 阅读标题。您无需了解/阅读数学即可回答该问题。是的,我绝对确定这(图灵机)是解决我的整个问题的唯一方法。我可以解释为创造者,但没有必要。
-
对于那些想尝试实际问题的人。您有周期化合物的 APY 公式。现在建议您可以随时(每秒)进行复合,但每种复合的价格都是固定的。您知道您的 TVL 值、每日利润 (%) 和费用价格。计算几年的最佳复合方案。
标签: c# .net performance optimization collections