3

我希望能够输入一个数字并获得一个由字符串或唯一字符构建的密码。因此,如果我在字符串中有两个字符: $string = "AB"; 这些是期望的结果:

-in-|-out-
 0  |  A
 1  |  B
 2  | AA
 3  | AB
 4  | BA
 5  | BB
 6  | AAA
 7  | AAB
 8  | ABA
 9  | ABB
 10 | BBB

等等。这是我当前的代码:

for($i = 1; $i < 100; $i++)
{
    echo createString ($i, "AB")."<br/>";
}
function createString ($id, $chars) // THE ISSUE <---
{
    $length = getLength($id, $chars);
    //echo "LENGTH : ".$length."<br/><br/>";
    $string = "";
    for($i = 0; $i < $length; $i++)
    {
        $a = round(($id - 1)/pow($length, $i)); // THE ISSUE <-----
        $local = local($a, strlen($chars));
        $string = $chars{$local - 1}." : ".$string;
    }
    return $string;
}
function local ($num, $max)
{
    $num += $max;
    while($num > $max)
    {
        $num -= $max;
    }
    return $num;
}
/*
 get the length of the output by inputing the "in" and defining the possible characters
*/
function getLength ($id, $chars)
{
    $charNUM = 1;
    $LR = -1;
    $HR = 0;
    while(true)
    {
        $LR = $HR;
        $HR = pow(strlen($chars), $charNUM) + $LR;
        $LR += 1;
        //echo $LR." : ".$HR." : ".$charNUM."<br/>";
        if($id >= $LR && $id <= $HR)
        {
            return $charNUM;
        }
        if($id < $LR)
        {
            return false;
        }
        $charNUM ++;
    }
}

输出:

B : 
A : 
A : B : 
B : A : 
B : B : 
A : A : 
A : B : B : 
A : B : A : 
A : A : B : 
A : A : A : 
A : A : B : 
A : B : A : 
A : B : B : 
A : B : A : 
B : A : B : B : 
B : A : B : A : 
B : A : B : B : 
B : A : B : A : 
B : A : A : B : 
B : A : A : A : 
B : A : A : B : 
B : A : A : A : 
B : A : B : B : 
B : A : B : A : 
B : B : B : B : 
B : B : B : A : 
B : B : A : B : 
B : B : A : A : 
B : B : A : B : 
B : B : A : A : 
B : B : A : B : B : 
B : B : A : B : A : 
B : B : A : B : B : 
B : B : A : A : A : 
B : B : A : A : B : 
B : B : A : A : A : 
B : B : A : A : B : 
B : B : A : A : A : 
B : B : B : B : B : 
B : B : B : B : A : 
B : B : B : B : B :

等等。但它有重复。我遇到了函数 createString() 的问题。我想在没有预先计算的情况下在蛮力密码表的某个地方访问密码。我不想要一个预先计算的数组,而只是访问它的一个点。

4

3 回答 3

5

我将在这里发布将任何正整数转换为任何给定正整数基数 (>1) 的系统的代码,返回每个数字的值。

function convert($number, $base)
{
        $return = array();
        do{
                $return[] = $number % $base;
                $number = floor($number / $base);
        }while($number != 0);
        return $return;
}

所以你会调用使用这个函数,如下所示:

function createString($i, $base)
{
        $res = convert($i, strlen($base));
        $str = "";
        foreach($res as $digit)
        {
                $str = $base[$digit] . $str;
        }
        return $str;
}

试试看。它的格式与您的输出略有不同,但应该是可读的。

基本“AB”的一些示例输出:

0 -> A    
1 -> B
2 -> BA
3 -> BB
4 -> BAA
5 -> BAB
6 -> BBA
7 -> BBB
8 -> BAAA
9 -> BAAB
10-> BABA
11-> BABB
12-> BBAA
13-> BBAB
14-> BBBA
15-> BBBB
于 2011-08-11T19:21:18.333 回答
4

解决方案:

function id_encode($id, $chars) {
    $len = strlen($chars);
    $i = 1;
    $str = array();
    while ($id >= 0) {
        $str[] = $chars[ $id / pow($len, $i - 1) % $len ];
        $id -= pow($len, $i);
        $i++;
    }
    return strrev(implode('', $str));
}
function id_decode($str, $chars) {
    $len = strlen($chars);
    $chars = array_flip(str_split($chars));
    $strs = str_split(strrev($str));
    $i = 0;
    foreach ($strs as $key => $char) {
        if (!$i) {
            $id = $chars[ $char ];
        }
        else {
            $id += pow($len, $i) * ($chars[ $char ] + 1);
        }
        $i++;
    }
    return $id;
}

例子:

$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';

$id = 42599293;

$string = id_encode($id, $chars);
echo 'id:          ' . $id . PHP_EOL;
echo 'id_encode(): ' . $string . PHP_EOL;
echo 'id_decode(): ' . id_decode($string, $chars) . PHP_EOL;

输出:

id:          42599293
id_encode(): bHFm9
id_decode(): 42599293

示例 2:

$chars = 'AB';
$len = strlen($chars);

for ($i = 0; $i < 50; $i++) {
    if ($i) {
        if (!($i % $len)) {
            echo PHP_EOL;
        }
        else {
            echo ', ';
        }
    }
    $str = id_encode($i, $chars);
    $id = id_decode($str, $chars);
    echo $i . '=' . $str . '=' . $id;
}

输出 2:

0=A=0, 1=B=1
2=AA=2, 3=AB=3
4=BA=4, 5=BB=5
6=AAA=6, 7=AAB=7
8=ABA=8, 9=ABB=9
10=BAA=10, 11=BAB=11
12=BBA=12, 13=BBB=13
14=AAAA=14, 15=AAAB=15
16=AABA=16, 17=AABB=17
18=ABAA=18, 19=ABAB=19
20=ABBA=20, 21=ABBB=21
22=BAAA=22, 23=BAAB=23
24=BABA=24, 25=BABB=25
26=BBAA=26, 27=BBAB=27
28=BBBA=28, 29=BBBB=29
30=AAAAA=30, 31=AAAAB=31
32=AAABA=32, 33=AAABB=33
34=AABAA=34, 35=AABAB=35
36=AABBA=36, 37=AABBB=37
38=ABAAA=38, 39=ABAAB=39
40=ABABA=40, 41=ABABB=41
42=ABBAA=42, 43=ABBAB=43
44=ABBBA=44, 45=ABBBB=45
46=BAAAA=46, 47=BAAAB=47
48=BAABA=48, 49=BAABB=49

归功于@PatrickLorio id_encode()id_decode()是我自己先手工计算的: 在此处输入图像描述

在那之后,我认为可以id_encode()通过取 id 的第 n 个根来进行优化......也许我有时间检查一下。

于 2017-02-16T15:14:14.443 回答
3

好旧的递归

$string = "AB";
$characters = str_split($string, 1);

function mutate ($characters, $count) {
  var_dump($characters);

  if (!$count) return $characters;

  $result = $tmp = mutate($characters, $count -1);

  foreach ($characters as $char) {
    foreach ($tmp as $current) {
      $result[] = $current . $char;
    }
  }
  return $result;
}
于 2011-08-11T19:30:23.790 回答