4

ユーザーがテキストボックスにテキストを入力できるようにし、最小 3 文字、最大 6 文字を除いて、可能なすべての組み合わせをプログラムに生成させようとしています。 「a」、「i」、「to」などが配列を乱雑にしています。また、各組み合わせを辞書と照合して、それが実際の単語であることを確認します.

私は完全な辞書を持っています (骨の折れる作業で生成されたものです。見返りとして、辞書へのリンクがあります(警告: 膨大な読み込み時間 (私にとって)!)

とにかく、ユーザーが「ABCDEF」と入力した場合 (順不同)、たとえば次のように生成できます。

'ABC'
'BAC'
'CAB'
...
'ABD'
'ABE'
'ABF'

など...順序に関係なく、すべての可能な組み合わせはありますか? とんでもない数の組み合わせがあるのは承知していますが、一度計算すればいいのであまり気にしていません。

固定幅文字列 (ABCDEF、ABCDFE ... ACDBFE など) だけの組み合わせ (順列ではなく、必要ありません) を再帰的に見つけるコード サンプルを見つけました。彼らは私が必要とすることをしてくれませんし、私はこのプロジェクトをどこから始めればよいのか、まったく手がかりがありません。

これは宿題ではありません。私の個人的なプロジェクトとして始まり、このような単純な問題が私の人生を引き継ぐようになりました... 私がこれを理解できないなんて信じられません!

4

4 に答える 4

2

パワーセットについて説明しているように思えます

私の個人的なライブラリの周りに横たわっていた実装は次のとおりです。

// Helper method to count set bits in an integer
public static int CountBits(int n)
{
    int count = 0;
    while (n != 0)
    {
        count++;
        n &= (n - 1);
    }
    return count;
}


public static IEnumerable<IEnumerable<T>> PowerSet<T>(
    IEnumerable<T> src, 
    int minSetSize = 0, 
    int maxSetSize = int.MaxValue)
{
    // we want fast random access to the source, so we'll
    // need to ToArray() it
    var cached = src.ToArray();
    var setSize = Math.Pow(2, cached.Length);
    for(int i=0; i < setSize; i++)
    {
        var subSetSize = CountBits(i);
        if(subSetSize < minSetSize || 
           subSetSize > maxSetSize)
        {
            continue;
        }
        T[] set = new T[subSetSize];

        var temp = i;
        var srcIdx = 0;
        var dstIdx = 0;
        while(temp > 0)
        {
            if((temp & 0x01) == 1)
            {
                set[dstIdx++] = cached[srcIdx];
            }
            temp >>= 1;
            srcIdx++;            
        }
        yield return set;
    }
    yield break;
}

そして、簡単なテスト リグ:

void Main()
{
    var src = "ABCDEF";
    var combos = PowerSet(src, 3, 6);

    // hairy joins for great prettiness
    Console.WriteLine(
        string.Join(" , ", 
            combos.Select(subset => 
                string.Concat("[", 
                    string.Join(",", subset) , "]")))
    );
}

出力:

[A,B,C] , [A,B,D] , [A,C,D] , [B,C,D] , [A,B,C,D] , [A,B,E] , [A,C,E] , [B,C,E] , [A,B,C,E] , 
[A,D,E] , [B,D,E] , [A,B,D,E] , [C,D,E] , [A,C,D,E] , [B,C,D,E] , [A,B,C,D,E] , [A,B,F] , 
[A,C,F] , [B,C,F] , [A,B,C,F] , [A,D,F] , [B,D,F] , [A,B,D,F] , [C,D,F] , [A,C,D,F] , 
[B,C,D,F] , [A,B,C,D,F] , [A,E,F] , [B,E,F] , [A,B,E,F] , [C,E,F] , [A,C,E,F] , [B,C,E,F] , 
[A,B,C,E,F] , [D,E,F] , [A,D,E,F] , [B,D,E,F] , [A,B,D,E,F] , [C,D,E,F] , [A,C,D,E,F] , 
[B,C,D,E,F] , [A,B,C,D,E,F]
于 2013-02-27T04:21:47.360 に答える
0

「AAB」のようなものも必要だと仮定すると、文字セットの「交差積」はそれであるはずです。

生成は LINQ と同じくらい簡単です。

            string myset = "ABCDE";
            var All = (from char l1 in myset 
                   from char l2 in myset 
                   from char l3 in myset 
                   select new string(new char[] { l1, l2, l3})).ToList();

注: 多くの文字列と文字配列の構築は高速ではありません。次のように、新しい文字列と新しい char[] をカスタム クラスに置き換えることができます。

select new MyCustomClass(l1, l2, l3).ToList();

「AAB」(または「EEL」)のようなものが必要ない場合は、ウィキペディアの「組み合わせ」を参照してください。

固定長から「3 から 6 までの任意の長さ」にするには、複数のセットを結合します。制限が動的である場合は、ループを使用します。

于 2013-02-27T03:28:10.103 に答える
0

これを行う最善の方法は、for ループを使用して、各文字を int から char に変換し、それらを文字列に連結することです。

例えば:

for(int i = 0; i < 26; i++)
{
    Console.WriteLine((char)i + 'A');        
}
于 2013-02-27T03:29:06.050 に答える
0

このリンクから(MIT ライセンスの下で)

using System;
using System.Collections.Generic;
using System.Diagnostics;

// Copyright (c) 2010 Alex Regueiro
// Licensed under MIT license, available at <http://www.opensource.org/licenses/mit-license.php>.
// Published originally at <http://blog.noldorin.com/2010/05/combinatorics-in-csharp/>.
// Version 1.0, released 22nd May 2010.
public static class CombinatoricsUtilities
{
    // Error messages
    private const string errorMessageValueLessThanZero = "Value must be greater than zero, if specified.";
    private const string errorMessagesIndicesListInvalidSize = "List of indices must have same size as list of elements.";

    /// <summary>
    /// Gets all permutations (of a given size) of a given list, either with or without reptitions.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the list.</typeparam>
    /// <param name="list">The list of which to get permutations.</param>
    /// <param name="action">The action to perform on each permutation of the list.</param>
    /// <param name="resultSize">The number of elements in each resulting permutation; or <see langword="null"/> to get
    /// premutations of the same size as <paramref name="list"/>.</param>
    /// <param name="withRepetition"><see langword="true"/> to get permutations with reptition of elements;
    /// <see langword="false"/> to get permutations without reptition of elements.</param>
    /// <exception cref="ArgumentNullException"><paramref name="list"/> is <see langword="null"/>. -or-
    /// <paramref name="action"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentException"><paramref name="resultSize"/> is less than zero.</exception>
    /// <remarks>
    /// The algorithm performs permutations in-place. <paramref name="list"/> is however not changed.
    /// </remarks>
    public static void GetPermutations<T>(this IList<T> list, Action<IList<T>> action, int? resultSize = null,
        bool withRepetition = false)
    {
        if (list == null)
            throw new ArgumentNullException("list");
        if (action == null)
            throw new ArgumentNullException("action");
        if (resultSize.HasValue && resultSize.Value <= 0)
            throw new ArgumentException(errorMessageValueLessThanZero, "resultSize");

        var result = new T[resultSize.HasValue ? resultSize.Value : list.Count];
        var indices = new int[result.Length];
        for (int i = 0; i < indices.Length; i++)
            indices[i] = withRepetition ? -1 : i - 1;

        int curIndex = 0;
        while (curIndex != -1)
        {
            indices[curIndex]++;
            if (indices[curIndex] == list.Count)
            {
                indices[curIndex] = withRepetition ? -1 : curIndex - 1;
                curIndex--;
            }
            else
            {
                result[curIndex] = list[indices[curIndex]];
                if (curIndex < indices.Length - 1)
                    curIndex++;
                else
                    action(result);
            }
        }
    }

    /// <summary>
    /// Gets all combinations (of a given size) of a given list, either with or without reptitions.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the list.</typeparam>
    /// <param name="list">The list of which to get combinations.</param>
    /// <param name="action">The action to perform on each combination of the list.</param>
    /// <param name="resultSize">The number of elements in each resulting combination; or <see langword="null"/> to get
    /// premutations of the same size as <paramref name="list"/>.</param>
    /// <param name="withRepetition"><see langword="true"/> to get combinations with reptition of elements;
    /// <see langword="false"/> to get combinations without reptition of elements.</param>
    /// <exception cref="ArgumentNullException"><paramref name="list"/> is <see langword="null"/>. -or-
    /// <paramref name="action"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentException"><paramref name="resultSize"/> is less than zero.</exception>
    /// <remarks>
    /// The algorithm performs combinations in-place. <paramref name="list"/> is however not changed.
    /// </remarks>
    public static void GetCombinations<T>(this IList<T> list, Action<IList<T>> action, int? resultSize = null,
        bool withRepetition = false)
    {
        if (list == null)
            throw new ArgumentNullException("list");
        if (action == null)
            throw new ArgumentNullException("action");
        if (resultSize.HasValue && resultSize.Value <= 0)
            throw new ArgumentException(errorMessageValueLessThanZero, "resultSize");

        var result = new T[resultSize.HasValue ? resultSize.Value : list.Count];
        var indices = new int[result.Length];
        for (int i = 0; i < indices.Length; i++)
            indices[i] = withRepetition ? -1 : indices.Length - i - 2;

        int curIndex = 0;
        while (curIndex != -1)
        {
            indices[curIndex]++;
            if (indices[curIndex] == (curIndex == 0 ? list.Count : indices[curIndex - 1] + (withRepetition ? 1 : 0)))
            {
                indices[curIndex] = withRepetition ? -1 : indices.Length - curIndex - 2;
                curIndex--;
            }
            else
            {
                result[curIndex] = list[indices[curIndex]];
                if (curIndex < indices.Length - 1)
                    curIndex++;
                else
                    action(result);
            }
        }
    }

    /// <summary>
    /// Gets a specific permutation of a given list.
    /// </summary>
    /// <typeparam name="T">The type of the elements in the list.</typeparam>
    /// <param name="list">The list to permute.</param>
    /// <param name="indices">The indices of the elements in the original list at each index in the permuted list.
    /// </param>
    /// <returns>The specified permutation of the given list.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="list"/> is <see langword="null"/>. -or-
    /// <paramref name="indices"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentException"><paramref name="indices"/> does not have the same size as
    /// <paramref name="list"/>.</exception>
    public static IList<T> Permute<T>(this IList<T> list, IList<int> indices)
    {
        if (list == null)
            throw new ArgumentNullException("list");
        if (indices == null)
            throw new ArgumentNullException("indices");
        if (list.Count != indices.Count)
            throw new ArgumentException(errorMessagesIndicesListInvalidSize, "indices");

        var result = new T[list.Count];
        for (int i = 0; i < result.Length; i++)
            result[i] = list[indices[i]];
        return result;
    }
}
于 2013-02-27T03:35:32.560 に答える