每个数字组合的递归函数

时间:2016-03-03 01:56:48

标签: c# recursion formula equation

提供一些上下文:我正在开发一个算法问题构建器,最终用户可以输入变量,为它们分配范围和规则,在公式中使用它们并实现(x)大量的问题。

我目前需要使用变量名[a],[b],[c]等等的键来填充x个元素的x个字典,每个值都是唯一的,每个它们可能存在的范围的可能性;即a = 1 - 100,b = 1 - 50等等。

So 1st dict would be:
[a] = 1
[b] = 1
[c] = 1

2nd dict
[a] = 2
[b] = 1
[c] = 1

是否有一个简单的递归函数可以比迭代函数更好地处理它?<​​/ p>

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

如果我从可以表示您的值范围的结构开始,如下所示:

public struct Range
{
    public int Minimum { get; set; }
    public int Maximum { get; set; }
}

...然后我可以代表你的输入:

var inputs = new Dictionary<string, Range>()
{
    { "a", new Range() { Minimum = 1, Maximum = 3 } },
    { "b", new Range() { Minimum = 1, Maximum = 2 } },
    { "c", new Range() { Minimum = 1, Maximum = 2 } },
};

...然后我可以像这样构建结果:

Func<IEnumerable<KeyValuePair<string, Range>>, IEnumerable<Dictionary<string, int>>> build = null;
build =
    kvps =>
    {
        if (kvps.Skip(1).Any())
        {
            return
                from kvp in kvps.Take(1)
                from n in Enumerable.Range(kvp.Value.Minimum, kvp.Value.Maximum - kvp.Value.Minimum + 1)
                from r in build(kvps.Skip(1))
                select new[] { new KeyValuePair<string, int>(kvp.Key, n) }.Concat(r).ToDictionary(x => x.Key, x => x.Value);
        }
        else
        {
            return
                from kvp in kvps
                from n in Enumerable.Range(kvp.Value.Minimum, kvp.Value.Maximum - kvp.Value.Minimum + 1)
                select new[] { new KeyValuePair<string, int>(kvp.Key, n) }.ToDictionary(x => x.Key, x => x.Value);
        }
    };

这会产生以下词典列表:

a=1, b=1, c=1 
a=1, b=1, c=2 
a=1, b=2, c=1 
a=1, b=2, c=2 
a=2, b=1, c=1 
a=2, b=1, c=2 
a=2, b=2, c=1 
a=2, b=2, c=2 
a=3, b=1, c=1 
a=3, b=1, c=2 
a=3, b=2, c=1 
a=3, b=2, c=2 

以下是主要查询的解释:

from kvp in kvps.Take(1)

kvps枚举中获取第一个元素(这是可枚举的“头部”)

from n in Enumerable.Range(kvp.Value.Minimum, kvp.Value.Maximum - kvp.Value.Minimum + 1)

nMinimum生成Maximum的所有值。

from r in build(kvps.Skip(1))

递归调用列表“尾部”上的build以生成所有可能的尾部词典

select new[] { new KeyValuePair<string, int>(kvp.Key, n) }.Concat(r).ToDictionary(x => x.Key, x => x.Value);

使用KeyValuePair<string, int>[]和值Key创建一个新n,并在创建新词典时连接尾部(r)中的每个值。