C# 如何建立一个算法来找到一个组合,其总和最接近一个数字,其差值在c中的范围内#

C# 如何建立一个算法来找到一个组合,其总和最接近一个数字,其差值在c中的范围内#,c#,algorithm,sequence,C#,Algorithm,Sequence,我有一个随机值列表,如下所示 319, 4. 90, 50, 20, 99, 500, 95, 九百 我必须找到一个和在选定范围内的值,比如说5%到10% 例如,如果数字是300 范围是5%到10% 那么差值应该在15到30之间 那么满足这个条件的列表是 319=>319-300=-19,最接近300,差值在5%到10%之间 319,4=>319+4=323=>323-300=-23,最接近300,差值在5%到10%之间 90,99,97=>90+99+95=284=>284-300=16,最接

我有一个随机值列表,如下所示

319, 4. 90, 50, 20, 99, 500, 95, 九百

我必须找到一个和在选定范围内的值,比如说5%到10%

例如,如果数字是300 范围是5%到10%

那么差值应该在15到30之间

那么满足这个条件的列表是

319=>319-300=-19,最接近300,差值在5%到10%之间 319,4=>319+4=323=>323-300=-23,最接近300,差值在5%到10%之间 90,99,97=>90+99+95=284=>284-300=16,最接近300,差值在5%到10%之间

结果将是
319,
319,4
90,99,95

我尝试过修改递归算法 () 但它只能返回很少的匹配序列,而不是全部

代码:

public static IEnumerable GetSequence(十进制[]集,十进制总和,十进制起始百分比,十进制结束百分比,字符串值=”)
{            
for(int i=0;i=startPercent&&Math.Abs(decimal.Parse(left.ToString()))n 0)
{
foreach(GetSequence中的字符串s(可能、左侧、startPercent、endPercent、VAL))
{
收益率;
}
}
}
}
}

有人能帮我吗。

可能更好的方法是使用如下代码生成所有可能的组合:

public static IEnumerable<IEnumerable<T>> Combinations<T>(IList<T> items)
{
    return Combinations(items.Count).Select(comb => comb.Select(index => items[index]));
}

public static IEnumerable<IEnumerable<int>> Combinations(int n)
{
    long m = 1 << n;

    for (long i = 1; i < m; ++i)
        yield return bitIndices((uint)i);
}

static IEnumerable<int> bitIndices(uint n)
{
    uint mask = 1;

    for (int bit = 0; bit < 32; ++bit, mask <<= 1)
        if ((n & mask) != 0)
            yield return bit;
}
这是您的预期输出


注意:上面的代码使用的是C#7元组-如果您使用的是早期版本,则必须将
FindMatches()
SummedCombinations()
更改为:

static IEnumerable<List<int>> FindMatches(IList<int> values, int target, int toleranceLow, int toleranceHigh)
{
    int minDiff = (target * toleranceLow)  / 100;
    int maxDiff = (target * toleranceHigh) / 100;

    foreach (var sum in SummedCombinations(values))
    {
        int diff = Math.Abs(sum.Item1 - target);

        if (minDiff <= diff && diff <= maxDiff)
            yield return sum.Item2;
    }
}

static IEnumerable<Tuple<int, List<int>>> SummedCombinations(IList<int> values)
{
    return 
        Combinations(values)
        .Select(comb => comb.ToList())
        .Select(comb => Tuple.Create(comb.Sum(), comb));
}

请向我们显示您现有的代码。我还发现您表达
结果的方式很混乱。我在前面提到的随机值是我将传递给set的十进制数组,第二个参数sum是精确值,如示例319中所示,将通过该参数传递,起始百分比和结束百分比表示范围
286-300=16
Er,不,它不是。因此,这不应该是您期望的结果之一。但是,
4,50,20,99,97
加起来是270,这给出了30的差值,因此这应该是输出之一。在每次迭代中,将每个值彼此相加,并检查319和相加值之间的差值是否在范围内,如果条件满足,则返回列表,28~300是典型错误,请将其视为284,那么差异将满足条件16。我会试试这个,让你知道
static IEnumerable<(int Sum, List<int> Values)> SummedCombinations(IList<int> values)
{
    return 
        Combinations(values)
        .Select(comb => comb.ToList())
        .Select(comb => (comb.Sum(), comb));
}
static IEnumerable<List<int>> FindMatches(IList<int> values, int target, int toleranceLow, int toleranceHigh)
{
    int minDiff = (target * toleranceLow)  / 100;
    int maxDiff = (target * toleranceHigh) / 100;

    foreach (var sum in SummedCombinations(values))
    {
        int diff = Math.Abs(sum.Sum - target);

        if (minDiff <= diff && diff <= maxDiff)
            yield return sum.Values;
    }
}
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            int[] values = {319, 4, 90, 50, 20, 99, 500, 95, 900};

            foreach (var combination in FindMatches(values, 300, 5, 10))
            {
                Console.WriteLine(string.Join(", ", combination));
            }
        }

        static IEnumerable<List<int>> FindMatches(IList<int> values, int target, int toleranceLow, int toleranceHigh)
        {
            int minDiff = (target * toleranceLow)  / 100;
            int maxDiff = (target * toleranceHigh) / 100;

            foreach (var sum in SummedCombinations(values))
            {
                int diff = Math.Abs(sum.Sum - target);

                if (minDiff <= diff && diff <= maxDiff)
                    yield return sum.Values;
            }
        }

        static IEnumerable<(int Sum, List<int> Values)> SummedCombinations(IList<int> values)
        {
            return 
                Combinations(values)
                .Select(comb => comb.ToList())
                .Select(comb => (comb.Sum(), comb));
        }

        public static IEnumerable<IEnumerable<T>> Combinations<T>(IList<T> items)
        {
            return Combinations(items.Count).Select(comb => comb.Select(index => items[index]));
        }

        public static IEnumerable<IEnumerable<int>> Combinations(int n)
        {
            long m = 1 << n;

            for (long i = 1; i < m; ++i)
                yield return bitIndices((uint)i);
        }

        static IEnumerable<int> bitIndices(uint n)
        {
            uint mask = 1;

            for (int bit = 0; bit < 32; ++bit, mask <<= 1)
                if ((n & mask) != 0)
                    yield return bit;
        }
    }
}
319
319, 4
90, 99, 95
static IEnumerable<List<int>> FindMatches(IList<int> values, int target, int toleranceLow, int toleranceHigh)
{
    int minDiff = (target * toleranceLow)  / 100;
    int maxDiff = (target * toleranceHigh) / 100;

    foreach (var sum in SummedCombinations(values))
    {
        int diff = Math.Abs(sum.Item1 - target);

        if (minDiff <= diff && diff <= maxDiff)
            yield return sum.Item2;
    }
}

static IEnumerable<Tuple<int, List<int>>> SummedCombinations(IList<int> values)
{
    return 
        Combinations(values)
        .Select(comb => comb.ToList())
        .Select(comb => Tuple.Create(comb.Sum(), comb));
}
C B A (Input)
2 1 0 (Bit number, i.e. power of two)
---------------------------------------
0 0 1 [1] = A
0 1 0 [2] = B
0 1 1 [3] = A B
1 0 0 [4] = C
1 0 1 [5] = A C
1 1 0 [5] = B C
1 1 1 [6] = A B C