置换字符串直到它匹配一些输入?

Permute string until it matches some input?

我在网上查了一下,没有太多结果,因为很难用几句话来描述。

基本上,我需要一个函数,比如说 puntil,它接受参数 string。基本上,函数置换直到字符串等于参数。

例如,如果你 运行 puntil('ab') 它应该在函数内部执行:

一个 b C d 电子 F G H 一世 j k 升 米 n o p q r 秒 吨 你 v w X 是 z 一个 ab!!比赛

另一个例子,对于puntil('abcd')它会做

一个 b C d 电子 F G H 一世 j k 升 米 n o p q r 秒 吨 你 v w X 是 z 一个 ab 交流电 广告 ae 自动对焦 银 啊 艾 杰 啊 阿尔 是 一个 奥 应用程序 水 ar 作为 在 金 影音 哇 斧头 哎呀 阿兹

...等等等等.. 直到它匹配 abcd。

基本上是一个无限排列直到它匹配。

有什么想法吗?

OP 的要求有点模棱两可,所以我 post OP 要求的两件事(我怀疑)。

首先,问题可能是,输入字符串在字母表的无限排列中的位置是什么(我认为这是更合理的问题,稍后我会给出原因)。这可以通过以下方式完成:

举个例子(输入=dhca)。因此,所有长度为 1 到 3 个字符的字符串都将出现在该字符串之前。因此,在答案中添加:26^1 + 26^2 + 26^3。然后,第一个字符是d,这意味着,按照字典,如果第一个字符是a | b | c,则所有字符都是有效的。因此,将 3 * 26^3 添加到答案中。现在,假设第一个字符是 d。然后,我们可以得到 a to g (7) 中的所有字符,最后 2 个字符可以是任何字符。因此,将 7 * 26^2 添加到答案中。这样下去,我们得到的答案是:

26^1 + 26^2 + 26^3 + (3 * 26^3) + (7 * 26^2) + (2 * 26^1) + (0) + 1
= 75791

好的。现在是第二件事,我认为 OP 实际上是在问(在我们获得匹配之前打印所有字符串)。现在,为什么我认为这是不可行的,因为如果我们输入 zzzzz(5 个字符长),我们需要打印 26^1 + 26^2 + 26^3 + 26^4 + 26^5 个字符串,即 12356630。因此,对于这部分,我假设输入字符串的最大长度为 5(绝对不会更多),因为对于 6 个字符长度的字符串,我们需要打印 ~321272406 个字符串 --> 不可能。

因此,一个简单的解决方案可以是:

  • 创建一个大小为 27 的数组:arr[] = {'', 'a', 'b', ..., 'y', 'z'}。第一个字符为空。
  • 从 0 到 26(含)写入 5(最大字符串长度)嵌套循环并将其添加到虚拟字符串并打印。有点像。

    for i from 0 to 26
        String a = "" + arr[i]
        for j from 0 to 26
            String b = a + arr[j]
            for k from 0 to 26
                String c = b + arr[k]
                for l from 0 to 26
                    String d = c + arr[l]
                    for m from 0 to 26
                        String e = d + arr[m]
                        print e
                        if(e equals input string)
                            break from all loops //use some flag, goto statement etc.
    

Fiddle here

function next(charArray, rightBound){

    if(!rightBound){
        rightBound = charArray.length;
    }

    var oldValue = charArray[rightBound-1];
    var newValue = nextCharacter(charArray[rightBound-1]);
    charArray[rightBound-1] = newValue;

    if(newValue < oldValue){
        if(rightBound > 1){
            next(charArray, rightBound-1);
        }
        else{
            charArray.push('a');
        }
    }
    return charArray;
}

function nextCharacter(char){
    if(char === 'z'){
        return 'a'
    }
    else{
        return String.fromCharCode(char.charCodeAt(0) + 1)
    }
}

function permuteUntil(word){
    var charArray = ['a'];
    var wordChain = ['a'];

    while(next(charArray).join('') !== word){
        wordChain.push(charArray.join(''));
    }

    wordChain.push(word);

    return wordChain.join(', ');
}


alert(permuteUntil('ab'));

您要求更优雅的解决方案,这里有一个简单的函数,可将整数转换为小写字符串,使您可以轻松地遍历字符串。

function toWord(val, first, out) {
if(first == 1)
    out = String.fromCharCode(97 + val % 26) + out;
else
    out = String.fromCharCode(97 + (val-1) % 26) + out;
if(val % 26 == 0 && first == 0) {
    val -= 26;
}
else {
    val -= val %26;
}
val = val / 26;
if(val != 0)
    return toWord(val, 0, out);
else
    return out;
}

它绝不是完美的,但它简短而简单。调用函数时设置 val 为要转换的整数,首先为 1,输出为 "".

例如,以下内容会将 yourFunction 应用于前 10,000 个小写字符串

for(int i=0; i<10000; i++) {
    youFunction(toWord(i, 1, ""));
}

所以您需要始终从 a 开始递增?由于它们是 char 值,您可以使用以下结构轻松地做到这一点:

请注意,这是一个 java 解决方案:)

public static char[] increment(char[] arr, int pos) {
    // get current position char
    char currentChar = arr[pos];

    // increment it by one
    currentChar++;

    // if it is at the end of it's range
    boolean overflow = false;
    if (currentChar > 'Z') {
        overflow = true;
        currentChar = 'A';
    }

    // always update current char
    arr[pos] = currentChar;
    if (overflow) {
        if (pos == 0) {
            // resize array and add new character
            char[] newArr = new char[arr.length + 1];
            System.arraycopy(arr, 0, newArr, 0, arr.length);
            newArr[arr.length] = 'A';

            arr = newArr;
        } else {
            // overflowed, increment one position back
            arr = increment(arr, pos - 1);
        }
    }

    return arr;
}


public static void main(String[] args) {
    final String stringToUse = "A";
    final String stringToSearch = "ABCD";

    char[] use = stringToUse.toCharArray();
    for (;;) {
        final String result = new String(use);

        System.out.println("Candidate: " + result);
        if (stringToSearch.equals(result)) {
            System.out.println("Found!");
            break;
        }

        use = increment(use, use.length - 1);
    }
}

这是fiddle

 var alphabet = ['a','b','c'];//,'d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];

 var output = "";
 var match = "cccc";  //<----------- match here

//This is your main function 
function permutate() {

    var d = 0;   // d for depth

    while (true) {

       //Your main alphabet iteration             
       for (var i=0; i<alphabet.length; i++){

          //First level 
          if (d === 0) {
             console.log(alphabet[i])
             output = alphabet[i];
          }    
          else
             iterator(alphabet[i], d);   //Call iterator for d > 0

          if (output === match)
             return;
          }


          d++;  //Increase the depth
       }
 }


 //This function runs n depths of iterations
 function iterator(s, depth){

    if (depth === 0)
       return;

    for (var i=0; i<alphabet.length; i++){

       if (depth > 1)
          iterator(s + alphabet[i], depth - 1)
       else {
          console.log(s + alphabet[i]);
          output = s + alphabet[i];
       } 

       if (output === match)
          return;
    }

 };                

解释:

你的程序需要像这样遍历字母表树

[a] 
    -[a]
        -[a] 
             -[a]...
             -[b]...

         [b] ...
    -[b] -
         -[a]...
         -[b]...

[b] - ...
[c] - ...

如果不是因为您需要先完成每个深度的要求,这可以通过传统的递归函数轻松完成。

所以我们需要一个特殊的 iterator(s, depth) 函数,它可以执行请求的嵌套迭代次数(深度)。

所以主函数可以调用深度递增的迭代器(d++)。

就这些了!!

警告:这只是原型。这是可以优化和改进的。它使用全局变量以便于演示。您的真实程序应该避免使用全局变量。如果您的匹配词太长,我还建议在 setTimeout 中调用 iterator()n 深度只能受限于你的资源。