listę wszystkich możliwych permutacji ciąg generować

głosy
143

Jak bym go o generowanie listy wszystkich możliwych permutacji ciąg pomiędzy X i Y znaków, zawierającego zmienną listę znaków.

Każdy język będzie działać, ale powinno być przenośne.

Utwórz 02/08/2008 o 07:57
źródło użytkownik
W innych językach...                            


35 odpowiedzi

głosy
67

Istnieje kilka sposobów, aby to zrobić. Wspólne metody użyć rekurencji, memoization lub programowanie dynamiczne. Podstawowym założeniem jest to, że można produkować listę wszystkich ciągów o długości 1, a następnie w każdej iteracji, za wszystkie sznurki produkowane w ostatniej iteracji, należy dodać, że ciąg sklejane z każdego znaku w łańcuchu indywidualnie. (Zmienna indeksu w kodzie poniżej śledzi początku ostatniej i następnej iteracji)

Niektóre Pseudokod:

list = originalString.split('')
index = (0,0)
list = [""]
for iteration n in 1 to y:
  index = (index[1], len(list))
  for string s in list.subset(index[0] to end):
    for character c in originalString:
      list.add(s + c)

którą następnie trzeba usunąć wszystkie ciągi mniej niż x długość, będą pierwszymi (x-1) * DŁ (originalString) pozycje w liście.

Odpowiedział 02/08/2008 o 08:48
źródło użytkownik

głosy
35

Lepiej użyć Backtracking

#include <stdio.h>
#include <string.h>

void swap(char *a, char *b) {
    char temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void print(char *a, int i, int n) {
    int j;
    if(i == n) {
        printf("%s\n", a);
    } else {
        for(j = i; j <= n; j++) {
            swap(a + i, a + j);
            print(a, i + 1, n);
            swap(a + i, a + j);
        }
    }
}

int main(void) {
    char a[100];
    gets(a);
    print(a, 0, strlen(a) - 1);
    return 0;
}
Odpowiedział 10/01/2012 o 19:00
źródło użytkownik

głosy
24

Masz zamiar uzyskać wiele strun, to na pewno ...

\ sum_ {i = X ^ Y} {\ Frac {R!} {{(ri)}!}} http://www.codecogs.com/eq.latex?%5Csum_%7Bi=x%7D%5Ey% 20% 7B% 20% 5Cfrac%% 7D% 7BR 7B% 7B (ri)% 7D% 7D% 20% 7D!
Gdzie, x i Y jest jak je definiować i R jest liczba znaków jesteśmy doborze od - -Jeśli mam zrozumienia zostanie poprawnie. Należy zdecydowanie generować je jako potrzebne i nie dostać niechlujny i powiedzieć, wygeneruje PowerSet a następnie filtrować długości strun.

Poniższy zdecydowanie nie jest to najlepszy sposób, aby wygenerować te, ale to ciekawy bok, żaden-the-mniej.

Knuth (tom 4, zeszyt 2, 7.2.1.3) mówi, że (S, T) -combination odpowiada s + 1 rzeczy brane T w czasie z powtarzania - (S, T) -combination jest używany przez oznaczenie Knuth, która jest równa {t \ wybrać {s + t} http://www.codecogs.com/eq.latex?%7Bt%20%5Cchoose%20%7Bs+t%7D%7D . Można to zrozumieć, że najpierw generuje każdą (s, t) -combination binarnie (tak długości (s + t)) i zliczanie liczby tych do 0 po lewej stronie każdej 1.

10001000011101 -> staje się przestawianie {0, 3, 4, 4, 4, 1}

Odpowiedział 05/08/2008 o 05:57
źródło użytkownik

głosy
14

Dla roztworu rekurencyjne według przykładu Knuth Pythonie

def nextPermutation(perm):
    k0 = None
    for i in range(len(perm)-1):
        if perm[i]<perm[i+1]:
            k0=i
    if k0 == None:
        return None

    l0 = k0+1
    for i in range(k0+1, len(perm)):
        if perm[k0] < perm[i]:
            l0 = i

    perm[k0], perm[l0] = perm[l0], perm[k0]
    perm[k0+1:] = reversed(perm[k0+1:])
    return perm

perm=list("12345")
while perm:
    print perm
    perm = nextPermutation(perm)
Odpowiedział 09/11/2010 o 14:58
źródło użytkownik

głosy
12

Istnieje wiele dobrych odpowiedzi tutaj. Proponuję także bardzo proste rozwiązanie rekurencyjnej w C ++.

#include <string>
#include <iostream>

template<typename Consume>
void permutations(std::string s, Consume consume, std::size_t start = 0) {
    if (start == s.length()) consume(s);
    for (std::size_t i = start; i < s.length(); i++) {
        std::swap(s[start], s[i]);
        permutations(s, consume, start + 1);
    }
}

int main(void) {
    std::string s = "abcd";
    permutations(s, [](std::string s) {
        std::cout << s << std::endl;
    });
}

Uwaga : powtarzające się ciągi znaków ze nie będzie produkować unikalne permutacji.

Odpowiedział 08/01/2014 o 12:00
źródło użytkownik

głosy
12

Oto proste rozwiązanie w języku C #.

Generuje tylko różne permutacje danego łańcucha.

    static public IEnumerable<string> permute(string word)
    {
        if (word.Length > 1)
        {

            char character = word[0];
            foreach (string subPermute in permute(word.Substring(1)))
            {

                for (int index = 0; index <= subPermute.Length; index++)
                {
                    string pre = subPermute.Substring(0, index);
                    string post = subPermute.Substring(index);

                    if (post.Contains(character))
                            continue;                       

                    yield return pre + character + post;
                }

            }
        }
        else
        {
            yield return word;
        }
    }
Odpowiedział 05/07/2010 o 10:06
źródło użytkownik

głosy
12

Niektórzy pracują kod Java na podstawie odpowiedzi SARP :

public class permute {

    static void permute(int level, String permuted,
                    boolean used[], String original) {
        int length = original.length();
        if (level == length) {
            System.out.println(permuted);
        } else {
            for (int i = 0; i < length; i++) {
                if (!used[i]) {
                    used[i] = true;
                    permute(level + 1, permuted + original.charAt(i),
                       used, original);
                    used[i] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        String s = "hello";
        boolean used[] = {false, false, false, false, false};
        permute(0, "", used, s);
    }
}
Odpowiedział 04/04/2010 o 19:18
źródło użytkownik

głosy
12

Można spojrzeć na „ Skutecznie Wyliczając podzbiorów zbioru ”, który opisuje algorytm zrobić część tego, co chcesz - szybko wygenerować wszystkie podzbiory N znaków od długości x do y. Zawiera ona implementację w C

Dla każdego podzbioru, że nadal masz do generowania wszystkich permutacji. Na przykład, jeśli chcesz 3 znaki z „ABCDE”, algorytm ten nie daje „abc”, „abd”, „abe” ... ale trzeba by permutacji każdy dostać „ACB”, „bac” "BCA", etc.

Odpowiedział 14/11/2008 o 20:36
źródło użytkownik

głosy
8

Właśnie bita to się szybko w Ruby:

def perms(x, y, possible_characters)
  all = [""]
  current_array = all.clone
  1.upto(y) { |iteration|
    next_array = []
    current_array.each { |string|
      possible_characters.each { |c|
        value = string + c
        next_array.insert next_array.length, value
        all.insert all.length, value
      }
    }
    current_array = next_array
  }
  all.delete_if { |string| string.length < x }
end

Można spojrzeć na język API dla wbudowanych funkcji typu permutacji, a może być w stanie napisać bardziej zoptymalizowany kod, ale jeśli numery są takie wysokie, że nie jestem pewien, że istnieje wiele sposób wokół mającego wiele wyników ,

Tak czy inaczej, idea kodu jest rozpocząć z ciągiem o długości 0, a następnie śledzić wszystkie ciągi o długości Z gdzie Z jest obecny rozmiar w iteracji. Następnie przejdź przez każdy ciąg i dołączyć każdy znak na każdej struny. Na koniec w celu usunięcia wszelkich które były poniżej granicy x i zwraca wynik.

Nie testowałem go z wejściem potencjalnie znaczenia (lista znak null, dziwne wartości x i y, etc).

Odpowiedział 02/08/2008 o 08:56
źródło użytkownik

głosy
7

Ruby odpowiedź, że działa:

class String
  def each_char_with_index
    0.upto(size - 1) do |index|
      yield(self[index..index], index)
    end
  end
  def remove_char_at(index)
    return self[1..-1] if index == 0
    self[0..(index-1)] + self[(index+1)..-1]
  end
end

def permute(str, prefix = '')
  if str.size == 0
    puts prefix
    return
  end
  str.each_char_with_index do |char, index|
    permute(str.remove_char_at(index), prefix + char)
  end
end

# example
# permute("abc")
Odpowiedział 20/04/2012 o 01:21
źródło użytkownik

głosy
7

przestawiać (ABC) -> A.perm (BC) -> A.perm [B.perm (c)] -> A.perm [( * B C), (C, B * )] -> [( * a BC ), (B C), (BC A * ) ( * a CB), (C B), (CB A * )] aby usunąć duplikaty po włożeniu każdej kontroli alfabetu, aby sprawdzić, czy poprzedni łańcuch kończy się tego samego alfabetu (dlaczego? -exercise)

public static void main(String[] args) {

    for (String str : permStr("ABBB")){
        System.out.println(str);
    }
}

static Vector<String> permStr(String str){

    if (str.length() == 1){
        Vector<String> ret = new Vector<String>();
        ret.add(str);
        return ret;
    }

    char start = str.charAt(0);
    Vector<String> endStrs = permStr(str.substring(1));
    Vector<String> newEndStrs = new Vector<String>();
    for (String endStr : endStrs){
        for (int j = 0; j <= endStr.length(); j++){
            if (endStr.substring(0, j).endsWith(String.valueOf(start)))
                break;
            newEndStrs.add(endStr.substring(0, j) + String.valueOf(start) + endStr.substring(j));
        }
    }
    return newEndStrs;
}

Drukuje wszystkie permutacje sans duplikaty

Odpowiedział 22/02/2011 o 19:45
źródło użytkownik

głosy
7

... i tutaj jest wersja C:

void permute(const char *s, char *out, int *used, int len, int lev)
{
    if (len == lev) {
        out[lev] = '\0';
        puts(out);
        return;
    }

    int i;
    for (i = 0; i < len; ++i) {
        if (! used[i])
            continue;

        used[i] = 1;
        out[lev] = s[i];
        permute(s, out, used, len, lev + 1);
        used[i] = 0;
    }
    return;
}
Odpowiedział 07/02/2011 o 22:56
źródło użytkownik

głosy
7

W Perl, jeśli chcesz ograniczać się do małych liter alfabetu, można to zrobić:

my @result = ("a" .. "zzzz");

To daje wszystkie możliwe ciągi między 1 a 4 znaków używając małych liter. Na wielkie litery, zmienia "a"się "A"i "zzzz"do "ZZZZ".

Do mieszanej przypadku robi się o wiele trudniejsze, a prawdopodobnie nie wykonalne z jednym z wbudowanych operatorów Perla tak.

Odpowiedział 15/02/2009 o 11:02
źródło użytkownik

głosy
7

Oto prosty słowo C # rekurencyjne rozwiązanie:

Metoda:

public ArrayList CalculateWordPermutations(string[] letters, ArrayList words, int index)
        {
            bool finished = true;
            ArrayList newWords = new ArrayList();
            if (words.Count == 0)
            {
                foreach (string letter in letters)
                {
                    words.Add(letter);
                }
            }

            for(int j=index; j<words.Count; j++)
            {
                string word = (string)words[j];
                for(int i =0; i<letters.Length; i++)
                {
                    if(!word.Contains(letters[i]))
                    {
                        finished = false;
                        string newWord = (string)word.Clone();
                        newWord += letters[i];
                        newWords.Add(newWord);
                    }
                }
            }

            foreach (string newWord in newWords)
            {   
                words.Add(newWord);
            }

            if(finished  == false)
            {
                CalculateWordPermutations(letters, words, words.Count - newWords.Count);
            }
            return words;
        }

Powołanie:

string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
Odpowiedział 20/10/2008 o 01:17
źródło użytkownik

głosy
7

Rekursywne rozwiązanie C ++

int main (int argc, char * const argv[]) {
        string s = "sarp";
        bool used [4];
        permute(0, "", used, s);
}

void permute(int level, string permuted, bool used [], string &original) {
    int length = original.length();

    if(level == length) { // permutation complete, display
        cout << permuted << endl;
    } else {
        for(int i=0; i<length; i++) { // try to add an unused character
            if(!used[i]) {
                used[i] = true;
                permute(level+1, original[i] + permuted, used, original); // find the permutations starting with this string
                used[i] = false;
            }
        }
}
Odpowiedział 29/09/2008 o 02:34
źródło użytkownik

głosy
7

Jest to tłumaczenie z wersji Ruby Mike'a, w Common Lisp:

(defun perms (x y original-string)
  (loop with all = (list "")
        with current-array = (list "")
        for iteration from 1 to y
        do (loop with next-array = nil
                 for string in current-array
                 do (loop for c across original-string
                          for value = (concatenate 'string string (string c))
                          do (push value next-array)
                             (push value all))
                    (setf current-array (reverse next-array)))
        finally (return (nreverse (delete-if #'(lambda (el) (< (length el) x)) all)))))

I kolejna wersja, nieco krótsze i przy użyciu więcej funkcji facility pętla:

(defun perms (x y original-string)
  (loop repeat y
        collect (loop for string in (or (car (last sets)) (list ""))
                      append (loop for c across original-string
                                   collect (concatenate 'string string (string c)))) into sets
        finally (return (loop for set in sets
                              append (loop for el in set when (>= (length el) x) collect el)))))
Odpowiedział 16/09/2008 o 06:15
źródło użytkownik

głosy
6

Poniższe Java rekursji drukuje wszystkie permutacje danego ciągu znaków:

//call it as permut("",str);

public void permut(String str1,String str2){
    if(str2.length() != 0){
        char ch = str2.charAt(0);
        for(int i = 0; i <= str1.length();i++)
            permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                     str2.substring(1,str2.length()));
    }else{
    System.out.println(str1);
    }
}

Poniżej znajduje się zaktualizowana wersja powyższej „PERMUTACJE” metoda, która sprawia, że ​​n! (N czynnikowych) połączenia mniej cyklicznych porównaniu z powyższym sposobem

//call it as permut("",str);

public void permut(String str1,String str2){
   if(str2.length() > 1){
       char ch = str2.charAt(0);
       for(int i = 0; i <= str1.length();i++)
          permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }else{
    char ch = str2.charAt(0);
    for(int i = 0; i <= str1.length();i++)
        System.out.println(str1.substring(0,i) + ch +    str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }
}
Odpowiedział 19/06/2013 o 05:23
źródło użytkownik

głosy
5

Oto nierekursywnych wersja wpadłem w javascript. To nie jest oparty na non-rekurencyjne jednego Knutha powyżej, choć ma pewne podobieństwa w elemencie zamiany. I zweryfikowaniu jego poprawności dla tablic wejściowych do 8 elementów.

Szybka optymalizacja będzie pre-flighting na outtablicę i unikania push().

Podstawowym założeniem jest:

  1. Biorąc pod uwagę jeden Tablica źródła, generuje pierwszy nowy zestaw matryc, które parami zamienić pierwszy element z każdego kolejnego elementu z kolei, za każdym razem, podczas gdy pozostałe elementy unperturbed. np podane 1234 generowania 1234, 2134, 3214, 4231.

  2. Używać każdą tablicę z poprzedniego przebiegu jako nasiona do nowego podaniu, lecz zamiast wymiany pierwszy element, drugi element wymiany z każdego kolejnego elementu. Również tym razem, nie zawierają oryginalną tablicę na wyjściu.

  3. Powtórz krok 2 aż do zrobienia.

Oto przykładowy kod:

function oxe_perm(src, depth, index)
{
    var perm = src.slice();     // duplicates src.
    perm = perm.split("");
    perm[depth] = src[index];
    perm[index] = src[depth];
    perm = perm.join("");
    return perm;
}

function oxe_permutations(src)
{
    out = new Array();

    out.push(src);

    for (depth = 0; depth < src.length; depth++) {
        var numInPreviousPass = out.length;
        for (var m = 0; m < numInPreviousPass; ++m) {
            for (var n = depth + 1; n < src.length; ++n) {
                out.push(oxe_perm(out[m], depth, n));
            }
        }
    }

    return out;
}
Odpowiedział 03/08/2011 o 08:11
źródło użytkownik

głosy
5
import java.util.*;

public class all_subsets {
    public static void main(String[] args) {
        String a = "abcd";
        for(String s: all_perm(a)) {
            System.out.println(s);
        }
    }

    public static Set<String> concat(String c, Set<String> lst) {
        HashSet<String> ret_set = new HashSet<String>();
        for(String s: lst) {
            ret_set.add(c+s);
        }
        return ret_set;
    }

    public static HashSet<String> all_perm(String a) {
        HashSet<String> set = new HashSet<String>();
        if(a.length() == 1) {
            set.add(a);
        } else {
            for(int i=0; i<a.length(); i++) {
                set.addAll(concat(a.charAt(i)+"", all_perm(a.substring(0, i)+a.substring(i+1, a.length()))));
            }
        }
        return set;
    }
}
Odpowiedział 24/10/2010 o 23:01
źródło użytkownik

głosy
4

Nie jestem pewien, dlaczego chcesz to zrobić w pierwszej kolejności. Uzyskany zestaw za umiarkowanie duże wartości x i y będą ogromne, i będzie rosnąć wykładniczo jako x i / lub y stają się coraz większe.

Powiedzmy, że Twój zestaw możliwych znaków jest 26 małych liter alfabetu, i poprosić swoją aplikację do generowania wszystkich permutacji gdzie długość = 5. Zakładając, że nie zabraknie pamięci dostaniesz 11,881,376 (czyli 26 do potęgi 5) sznury tylne. Bump tej długości do 6, a dostaniesz 308,915,776 ciągi powrotem. Numery te boleśnie dostać duży, bardzo szybko.

Oto rozwiązanie ułożyła w Javie. Musisz dostarczyć dwa argumenty uruchomieniowe (odpowiadające X i Y). Baw się dobrze.

public class GeneratePermutations {
    public static void main(String[] args) {
        int lower = Integer.parseInt(args[0]);
        int upper = Integer.parseInt(args[1]);

        if (upper < lower || upper == 0 || lower == 0) {
            System.exit(0);
        }

        for (int length = lower; length <= upper; length++) {
            generate(length, "");
        }
    }

    private static void generate(int length, String partial) {
        if (length <= 0) {
            System.out.println(partial);
        } else {
            for (char c = 'a'; c <= 'z'; c++) {
                generate(length - 1, partial + c);
            }
        }
    }
}
Odpowiedział 02/08/2008 o 10:40
źródło użytkownik

głosy
3

Musiałem to dzisiaj, i chociaż już udzielone odpowiedzi wskazał mnie we właściwym kierunku, nie były one całkiem to, czego chciałem.

Oto implementacja przy użyciu metody sterty. Długość tablicy musi mieć co najmniej 3 i względów praktycznych nie może być większa niż 10 lub więcej, w zależności od tego, co chcesz zrobić, cierpliwości i taktowanie.

Przed wprowadzeniem pętli zainicjować Perm(1 To N)z pierwszym permutacji, Stack(3 To N)z zer * oraz Levelz 2**. Pod koniec rozmowy pętli NextPerm, która będzie return false kiedy skończymy.

* VB zrobi to za Ciebie.

** Można zmienić NextPerm trochę, aby to niepotrzebne, ale to bardziej przejrzyste jak ten.

Option Explicit

Function NextPerm(Perm() As Long, Stack() As Long, Level As Long) As Boolean
Dim N As Long
If Level = 2 Then
    Swap Perm(1), Perm(2)
    Level = 3
Else
    While Stack(Level) = Level - 1
        Stack(Level) = 0
        If Level = UBound(Stack) Then Exit Function
        Level = Level + 1
    Wend
    Stack(Level) = Stack(Level) + 1
    If Level And 1 Then N = 1 Else N = Stack(Level)
    Swap Perm(N), Perm(Level)
    Level = 2
End If
NextPerm = True
End Function

Sub Swap(A As Long, B As Long)
A = A Xor B
B = A Xor B
A = A Xor B
End Sub

'This is just for testing.
Private Sub Form_Paint()
Const Max = 8
Dim A(1 To Max) As Long, I As Long
Dim S(3 To Max) As Long, J As Long
Dim Test As New Collection, T As String
For I = 1 To UBound(A)
    A(I) = I
Next
Cls
ScaleLeft = 0
J = 2
Do
    If CurrentY + TextHeight("0") > ScaleHeight Then
        ScaleLeft = ScaleLeft - TextWidth(" 0 ") * (UBound(A) + 1)
        CurrentY = 0
        CurrentX = 0
    End If
    T = vbNullString
    For I = 1 To UBound(A)
        Print A(I);
        T = T & Hex(A(I))
    Next
    Print
    Test.Add Null, T
Loop While NextPerm(A, S, J)
J = 1
For I = 2 To UBound(A)
    J = J * I
Next
If J <> Test.Count Then Stop
End Sub

Inne metody są opisane przez różnych autorów. Knuth opisuje dwóch, porządkuje leksykograficznego, ale jest złożone i powolne, a druga jest znana jako metoda płaskich zmian. Jie Gao i Dianjun Wang napisał również ciekawy papier.

Odpowiedział 02/10/2011 o 10:13
źródło użytkownik

głosy
2

Tu jest link, który opisuje, jak drukować permutacji ciąg. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html

Odpowiedział 13/02/2014 o 22:08
źródło użytkownik

głosy
2

Ten kod w Pythonie, gdy wywołana z allowed_characterszestawu do [0,1]i 4 znaków max, by wygenerować 2 ^ 4 wyniki:

['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']

def generate_permutations(chars = 4) :

#modify if in need!
    allowed_chars = [
        '0',
        '1',
    ]

    status = []
    for tmp in range(chars) :
        status.append(0)

    last_char = len(allowed_chars)

    rows = []
    for x in xrange(last_char ** chars) :
        rows.append("")
        for y in range(chars - 1 , -1, -1) :
            key = status[y]
            rows[x] = allowed_chars[key] + rows[x]

        for pos in range(chars - 1, -1, -1) :
            if(status[pos] == last_char - 1) :
                status[pos] = 0
            else :
                status[pos] += 1
                break;

    return rows

import sys


print generate_permutations()

Nadzieję, że to przydatne dla Ciebie. Współpracuje z dowolnym charakterze, nie tylko numery

Odpowiedział 26/05/2011 o 15:22
źródło użytkownik

głosy
2

W Ruby:

str = "a"
100_000_000.times {puts str.next!}

Jest to dość szybko, ale to zajmie trochę czasu =). Oczywiście, można rozpocząć w „AAAAAAAA” czy krótkie łańcuchy nie są interesujące dla ciebie.

Mógłbym błędnie interpretowane rzeczywiste pytanie chociaż - w jednym z postów Brzmiało to tak, jakby po prostu potrzebne biblioteki Bruteforce ciągów, ale główne pytanie brzmi jak trzeba permutate konkretny łańcuch.

Twój problem jest nieco podobny do tego: http://beust.com/weblog/archives/000491.html (lista wszystkich liczb całkowitych, w którym żadna z cyfr powtarzają się, co spowodowało całe mnóstwo języków go rozwiązać, z ocaml facet za pomocą permutacji, a niektóre java facet używając kolejnego rozwiązania).

Odpowiedział 15/09/2008 o 18:32
źródło użytkownik

głosy
0

Możliwych permutacji ciąg znaków może być obliczany za pomocą funkcji rekurencyjnej. Poniżej jest jednym z możliwych rozwiązań.

public static String insertCharAt(String s, int index, char c) {
        StringBuffer sb = new StringBuffer(s);
        StringBuffer sbb = sb.insert(index, c);
        return sbb.toString();
}

public static ArrayList<String> getPerm(String s, int index) {
        ArrayList<String> perm = new ArrayList<String>();

        if (index == s.length()-1) {
            perm.add(String.valueOf(s.charAt(index)));
            return perm;
        }

        ArrayList<String> p = getPerm(s, index+1);
        char c = s.charAt(index);

        for(String pp : p) {
            for (int idx=0; idx<pp.length()+1; idx++) {
                String ss = insertCharAt(pp, idx, c);
                perm.add(ss);
            }
        }

        return perm;    
}

public static void testGetPerm(String s) {
        ArrayList<String> perm = getPerm(s,0);
        System.out.println(s+" --> total permutation are :: "+perm.size());
        System.out.println(perm.toString());
}
Odpowiedział 06/02/2017 o 06:00
źródło użytkownik

głosy
0

Kod napisany w języku Java:

namo.algorithms opakowania;

importu java.util.Scanner;

{public class Permuations

public static int totalPermutationsCount = 0;
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("input string : ");
        String inputString = sc.nextLine();
        System.out.println("given input String ==> "+inputString+ " :: length is = "+inputString.length());
        findPermuationsOfString(-1, inputString);
        System.out.println("**************************************");
        System.out.println("total permutation strings ==> "+totalPermutationsCount);
    }


    public  static void findPermuationsOfString(int fixedIndex, String inputString) {
        int currentIndex = fixedIndex +1;

        for (int i = currentIndex; i < inputString.length(); i++) {
            //swap elements and call the findPermuationsOfString()

            char[] carr = inputString.toCharArray();
            char tmp = carr[currentIndex];
            carr[currentIndex] = carr[i];
            carr[i] = tmp;
            inputString =  new String(carr);

            //System.out.println("chat At : current String ==> "+inputString.charAt(currentIndex));
            if(currentIndex == inputString.length()-1) {
                totalPermutationsCount++;
                System.out.println("permuation string ==> "+inputString);
            } else {
                //System.out.println("in else block>>>>");
                findPermuationsOfString(currentIndex, inputString);
                 char[] rarr = inputString.toCharArray();
                    char rtmp = carr[i];
                    carr[i] = carr[currentIndex];
                    carr[currentIndex] = rtmp;
                    inputString =  new String(carr);
            }
        }
    }

}

Odpowiedział 05/06/2016 o 08:42
źródło użytkownik

głosy
0

Więc tutaj jest elegancki, nierekursywnych, O (n!) Rozwiązanie:

public static StringBuilder[] permutations(String s) {
        if (s.length() == 0)
            return null;
        int length = fact(s.length());
        StringBuilder[] sb = new StringBuilder[length];
        for (int i = 0; i < length; i++) {
            sb[i] = new StringBuilder();
        }
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            int times = length / (i + 1);
            for (int j = 0; j < times; j++) {
                for (int k = 0; k < length / times; k++) {
                    sb[j * length / times + k].insert(k, ch);
                }
            }
        }
        return sb;
    }
Odpowiedział 27/06/2015 o 08:44
źródło użytkownik

głosy
0

Pythonic rozwiązanie:

from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
Odpowiedział 13/07/2014 o 08:51
źródło użytkownik

głosy
0
def permutation(str)
  posibilities = []
  str.split('').each do |char|
    if posibilities.size == 0
      posibilities[0] = char.downcase
      posibilities[1] = char.upcase
    else
      posibilities_count = posibilities.length
      posibilities = posibilities + posibilities
      posibilities_count.times do |i|
        posibilities[i] += char.downcase
        posibilities[i+posibilities_count] += char.upcase
      end
    end
  end
  posibilities
end

Oto moje zdanie na brak wersji rekurencyjnej

Odpowiedział 23/01/2014 o 04:28
źródło użytkownik

głosy
0

Rozwiązanie rekurencyjne z kierowcą main()metody.

public class AllPermutationsOfString {
public static void stringPermutations(String newstring, String remaining) {
    if(remaining.length()==0)
        System.out.println(newstring);

    for(int i=0; i<remaining.length(); i++) {
        String newRemaining = remaining.replaceFirst(remaining.charAt(i)+"", "");
        stringPermutations(newstring+remaining.charAt(i), newRemaining);
    }
}

public static void main(String[] args) {
    String string = "abc";
    AllPermutationsOfString.stringPermutations("", string); 
}

}

Odpowiedział 19/10/2013 o 02:34
źródło użytkownik

głosy
0
def gen( x,y,list): #to generate all strings inserting y at different positions
list = []
list.append( y+x )
for i in range( len(x) ):
    list.append( func(x,0,i) + y + func(x,i+1,len(x)-1) )
return list 

def func( x,i,j ): #returns x[i..j]
z = '' 
for i in range(i,j+1):
    z = z+x[i]
return z 

def perm( x , length , list ): #perm function
if length == 1 : # base case
    list.append( x[len(x)-1] )
    return list 
else:
    lists = perm( x , length-1 ,list )
    lists_temp = lists #temporarily storing the list 
    lists = []
    for i in range( len(lists_temp) ) :
        list_temp = gen(lists_temp[i],x[length-2],lists)
        lists += list_temp 
    return lists
Odpowiedział 22/08/2013 o 18:51
źródło użytkownik

głosy
0

Cykliczna rozwiązaniem pytona. Dobrą rzeczą jest to, że ten kod eksportuje słownika, z klawiszami jak łańcuchów i wszystkich możliwych permutacji jako wartości. Wszystkie możliwe długości strun są włączone, więc w efekcie, tworzysz rozszerzeniem.

Jeśli tylko wymagają ostatecznego permutacje, można usunąć inne klucze ze słownika.

W tym kodzie słownika permutacji jest globalny.

W przypadku bazowego, przechowywać wartości jako obu możliwości w postaci listy. perms['ab'] = ['ab','ba'],

W przypadku większych długości ciągów funkcja dotyczy niższych długości ciągów i obejmuje wcześniej obliczone permutacji.

Funkcja robi dwie rzeczy:

  • zwraca się z mniejszym ciągiem
  • zwraca listę permutacji określonego ciągu znaków, jeżeli już dostępne. Jeśli zwrócone do siebie, które zostaną wykorzystane do dołączania do charakteru i stworzyć nowsze permutacji.

Kosztowne dla pamięci.

perms = {}
def perm(input_string):
    global perms
    if input_string in perms:
        return perms[input_string] # This will send a list of all permutations
    elif len(input_string) == 2:
        perms[input_string] = [input_string, input_string[-1] + input_string [-2]]
        return perms[input_string]
    else:
        perms[input_string] = []
        for index in range(0, len(input_string)):
            new_string = input_string[0:index] + input_string[index +1:]
            perm(new_string)
            for entries in perms[new_string]:
                perms[input_string].append(input_string[index] + entries)
    return perms[input_string]
Odpowiedział 05/07/2013 o 05:15
źródło użytkownik

głosy
0

Jest iteracyjny implementacja Javy w UncommonsMaths (działa na listę obiektów):

/**
 * Generate the indices into the elements array for the next permutation. The
 * algorithm is from Kenneth H. Rosen, Discrete Mathematics and its 
 * Applications, 2nd edition (NY: McGraw-Hill, 1991), p. 284)
 */
private void generateNextPermutationIndices()
{
    if (remainingPermutations == 0)
    {
        throw new IllegalStateException("There are no permutations " +
             "remaining. Generator must be reset to continue using.");
    }
    else if (remainingPermutations < totalPermutations)
    {
        // Find largest index j with 
        // permutationIndices[j] < permutationIndices[j + 1]
        int j = permutationIndices.length - 2;
        while (permutationIndices[j] > permutationIndices[j + 1])
        {
            j--;
        }

        // Find index k such that permutationIndices[k] is smallest integer 
        // greater than permutationIndices[j] to the right
        // of permutationIndices[j].
        int k = permutationIndices.length - 1;
        while (permutationIndices[j] > permutationIndices[k])
        {
            k--;
        }

        // Interchange permutation indices.
        int temp = permutationIndices[k];
        permutationIndices[k] = permutationIndices[j];
        permutationIndices[j] = temp;

        // Put tail end of permutation after jth position in increasing order.
        int r = permutationIndices.length - 1;
        int s = j + 1;

        while (r > s)
        {
            temp = permutationIndices[s];
            permutationIndices[s] = permutationIndices[r];
            permutationIndices[r] = temp;
            r--;
            s++;
        }
    }
    --remainingPermutations;
}

/**
 * Generate the next permutation and return a list containing
 * the elements in the appropriate order.  This overloaded method
 * allows the caller to provide a list that will be used and returned.
 * The purpose of this is to improve performance when iterating over
 * permutations.  If the {@link #nextPermutationAsList()} method is
 * used it will create a new list every time.  When iterating over
 * permutations this will result in lots of short-lived objects that
 * have to be garbage collected.  This method allows a single list
 * instance to be reused in such circumstances.
 * @param destination Provides a list to use to create the
 * permutation.  This is the list that will be returned, once
 * it has been filled with the elements in the appropriate order.
 * @return The next permutation as a list.
 */
public List<T> nextPermutationAsList(List<T> destination)
{
    generateNextPermutationIndices();
    // Generate actual permutation.
    destination.clear();
    for (int i : permutationIndices)
    {
        destination.add(elements[i]);
    }
    return destination;
}

Pełna źródło

Odpowiedział 07/05/2013 o 02:18
źródło użytkownik

głosy
0

c # iteracyjny:

public List<string> Permutations(char[] chars)
    {
        List<string> words = new List<string>();
        words.Add(chars[0].ToString());
        for (int i = 1; i < chars.Length; ++i)
        {
            int currLen = words.Count;
            for (int j = 0; j < currLen; ++j)
            {
                var w = words[j];
                for (int k = 0; k <= w.Length; ++k)
                {
                    var nstr = w.Insert(k, chars[i].ToString());
                    if (k == 0)
                        words[j] = nstr;
                    else
                        words.Add(nstr);
                }
            }
        }
        return words;
    }
Odpowiedział 26/07/2012 o 16:20
źródło użytkownik

głosy
0

Chociaż to nie jest odpowiedź na Twoje pytanie dokładnie, tutaj jest jeden sposób, aby generować każdy permutacji liter z wielu łańcuchów o tej samej długości: na przykład, jeśli twoje słowa były „kawa”, „joomla” i „moodle”, można oczekiwać wyjścia jak "coodle", "joodee", "joffle", etc.

Zasadniczo, liczba kombinacji jest (liczba słów) do potęgi (liczba liter w słowie). Więc wybrać losową liczbę między 0 i liczbę kombinacji - 1, przekształcić tę liczbę do bazy (liczba słów), a następnie użyć każdą cyfrę tej liczby jako wskaźnik dla których słowo aby wykonać kolejny list.

np w powyższym przykładzie. 3, 6 liter słowa = 729 kombinacje. Wybierz liczbę losową: 465. Konwersja do podstawy 3: 122020. Weź pierwszą literę słowa z 1, 2 z 2, 3 słowa ze słowem 2, 4 od słowa 0 ... i masz ... „joofle”.

Jeśli chciałeś wszystkie permutacje, tylko pętlę od 0 do 728. Oczywiście, jeśli jesteś po prostu wybierając jedną wartość losową, o wiele prostsze mniej mylące sposobem byłoby pętli nad literami. Metoda ta pozwala uniknąć rekursji powinna chcesz wszystkie permutacje, plus to sprawia, że wyglądają jak wiesz matematyki (tm) !

Jeśli liczba kombinacji jest zbyt duża, można podzielić ją na szereg mniejszych słów i złączyć je na końcu.

Odpowiedział 16/09/2008 o 06:33
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more