c# - 在没有递归函数的 C# 中计算组合
问题描述
我想计算所有可能的组合,但我不想在 C# 中使用递归函数只是一些简单的代码?
这是示例:
col1 col2 col3
valueinf= 5 6 7
valuesup= 10 20 30
我想要这个结果:
res1 = 5+6+7
res2 = 5+6+30
res3 = 5+20+7
res4 = 5+20+30
res5 = 10+6+7
res6 = 10+6+30
res7 = 10+20+7
res8 = 10+20+30
Colonne 的数量是可变的,但我总是有 2 条线,一条下线,一条上线。我不知道如何开始算法。一些帮助将不胜感激刚刚开始
解决方案
好吧,你必须循环:
using System.Linq;
...
private static IEnumerable<int> Sums(IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
do {
yield return Enumerable.Range(0, data.Length).Sum(i => data[i][pos[i]]);
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
}
如果你想打印公式,同样的想法:
private static IEnumerable<string> Formulae(IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
do {
yield return string.Join("+", Enumerable
.Range(0, data.Length).Select(i => data[i][pos[i]]));
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
}
演示:
List<int[]> columns = new List<int[]>() {
new int[] {5, 10},
new int[] {6, 20},
new int[] {7, 30},
};
var sums = Sums(columns);
var formulae = Formulae(columns);
Console.WriteLine(string.Join(Environment.NewLine, sums
.Select((v, i) => $"res{i+1} = {v}")));
Console.WriteLine();
Console.WriteLine(string.Join(Environment.NewLine, formulae
.Select((v, i) => $"res{i+1} = {v}")));
结果:
res1 = 18
res2 = 41
res3 = 32
res4 = 55
res5 = 23
res6 = 46
res7 = 37
res8 = 60
res1 = 5+6+7
res2 = 5+6+30
res3 = 5+20+7
res4 = 5+20+30
res5 = 10+6+7
res6 = 10+6+30
res7 = 10+20+7
res8 = 10+20+30
编辑:要找到最合适的,您可以利用相同的原则:
private static (int[] pos, int diff, string formula) BestFit(int target, IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
int bestDiff = -1;
int[] bestPos = null;
do {
int diff = Math.Abs(target - Enumerable.Range(0, data.Length).Sum(i => data[i][pos[i]]));
if (diff < bestDiff || bestPos == null) {
bestPos = pos.ToArray();
bestDiff = diff;
}
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
return (
bestPos,
bestDiff,
string.Join("+", Enumerable.Range(0, data.Length).Select(i => data[i][bestPos[i]]))
);
}
演示:
int[][] data = new int[][] {
new int[] {5, 10},
new int[] {6, 20},
new int[] {7, 30},
};
var fit = BestFit(20, data);
Console.Write($"delta = {fit.diff}; formula = {fit.formula}");
结果:
delta = 2; formula = 5+6+7
推荐阅读
- twilio - Twilio 录制视频
- c++ - pqxx::nontransaction 似乎开始了一个事务
- tensorflow - 在 Tensorflow Federated 中测量执行时间的推荐方法
- reactjs - 在“if”语句中不会调用模拟函数 - 用玩笑和酶反应应用程序测试?
- office-js - Office.EventType.ItemChanged 未触发
- flutter - 为什么颤振工具提示不起作用
- spring-boot - 单元测试中的 EntityManager - 春季启动
- python - 跨平台编程中的换行符
- python - 当我调用这个对象时,哪个方法直接返回一个类的元素?
- c# - 如何检查 PowerPoint 中是否打开了对话框?