Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计算第n置换步?_C#_Math_List_Indexing - Fatal编程技术网

C# 计算第n置换步?

C# 计算第n置换步?,c#,math,list,indexing,C#,Math,List,Indexing,我有一个字母a-z的字符[26],为语句嵌套了via,我正在生成一个序列列表,如: aaa, aaz... aba, abb, abz, ... zzy, zzz. 目前,编写该软件是为了从aaa zzz生成所有可能值的列表,然后维护一个索引,并对每个值执行操作 这个列表显然很大,并没有大到可笑的程度,但它已经达到了内存占用太大的程度(还有其他一些方面正在研究,但这是我得到的) 我试图生成一个公式,在这个公式中,我可以保留索引,但不需要序列列表,而是根据当前索引计算当前序列(因为序列之间的操作

我有一个字母a-z的字符[26],为语句嵌套了via,我正在生成一个序列列表,如:

aaa, aaz... aba, abb, abz, ... zzy, zzz.
目前,编写该软件是为了从aaa zzz生成所有可能值的列表,然后维护一个索引,并对每个值执行操作

这个列表显然很大,并没有大到可笑的程度,但它已经达到了内存占用太大的程度(还有其他一些方面正在研究,但这是我得到的)

我试图生成一个公式,在这个公式中,我可以保留索引,但不需要序列列表,而是根据当前索引计算当前序列(因为序列之间的操作间隔时间很长)

例如:

我试着用一个子集(abc)做一个小例子,并试着用模除法把它编入索引,但我今天思考起来有困难,我被难倒了


我不是在寻求答案,只是寻求任何帮助。也许是朝着正确的方向踢了一脚?

提示:想想如何用26进制而不是10进制打印数字,用字母而不是数字。以任意基数显示数字的通用算法是什么

扰流板:(向右滚动查看)


假设有26个字符,这样的东西应该会起作用:

public string CurrentSequence(int currentIndex) {
    return characters[currentIndex / (26 * 26)] 
        + characters[(currentIndex / 26) % 26]
        + characters[currentIndex % 26];
}
哇,这可以通过笛卡尔积来解决。太棒了。

可以使用生成索引值的所有组合。这种方法产生一组流式的值,因此它们不需要存储在内存中。这种方法很好地将生成代码的逻辑与维护状态或使用代码执行计算分离开来

Eric针对所有组合的代码:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)  
{  
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };  
  return sequences.Aggregate(  
    emptyProduct,  
    (accumulator, sequence) =>   
      from accseq in accumulator   
      from item in sequence   
      select accseq.Concat(new[] {item}));                 
} 

有多种方法可以解决您的问题,但一种选择是动态生成序列,而不是将其存储在列表中:

IEnumerable<String> Sequence() {
  for (var c1 = 'a'; c1 <= 'z'; ++c1)
    for (var c2 = 'a'; c2 <= 'z'; ++c2)
      for (var c3 = 'a'; c3 <= 'z'; ++c3)
        yield return String.Format("{0}{1}{2}", c1, c2, c3);
}

此代码根本不使用索引,但它允许您使用简单代码围绕字符串序列创建循环,而不存储字符串。

char[25]不足以保存a..z。您可能想检查缓冲区溢出或其他情况。您到底想实现什么?看起来您想计算置换序列的单个特定步骤,而不是索引整个置换结果?我知道答案已被接受,但这是一个很好的问题,有一组聪明的答案。我将把它留给作者,但我建议一个更好的标题,比如:“如何计算第n个排列步骤?”“索引到不存在的集合”并不能真正传达问题所在,我同意。改变。顺便说一句,我确实使用了@LBushkin和@Martin livesage提供的思想的变体来解决与此非常相关的问题。这种解决方案不允许您高效地查找索引,这是一个用例。@recursive。也许。除此之外,OP确实表明该软件在所有索引中都能正常工作。所以这可能仍然有用。递归是正确的,但它确实非常有用。我看过埃里克关于这件事的帖子,但我忘了+1我不会说查找索引就是用例。当OPs试图解决内存中的大列表问题时,我读到了它,我认为使用惰性枚举器是一个更好的解决方案,因为问题中定义了这样的需求。
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)  
{  
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };  
  return sequences.Aggregate(  
    emptyProduct,  
    (accumulator, sequence) =>   
      from accseq in accumulator   
      from item in sequence   
      select accseq.Concat(new[] {item}));                 
} 
public static IEnumerable<string> AllCodes()
{
  char[] characters = {a, b, c... z}; 
  IEnumerable<char[]> codeSets = new[] { characters, characters, characters };

  foreach( var codeValues in codeSets.CartesianProduct() )
  {
    yield return 
       string.Format( "{0}{1}{2}", codeValues[0], codeValues[1], codeValues[2]);
  }
}
foreach( var code in AllCodes() )
{
    // use the code value somehow...
}
IEnumerable<String> Sequence() {
  for (var c1 = 'a'; c1 <= 'z'; ++c1)
    for (var c2 = 'a'; c2 <= 'z'; ++c2)
      for (var c3 = 'a'; c3 <= 'z'; ++c3)
        yield return String.Format("{0}{1}{2}", c1, c2, c3);
}
foreach (var s in Sequence())
  Console.WriteLine(s);