1

重複の可能性:
セットの順列の生成 (最も効率的)

私は古いプログラミングの課題を見ていて、解決策を考え出そうとしていました。チャレンジは期限切れで、何年も経っています。この時点では、スキルを構築するためだけにやっています。

次のパターンで数値を生成する必要があります。

  • 123456789
  • 123456798
  • 123456879
  • 123456897
  • 123456978
  • 123456987

続けて、常に同じ 9 つの数字を使用し、決して複製せず、常に次の数字を取得します。

私は過去 2 時間頭を悩ませてきましたが、これに取り組むための適切なプログラミング パターンがわかりません。

助言がありますか?

4

2 に答える 2

1

解決策としてこれはどうですか:

var numerals = Enumerable.Range(1, 9).ToArray();

var query =
    from n1 in numerals
    from n2 in numerals.Except(new [] { n1, })
    from n3 in numerals.Except(new [] { n1, n2, })
    from n4 in numerals.Except(new [] { n1, n2, n3, })
    from n5 in numerals.Except(new [] { n1, n2, n3, n4, })
    from n6 in numerals.Except(new [] { n1, n2, n3, n4, n5, })
    from n7 in numerals.Except(new [] { n1, n2, n3, n4, n5, n6, })
    from n8 in numerals.Except(new [] { n1, n2, n3, n4, n5, n6, n7, })
    from n9 in numerals.Except(new [] { n1, n2, n3, n4, n5, n6, n7, n8, })
    select n1 * 100000000
        + n2 * 10000000
        + n3 * 1000000
        + n4 * 100000
        + n5 * 10000
        + n6 * 1000
        + n7 * 100
        + n8 * 10
        + n9;

これは非常に高速であり、私のコンピューターでは 864 ミリ秒ですべての結果が生成されます。

最初の 10 件の結果は次のとおりです。

123456789 
123456798 
123456879 
123456897 
123456978 
123456987 
123457689 
123457698 
123457869 
123457896 
于 2012-10-10T03:51:40.487 に答える
0

私は2つの解決策を思いつきました:

遅い方法

private static void GetAnswerByLoopingNumbers(Stopwatch timer) 
{
    int _counter = 1;
    for (int number = 123456789; number <= 987654321; number += 9)
    {
        string numToCheck = number.ToString();
        if (ContainsZero(numToCheck) || ContainsDuplicates(numToCheck))
            continue;
        _counter++;
        if (_counter != 100000)
            continue;
        timer.Stop();
        CheckAnswer(numToCheck, timer);
        break;
    } }

private static bool ContainsDuplicates(IEnumerable<char> numToCheck)
{
    IEnumerable<char> check = numToCheck as char[] ?? numToCheck.ToArray();
    foreach (char number in check)
    {
        int count = 0;
        foreach (char c in check)
        {
            if (c == number)
                count++;
        }
        if (count > 1)
            return true;
    }
    return false;
}

private static bool ContainsZero(IEnumerable<char> numToCheck)
{
    foreach (char number in numToCheck)
    {
        if (number == '0')
            return true;
    }
    return false;
}

速い方法

private static void GetAnswerByCreatingPermutations(Stopwatch timer)
{
    int _counter = 1;
    int[] baseNumberSet = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    while (_counter < 100000)
    {
        int firstSwapNumber = GetFirstNumberToSwap(baseNumberSet);
        int secondSwapNumber = GetSecondSwapNumber(firstSwapNumber, baseNumberSet);
        if (baseNumberSet[firstSwapNumber] >= baseNumberSet[secondSwapNumber])
            continue;
        SwapNumbers(firstSwapNumber, secondSwapNumber, baseNumberSet);
        ReverseSequenceOfNumbersAfterFirstSwapNumber(firstSwapNumber, baseNumberSet);
        _counter++;
    }
}

private static int GetFirstNumberToSwap(int[] baseNumberSet)
{
    int largestIndex = 0;

    // Check first 8 numbers
    for (int index = 0; index < 8; index++)
    {
        // Check to see if current number, is less than the next number
        if (baseNumberSet[index] < baseNumberSet[index + 1])
            largestIndex = index;
    }
    // Return the last number in sequence, to be smaller than the next number in the sequence
    return largestIndex;
}

private static int GetSecondSwapNumber(int firstSwapNumber, int[] baseNumberSet)
{
    int secondLargestIndex = 0;

    // Check all nine numbers
    for (int index = 0; index < 9; index++)
    {
        // Check to see if number is bigger than first swap number
        if (baseNumberSet[firstSwapNumber] < baseNumberSet[index])
            secondLargestIndex = index;
    }
    // Return last number in sequence that is larger than the first swap number
    return secondLargestIndex;
}

private static void ReverseSequenceOfNumbersAfterFirstSwapNumber(int firstSwapNumber, int[] baseNumberSet)
{
    if (firstSwapNumber >= 7)
        return;
    int lengthOfSequenceToSwap = 8 - firstSwapNumber;
    if (lengthOfSequenceToSwap <= 1)
        return;
    Array.Reverse(baseNumberSet, firstSwapNumber + 1, lengthOfSequenceToSwap);
}

private static void SwapNumbers(int firstSwapNumber, int secondSwapNumber, int[] baseNumberSet)
{
    baseNumberSet[firstSwapNumber] ^= baseNumberSet[secondSwapNumber];
    baseNumberSet[secondSwapNumber] ^= baseNumberSet[firstSwapNumber];
    baseNumberSet[firstSwapNumber] ^= baseNumberSet[secondSwapNumber];
}
于 2012-10-10T04:28:12.977 に答える