String 生成字符串的所有可能排列的列表

String 生成字符串的所有可能排列的列表,string,language-agnostic,cross-platform,String,Language Agnostic,Cross Platform,如何生成长度介于x和y字符之间的字符串的所有可能排列的列表,其中包含一个可变的字符列表 任何语言都可以,但它应该是可移植的。有几种方法可以做到这一点。常用方法使用递归、记忆或动态编程。基本思想是生成一个长度为1的所有字符串的列表,然后在每次迭代中,对于上一次迭代中生成的所有字符串,分别添加与字符串中每个字符连接的字符串。(下面代码中的变量索引跟踪上一次迭代和下一次迭代的开始) 一些伪代码: list = originalString.split('') index = (0,0) list =

如何生成长度介于x和y字符之间的字符串的所有可能排列的列表,其中包含一个可变的字符列表


任何语言都可以,但它应该是可移植的。

有几种方法可以做到这一点。常用方法使用递归、记忆或动态编程。基本思想是生成一个长度为1的所有字符串的列表,然后在每次迭代中,对于上一次迭代中生成的所有字符串,分别添加与字符串中每个字符连接的字符串。(下面代码中的变量索引跟踪上一次迭代和下一次迭代的开始)

一些伪代码:

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)

然后,您需要删除所有长度小于x的字符串,它们将是列表中的第一个(x-1)*len(originalString)项。

我刚刚在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
def perms(x,y,可能的_字符)
全部=[“”]
当前_数组=all.clone
1.高达(y){迭代|
下一个数组=[]
当前_数组。每个{124;字符串|
可能的_字符。每个{124; c|
value=string+c
下一个数组。插入下一个数组。长度,值
all.insert all.length、value
}
}
当前数组=下一个数组
}
如果{| string | string.length
您可能会研究内置置换类型函数的语言API,您可能会编写更优化的代码,但如果数量如此之多,我不确定有多少方法可以获得大量结果

无论如何,代码背后的想法是从长度为0的字符串开始,然后跟踪所有长度为Z的字符串,其中Z是迭代中的当前大小。然后,遍历每个字符串并将每个字符附加到每个字符串上。最后,删除所有低于x阈值的项并返回结果


我没有使用可能毫无意义的输入(空字符列表、奇怪的x和y值等)来测试它。

我不知道您为什么首先要这样做。任何中等大小的x和y值的结果集都将是巨大的,并且会随着x和/或y变大而呈指数增长

假设您的可能字符集是字母表中的26个小写字母,您要求应用程序生成长度为5的所有排列。假设你没有用完内存,你会得到11881376(即26的5次方)字符串。将该长度增加到6,您将获得308915776个字符串。这些数字很快就变得非常庞大

下面是我用Java编写的一个解决方案。您需要提供两个运行时参数(对应于x和y)。玩得开心

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);
            }
        }
    }
}
公共类生成项{
公共静态void main(字符串[]args){
int lower=Integer.parseInt(args[0]);
int upper=Integer.parseInt(args[1]);
如果(上<下| |上==0 | |下==0){
系统出口(0);
}

对于(int-length=lower;length您将获得大量字符串,这是肯定的


其中x和y是定义它们的方式,r是我们从中选择的字符数——如果我理解正确的话。你应该根据需要生成它们,而不是草率地说,生成一个powerset,然后过滤字符串的长度

下面的内容肯定不是生成这些内容的最佳方式,但它仍然是一个有趣的旁白

Knuth(第4卷,第2分册,7.2.1.3)告诉我们,(s,t)-组合相当于一次取t的s+1事物的重复-(s,t)-组合是Knuth使用的表示法,它等于。我们可以通过首先以二进制形式生成每个(s,t)-组合(长度为(s+t))并计算每个1左边0的数量

1000011101-->成为ruby中的置换:{0,3,4,4,4,1}

str = "a"
100_000_000.times {puts str.next!}
它相当快,但需要一些时间(当然,如果短字符串对您不感兴趣,您可以从“aaaaaaaa”开始

不过,我可能误解了实际的问题——在其中一篇文章中,它听起来好像你只需要一个bruteforce字符串库,但在主要问题中,它听起来像你需要排列一个特定的字符串


您的问题与此类似:(列出所有整数,其中没有一个数字重复,这导致许多语言解决了这个问题,ocaml使用排列,而java使用另一种解决方案)。

这是Mike的Ruby版本到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)))))

虽然这并不能准确回答您的问题,但有一种方法可以从许多相同长度的字符串中生成字母的每个排列:例如,如果您的单词是“coffee”、“joomla”和“moodle”,您可以期望输出“coodle”、“joodee”、“joffle”等

基本上,组合数是(单词数)到(每个单词的字母数)的幂。因此,在0和组合数-1之间选择一个随机数,将该数字转换为基数(单词数),然后使用该数字的每个数字作为从中提取下一个字母的指标

在上面的例子中,3个单词,6个字母=729个组合。选择一个随机数:465。转换为基数3:122020。从单词1中取第一个字母,从单词2中取第二个字母,从单词2中取第三个字母,从单词0中取第四个字母……然后你得到了……“joofle”

如果你想要所有的排列,只需从0循环到728。当然,如果你只是选择一个随机值,一个简单得多、不那么混乱的方法就是循环字母。如果你想要所有的排列,这个方法可以避免递归,而且它让你看起来像懂数学(tm)

如果组合的数量过多,您可以将其分解为一系列较小的单词,并在末尾将它们连接起来。

中的递归解决方案
(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)))))
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;
            }
        }
}
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;
        }
string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
my @result = ("a" .. "zzzz");
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);
    }
}
    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;
        }
    }
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;
    }
}
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)
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;
}
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;
}
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()
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;
}
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")
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;
    }
//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);
    }
}
//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()));
   }
}
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
#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;
    });
}
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
from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
class Permutation {

    /* runtime -O(n) for generating nextPermutaion
     * and O(n*n!) for generating all n! permutations with increasing sorted array as start
     * return true, if there exists next lexicographical sequence
     * e.g [a,b,c],3-> true, modifies array to [a,c,b]
     * e.g [c,b,a],3-> false, as it is largest lexicographic possible */
    public static boolean nextPermutation(char[] seq, int len) {
        // 1
        if (len <= 1)
            return false;// no more perm
        // 2: Find last j such that seq[j] <= seq[j+1]. Terminate if no such j exists
        int j = len - 2;
        while (j >= 0 && seq[j] >= seq[j + 1]) {
            --j;
        }
        if (j == -1)
            return false;// no more perm
        // 3: Find last l such that seq[j] <= seq[l], then exchange elements j and l
        int l = len - 1;
        while (seq[j] >= seq[l]) {
            --l;
        }
        swap(seq, j, l);
        // 4: Reverse elements j+1 ... count-1:
        reverseSubArray(seq, j + 1, len - 1);
        // return seq, add store next perm

        return true;
    }
    private static void swap(char[] a, int i, int j) {
        char temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    private static void reverseSubArray(char[] a, int lo, int hi) {
        while (lo < hi) {
            swap(a, lo, hi);
            ++lo;
            --hi;
        }
    }
    public static void main(String[] args) {
        String str = "abcdefg";
        char[] array = str.toCharArray();
        Arrays.sort(array);
        int cnt=0;
        do {
            System.out.println(new String(array));
            cnt++;
        }while(nextPermutation(array, array.length));
        System.out.println(cnt);//5040=7!
    }
    //if we use "bab"-> "abb", "bab", "bba", 3(#permutations)
}