次のような文字列をスクランブリングして、可能なすべての順列を実現するにはどうすればよいでしょうか。そのような取り組みのためのLINQメソッドはありますか?Googleを検索しましたが、何も見つかりませんでした。
STRING = "Little Red Riding Hood"
次のような文字列をスクランブリングして、可能なすべての順列を実現するにはどうすればよいでしょうか。そのような取り組みのためのLINQメソッドはありますか?Googleを検索しましたが、何も見つかりませんでした。
STRING = "Little Red Riding Hood"
これは、私が過去に使用した優れた順列ライブラリです。この記事には、あなたのニーズによく合うと私が信じているコードスニペットが含まれています(私は少し適応させました):
var inputSet = myString.ToCharArray();
var P2 = new Permutations<char>(inputSet,
GenerateOption.WithRepetition);
string format2 = "Permutations of {{A A C}} with Repetition; size = {0}";
Console.WriteLine(String.Format(format2, P2.Count));
foreach(IList<char> p in P2) {
Console.WriteLine(String.Format("{{{0} {1} {2}}}", p[0], p[1], p[2]));
}
C ++標準テンプレートライブラリ(STL)にはメソッドがありますが、C#から(巧妙な方法で)アクセスできないと思います。STL用の小さなC++ラッパーを作成し、それをC#から呼び出す必要があると思います。または、C#で順列をコーディングします。
アップデート:
N項目のすべての順列を生成することは、巡回セールスマン問題(TSP)の必要な前置きです。このためのアルゴリズムはWeb全体にあり、アンパッサンで可能なさまざまな順次および並列アルゴリズムで順列を生成する方法を説明します。
文字列の文字を使用してKnuth/Fisher-Yatesシャッフルを実行します。
配列の代わりに文字列に適応できる一連のC#実装を次に示します。RandomとOrderByを使用することは、優れたシャッフルアルゴリズムですか?
完全なサンプル プログラムは次のとおりです。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
internal class Program
{
private static void Main(string[] args)
{
var sentences = new List<string>
{
"Little Red Riding Hood",
"Three Little Pigs",
"Jack and the Beanstalk"
};
foreach (var sentence in sentences)
{
Console.WriteLine("----------------------------------");
foreach (var permutation in Permute(sentence.Split(' ')))
{
foreach (string word in permutation)
{
Console.Write(word + " ");
}
Console.WriteLine();
}
}
// If you want to put all the permutations for all the sentences into a List<string>, you can just do this:
List<string> permutations = new List<string>();
foreach (var sentence in sentences)
{
permutations.AddRange(Permute(sentence.Split(' ')).Select(perm => string.Join(" ", perm)));
}
Console.WriteLine("The total number of perms is: " + permutations.Count);
}
/// <summary>
/// Provides a sequence of enumerators for obtaining all permutations of a sequence.
/// Each enumeration in the returned sequence itself enumerates one of the permutations of the input sequence.
/// Use two nested foreach statements to visit each item in each permuted sequence.
/// </summary>
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> sequence)
{
return permute(sequence, sequence.Count());
}
// Returns an enumeration of enumerators, one for each permutation of the input.
private static IEnumerable<IEnumerable<T>> permute<T>(IEnumerable<T> sequence, int count)
{
if (count == 0)
{
yield return new T[0];
}
else
{
int startingElementIndex = 0;
foreach (T startingElement in sequence)
{
IEnumerable<T> remainingItems = allExcept(sequence, startingElementIndex);
foreach (IEnumerable<T> permutationOfRemainder in permute(remainingItems, count - 1))
{
yield return concat<T>(new T[] { startingElement }, permutationOfRemainder);
}
++startingElementIndex;
}
}
}
// Implements the recursive part of Permute<T>
private static void permute<T>(T[] items, int item, T[] permutation, bool[] used, Action<T[]> output)
{
for (int i = 0; i < items.Length; ++i)
{
if (!used[i])
{
used[i] = true;
permutation[item] = items[i];
if (item < (items.Length - 1))
{
permute(items, item + 1, permutation, used, output);
}
else
{
output(permutation);
}
used[i] = false;
}
}
}
// Enumerates over all items in the input, skipping over the item with the specified index.
private static IEnumerable<T> allExcept<T>(IEnumerable<T> input, int indexToSkip)
{
int index = 0;
foreach (T item in input)
{
if (index != indexToSkip)
{
yield return item;
}
++index;
}
}
// Enumerates over contents of two lists sequentially.
private static IEnumerable<T> concat<T>(IEnumerable<T> a, IEnumerable<T> b)
{
foreach (T item in a)
{
yield return item;
}
foreach (T item in b)
{
yield return item;
}
}
}
}