确定性地在C中生成强力排列

时间:2017-10-25 05:58:28

标签: c algorithm hash permutation

我正在用C编写一个暴力破解者。

出于显而易见的原因,我想生成任意符号的排列。但是,我还希望能够“重新启动”从给定点生成排列;即它需要是可序列化的或确定性的(不确定这个词是什么)。

因此,例如,如果符号只是a-z,它看起来像这样:

perm(1)  => 'a'
perm(2)  => 'b'
perm(27) => 'aa'
perm(28) => 'ab'

等等。

不幸的是我对c不太熟悉,所以解决这个问题有点棘手。我想我想计算当前排列中的字符数 - 让我们说我们试图找到'aa'之后的下一个排列。由于我们有两个字符,我们首先除以26 ^ 1 = 26,并发现我们可以用一个余数除一次。这意味着最左边的字符应该是a,最右边的字符应该是+ 1 = b,给我们'ab'。然而这有点棘手:如果我们以“az”开头,我们需要转换为“ba”,如果我们以“zz”开头,我们需要转换为“aaa”。

如果没有要求能够从给定点开始,我只会使用一堆for循环。

我的数据类型是一个char *,所以在我们需要添加一个新字符来查找下一个排列的情况下,这是否意味着我们需要为char *分配新的内存(因为它获得了一个字符)? / p>

感谢您的帮助

2 个答案:

答案 0 :(得分:-1)

据我所知,你想要一个字符串并添加1,以便' +1导致' b'和' +1' +1导致' a'和下一个数字的载体。如果没有"下一个数字",您需要一个值为' a'的新数字。

它可以通过多种方式实现。下面的方法就像一个简单的波纹载波添加。

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

#define MAX 100

void nextValue(char* current)
{
    char a[MAX] = { 0 };
    size_t len = strlen(current);
    if (len >= MAX-1)
    {
        printf("Input too long\n");
        exit(1);
    }
    size_t i;
    char carry = 1;
    for(i=0; i<len;++i)
    {
        char temp = carry+current[len-1-i];
        if (temp > 'z')
        {
            carry = 1;
            a[i] = 'a';
        }
        else
        {
            carry = 0;
            a[i] = temp;
        }

    }
    if (carry)
    {
        a[i] = 'a';
    }

    len = strlen(a);
    for(i=0; i<len;++i)
    {
        current[i] = a[len-1-i];
    }

}

int main(void) {
    char p[MAX] = "az";
    printf("%s\n", p);
    nextValue(p);
    printf("%s\n", p);
    return 0;
}

另一种方法 - 也许是表现更好的方法 - 是检查&#39; z&#39;的输入字符串。从最后一个角色开始。只有在所有字符都是&#39; z&#39;时,才需要插入&#39; a&#39;在前。类似的东西:

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

#define MAX 100

void nextValue(char* current)
{
    size_t len = strlen(current);
    size_t i = len - 1;
    while(i > 0 && current[i] == 'z')
    {
      current[i] = 'a';
      --i;
    }
    if (i > 0 || current[0] != 'z')
    {
      ++current[i];
      return;
    }
    current[0] = 'a';

    if (len == MAX-1)
    {
      // No more space
      return;
    }

    // Place a new 'a' in front of current
    memmove(current+1, current, len+1);
    current[0] = 'a';
}

int main(void) {
    char p[MAX] = "zz";
    printf("%s\n", p);
    nextValue(p);
    printf("%s\n", p);
    return 0;
}

答案 1 :(得分:-1)

不完全符合您的要求,但它完成了工作。它将(给定足够的时间)用字母a-z产生所有可能的字符串。它也符合您的要求,能够在您停止的地方继续。但是,您将无法从中重新启动它。你必须使用字符串。

这是一种非常快速的方法。既然你提到你想把它用于蛮力,那么比将数字转换为字符串要好得多。在大多数情况下(96%),唯一的操作是递增一个字符。

s

它需要一个字符串char s[30]="a"; for(int i=0; i<100; i++) { printf("%s ", s); next(s); } 并假设它在表单上以任意数量的字母a-z开头,然后用零填充。没有进行错误检查。

我用这个主要测试了它:

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 aa ba ca da ea fa ga ha ia ja ka la ma na oa pa qa ra sa ta ua va wa xa ya za ab bb cb db eb fb gb hb ib jb kb lb mb nb ob pb qb rb sb tb ub vb wb xb yb zb ac bc cc dc ec fc gc hc ic jc kc lc mc nc oc pc qc rc sc tc uc vc

输出:

select * from TableName  
where  monthname(modified_date) between  monthname(a.modified_date)= "March" 
and monthname(modified_date)="June" ;