开发者

Find string permutation including the single character using C# or F#

I would like to generate a li开发者_如何转开发st of all possible permutations of a string containing a variable list of characters. For example if I have the string "ABC", I would like to have a list that contains all the possible variations, like: A, B, C, AB, BC.

Thank you.


It's hard to tell exactly what you want, but based on your example output here's how to do what I think you're after in F#.

let combinations (s:string) =
  let rec loop acc i =
    seq {
      for i in i .. (s.Length - 1) do
        let acc = acc + s.[i..i]
        yield acc
        yield! loop acc (i + 1)
    }
  loop "" 0

combinations "ABC" |> Seq.toList //["A"; "AB"; "ABC"; "AC"; "B"; "BC"; "C"]


Here's a LINQ version:

Func<string, IEnumerable<string>> perm = t =>
{
    Func<string, string, IEnumerable<string>> perm2 = null;
    perm2 =
        (t0, t1s) =>
            from n in Enumerable.Range(0, t1s.Length)
            let c = t1s.Substring(n, 1)
            let x = t1s.Remove(n, 1)
            let h = t0 + c
            from r in (new [] { h, }).Concat(perm2(h, x))
            select r;
    return perm2("", t);
};

Use it like this:

var ps = perm("abc");

And it will perform a lazy computation.

var ps = perm("abcdefghijklmnopqrstuvwxyz").Take(2);
// Only computes two values when executed


Here will return all of the permutations (not distinct) given a string of chars. it's not fast or efficient, but it does work...

  public List<string> permute(string value, string prefix = "")
    {
        List<string> result = new List<string>();
        for (int x=0;x<value.Length;x++)
        {
            result.Add(prefix + value[x]);
            result.AddRange(permute( value.Remove(x, 1), prefix + value[x]));
        }
        return result;
    }

To use:

       List<string> output = permute("abc");


Check out this snippet at F# Snippets


If you are looking for a permutation by index (instead of having to iterate over all the permutations) you can use a numbering system called factoradics (Source) to find them. Here is the code from the original article, with a stronger C# style (the original code is very 'C++ish') and generics.

/// <summary>
/// Permutes the specified atoms; in lexicographical order.
/// </summary>
/// <typeparam name="T">The type of elements.</typeparam>
/// <param name="atoms">The atoms.</param>
/// <param name="index">The index of the permutation to find.</param>
/// <returns>The permutation.</returns>
public static IList<T> Permute<T>(this IList<T> atoms, int index)
{
    var result = new T[atoms.Count];
    Permute(atoms, result, index);
    return result;
}

/// <summary>
/// Permutes the specified atoms; in lexicographical order.
/// </summary>
/// <typeparam name="T">The type of elements.</typeparam>
/// <param name="atoms">The atoms.</param>
/// <param name="target">The array to place the permutation in.</param>
/// <param name="index">The index of the permutation to find.</param>
public static void Permute<T>(this IList<T> atoms, IList<T> target, int index)
{
    if (atoms == null)
        throw new ArgumentNullException("atoms");
    if (target == null)
        throw new ArgumentNullException("target");
    if (target.Count < atoms.Count)
        throw new ArgumentOutOfRangeException("target");
    if (index < 0)
        throw new ArgumentOutOfRangeException("index");

    var order = atoms.Count;

    // Step #1 - Find factoradic of k
    var perm = new int[order];
    for (var j = 1; j <= order; j++)
    {
        perm[order - j] = index % j;
        index /= j;
    }

    // Step #2 - Convert factoradic[] to numeric permuatation in perm[]
    var temp = new int[order];
    for (var i = 0; i < order; i++)
    {
        temp[i] = perm[i] + 1;
        perm[i] = 0;
    }

    perm[order - 1] = 1;  // right-most value is set to 1.
    for (var i = order - 2; i >= 0; i--)
    {
        perm[i] = temp[i];
        for (var j = i + 1; j < order; j++)
        {
            if (perm[j] >= perm[i])
                perm[j]++;
        }
    }

    // Step #3 - map numeric permutation to string permutation
    for (var i = 0; i < order; ++i)
    {
        target[i] = atoms[perm[i] - 1];
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜