Перечисление всех перестановок строки / целого числа

Мое решение представляет собой сочетание нескольких ответов здесь.

Я проверил сервер сборки, и Windows7 / NET4.0 SDK был уже установлен, поэтому я нашел путь:

C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v9.0 \ WebApplications \ Microsoft.WebApplication.targets`

Однако в этой строке:

& lt; Импорт проекта = "$ (MSBuildExtensionsPath) \ Microsoft \ VisualStudio \ v9.0 \ WebApplications \ Microsoft.WebApplication.targets" />

$ ( MSBuildExtensionsPath) расширяется до C: \ Program Files \ MSBuild, у которого нет пути.

Поэтому я сделал, чтобы создать символическую ссылку, используя эту команду:

mklink / J "C: \ Program Files \ MSBuild \ Microsoft \ VisualStudio" "C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio"

Таким образом расширяет $ (MSBuildExtensionsPath) к допустимому пути, и никаких изменений не требуется в самом приложении, только на сервере сборки (возможно, можно создать syml чернила для каждой сборки, чтобы убедиться, что этот шаг не потерян и «задокументирован»).

149
задан Machavity 26 December 2017 в 16:38
поделиться

6 ответов

Прежде всего: пахнет как рекурсия конечно!

Так как вы тоже хотели Чтобы узнать принцип, я сделал все возможное, чтобы объяснить это человеческим языком. Я думаю, что рекурсия в большинстве случаев очень проста. Вы должны понять только два шага:

  1. Первый шаг
  2. Все остальные шаги (все с одинаковой логикой)

На человеческом языке :

Короче:
1. Перестановка 1 элемента является одним элементом.
2. Перестановка набора элементов представляет собой список каждого из элементов, соединенных с каждой перестановкой других элементов.

Пример:

Если в наборе только один элемент ->
вернуть его.
perm (a) -> a

Если набор состоит из двух символов: для каждый элемент в нем: вернуть элемент, с перестановкой остальные добавленные элементы, например, так:

perm (ab) ->

a + perm (b) -> ab

b + perm (a) -> ba

Далее: для каждого символа в наборе: вернуть символ, объединенный с перестановкой> остальной части набора

perm (abc) ->

a + perm (bc) -> abc , acb

b + perm (ac) -> bac , bca

c + perm (ab) -> cab , cba

perm (abc ... z) ->

a + perm (...), b + perm (....)
....

Я нашел псевдокод на http://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/ :

makePermutations(permutation) {
  if (length permutation < required length) {
    for (i = min digit to max digit) {
      if (i not in permutation) {
        makePermutations(permutation+i)
      }
    }
  }
  else {
    add permutation to list
  }
}

C #

Хорошо, и что-то более сложное (и поскольку оно помечено как c #), из http://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html : Довольно длинная, но я все равно решила скопировать ее, чтобы пост не зависел от оригинала.

Функция берет строку символов и записывает каждую возможную перестановку этой точной строки, например, если «ABC» «поставлено, должно разлиться:

ABC, ACB, BAC, BCA, CAB, CBA.

Код:

class Program
{
    private static void Swap(ref char a, ref char b)
    {
        if (a == b) return;

        var temp = a;
        a = b;
        b = temp;
    }

    public static void GetPer(char[] list)
    {
        int x = list.Length - 1;
        GetPer(list, 0, x);
    }

    private static void GetPer(char[] list, int k, int m)
    {
        if (k == m)
        {
            Console.Write(list);
        }
        else
            for (int i = k; i <= m; i++)
            {
                   Swap(ref list[k], ref list[i]);
                   GetPer(list, k + 1, m);
                   Swap(ref list[k], ref list[i]);
            }
    }

    static void Main()
    {
        string str = "sagiv";
        char[] arr = str.ToCharArray();
        GetPer(arr);
    }
}
143
ответ дан 23 November 2019 в 22:19
поделиться

Вот чисто функциональная реализация F #:


let factorial i =
    let rec fact n x =
        match n with
        | 0 -> 1
        | 1 -> x
        | _ -> fact (n-1) (x*n)
    fact i 1

let swap (arr:'a array) i j = [| for k in 0..(arr.Length-1) -> if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]

let rec permutation (k:int,j:int) (r:'a array) =
    if j = (r.Length + 1) then r
    else permutation (k/j+1, j+1) (swap r (j-1) (k%j))

let permutations (source:'a array) = seq { for k = 0 to (source |> Array.length |> factorial) - 1 do yield permutation (k,2) source }

Производительность можно значительно улучшить, изменив свопинг, чтобы воспользоваться изменчивой природой массивов CLR, но эта реализация является потокобезопасным по отношению к исходному массиву, и это может быть желательно в некоторых контекстах. Кроме того, для массивов с более чем 16 элементами int необходимо заменить типами с большей / произвольной точностью, поскольку факториал 17 приводит к int32 переполнение.

5
ответ дан 23 November 2019 в 22:19
поделиться

Вот хорошая статья, охватывающая три алгоритма для нахождения всех перестановок, в том числе один для нахождения следующей перестановки.

http : //www.cut-the-knot.org/do_you_know/AllPerm.shtml

C ++ и Python имеют встроенные функции next_permutation и itertools.permutations , соответственно.

5
ответ дан 23 November 2019 в 22:19
поделиться

Прежде всего, наборы имеют перестановки, а не строки или целые числа, поэтому я просто предполагаю, что вы имеете в виду «набор символов в строке. "

Обратите внимание, что набор размера n имеет n! n-перестановки.

Следующий псевдокод (из Википедии), вызываемый с k = 1 ... n! выдаст все перестановки:

function permutation(k, s) {
    for j = 2 to length(s) {
        swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
        k := k / j; // integer division cuts off the remainder
    }
    return s;
}

Вот эквивалентный код Python (для индексов массива на основе 0):

def permutation(k, s):
    r = s[:]
    for j in range(2, len(s)+1):
        r[j-1], r[k%j] = r[k%j], r[j-1]
        k = k/j+1
    return r
9
ответ дан 23 November 2019 в 22:19
поделиться

Построение на решении @Peter, вот версия, которая объявляет простой LINQ-стиль Permutations() дополнительный метод, который работает над любым IEnumerable<T>.

Использование (на примере символов строки):

foreach (var permutation in "abc".Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

Выводы:

a, b, c
a, c, b
b, a, c
b, c, a
c, b, a
c, a, b

Или на любом другом типе набора:

foreach (var permutation in (new[] { "Apples", "Oranges", "Pears"}).Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

Выводы:

Apples, Oranges, Pears
Apples, Pears, Oranges
Oranges, Apples, Pears
Oranges, Pears, Apples
Pears, Oranges, Apples
Pears, Apples, Oranges
using System;
using System.Collections.Generic;
using System.Linq;

public static class PermutationExtension
{
    public static IEnumerable<T[]> Permutations<T>(this IEnumerable<T> source)
    {
        var sourceArray = source.ToArray();
        var results = new List<T[]>();
        Permute(sourceArray, 0, sourceArray.Length - 1, results);
        return results;
    }

    private static void Swap<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }

    private static void Permute<T>(T[] elements, int recursionDepth, int maxDepth, ICollection<T[]> results)
    {
        if (recursionDepth == maxDepth)
        {
            results.Add(elements.ToArray());
            return;
        }

        for (var i = recursionDepth; i <= maxDepth; i++)
        {
            Swap(ref elements[recursionDepth], ref elements[i]);
            Permute(elements, recursionDepth + 1, maxDepth, results);
            Swap(ref elements[recursionDepth], ref elements[i]);
        }
    }
}
0
ответ дан 23 November 2019 в 22:19
поделиться
void permute (char *str, int ptr) {
  int i, len;
  len = strlen(str);
  if (ptr == len) {
    printf ("%s\n", str);
    return;
  }

  for (i = ptr ; i < len ; i++) {
    swap (&str[ptr], &str[i]);
    permute (str, ptr + 1);
    swap (&str[ptr], &str[i]);
  }
}

Вы можете написать свою функцию обмена для замены символов.
Это должно вызываться как permute (строка, 0);

11
ответ дан 23 November 2019 в 22:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: