2016-03-03 45 views
0

提供一些上下文:我正在开发一个算法问题构建器,最终用户可以输入变量,为它们分配范围和规则,在公式中使用它们并实现(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 

是否有一个简单的递归函数可以比迭代函数更好地处理?

感谢您的帮助!

+2

为什么迭代解决方案不够? –

+1

定义:“更好” – Plutonix

+0

你想要的是范围的笛卡尔乘积。关于这个网站有很多问题。尝试http://stackoverflow.com/questions/4073713/is-there-a-good-linq-way-to-do-a-cartesian-product/4073806#4073806开始。 –

回答

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) 

n的所有值从Minimum生成为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)创建一个新字典。

+0

非常感谢你的这个@Enigmativity!有没有可能在迭代块中添加一些注释来解释发生了什么?再次欢呼! –

+0

@ daniel-schofield93 - 完成。 – Enigmativity