问题
I would like to generate anagram output of a given string without the help of any external libraries such as Google anagram algorithms helper.
Example:
Input string = "GOD"
Output list should look like the following one:
G O D GO GD OD OG DG DO GOD GDO ODG OGD DGO DOG
回答1:
That taks turned to be awesome on so many levels. I present you a pure LINQ (but not very efficient) solution.
static class Program
{
static void Main(string[] args)
{
var res = "cat".Anagrams();
foreach (var anagram in res)
Console.WriteLine(anagram.MergeToStr());
}
static IEnumerable<IEnumerable<T>> Anagrams<T>(this IEnumerable<T> collection) where T: IComparable<T>
{
var total = collection.Count();
// provided str "cat" get all subsets c, a, ca, at, etc (really nonefficient)
var subsets = collection.Permutations()
.SelectMany(c => Enumerable.Range(1, total).Select(i => c.Take(i)))
.Distinct(new CollectionComparer<T>());
return subsets;
}
public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> collection)
{
return collection.Count() > 1
?
from ch in collection
let set = new[] { ch }
from permutation in collection.Except(set).Permutations()
select set.Union(permutation)
:
new[] { collection };
}
public static string MergeToStr(this IEnumerable<char> chars)
{
return new string(chars.ToArray());
}
}// class
// cause Distinct implementation is shit
public class CollectionComparer<T> : IEqualityComparer<IEnumerable<T>> where T: IComparable<T>
{
Dictionary<IEnumerable<T>, int> dict = new Dictionary<IEnumerable<T>, int>();
public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
if (x.Count() != y.Count())
return false;
return x.Zip(y, (xi, yi) => xi.Equals(yi)).All(compareResult => compareResult);
}
public int GetHashCode(IEnumerable<T> obj)
{
var inDict = dict.Keys.FirstOrDefault(k => Equals(k, obj));
if (inDict != null)
return dict[inDict];
else
{
int n = dict.Count;
dict[obj] = n;
return n;
}
}
}// class
回答2:
For what it's worth, I wrote methods in Java that will do what you want, and I understand C# is similar enough you will probably be able to read the code without much trouble. (The syntax, that is. If you are not comfortable with recursive functions then that could give you trouble.) My user name is @undefined over on this forum thread. To use the code, you could loop through k-values from 1 to the length of your string inclusive. Alternatively, you could generate all subsets (discarding the empty set) as described in this thread and then get the permutations from there. Another way is to write a kth-permutation function and use that. I don't have one posted online; the one I use is a bit messy and I should rewrite it sometime.
Edit: Worth mentioning that I wrote the methods in a way that seemed easy, but more efficient would be to use a stack, that way you don't have to create tons of new objects.
回答3:
try this
public static IEnumerable<string> Permutations(this string text)
{
return PermutationsImpl(string.Empty, text);
}
private static IEnumerable<string> PermutationsImpl(string start, string text)
{
if (text.Length <= 1)
yield return start + text;
else
{
for (int i = 0; i < text.Length; i++)
{
text = text[i] +
text.Substring(0, i) +
text.Substring(i + 1);
foreach (var s in PermutationsImpl(start +
text[0], text.Substring(1)))
yield return s;
}
}
}
then simply use this extension method this way
string text = "CAT";
List<string> perms = text.Permutations().ToList();
来源:https://stackoverflow.com/questions/4409773/how-to-write-an-anagram-generator-in-pure-c-sharp-and-net-framework