【问题标题】:How to build a character table如何建立一个字符表
【发布时间】:2010-06-15 02:12:56
【问题描述】:
$chars = array
(
    ' ',
    '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
    ':', ';', '<', '=', '>', '?', '`',
    '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',
    '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',
    '{', '|', '}', '~'
);

使用$chars 数组中的字符,我想找到所有可能的组合,长度不超过$n

**For Example**:
It should start off with ' ', and then go to '!'.
Once it gets to the end of the $chars array (`~`) it should add on another charter.
Run though those combinations ('! ', '" ', ... '~ ', ' !' ... '~~', '   ', ect).
And then just keep on going ... 

【问题讨论】:

  • 我假设您不必支持 Unicode?​​span>
  • @Dan04,不,这次我感兴趣的只是 ASCII 中的可打印字符。但正如您所见,如果需要,字符数组是可扩展的。
  • 您希望找到所有可能的组合或排列吗?
  • 所以您希望函数返回 AAA、AAB、ABA、BAA、ABB、BAB、BBA 和 BBB?还是只是 AAA、AAB、ABB、BBB?
  • @Zack,类似这样,AAA, BAA, ABA, BBA, AAB, BAB, BBB,类似这样,但它应该只以一个字母开头,然后根据需要添加,A, B, AA, BA, AB, BB, AAA, BAA, ABA, BBA, AAB, BAB, BBB, AAAA ... 等。

标签: php string


【解决方案1】:
【解决方案2】:

如果您只想找到许多可能的组合,那就是组合 - 排列数学 - 您必须将长度 $n 提高到数组中元素的幂。在 PHP 中,这将是:

echo pow($n, count($chars)); 

其中 $n - 你的组合长度。

数学参考:combinations - permutations

附:向 Zackmans 解决方案致敬,但我想知道它(以及与此相关的任何其他问题)是否不会因为问题的范围而导致 PHP 脚本超时。

【讨论】:

  • 应该是echo pow(count($chars), $n);
  • 不,完全不。我已经给出了链接,它是示例 2,第 259 页。基数是 $n。我希望能有更多的人欣赏答案,而不是仅仅批评,因为有时进入一个主题,提出一个答案却得不到一个点是很无聊的。
  • 从 Mark 的例子可以看出允许重复。
  • @Arunas,除非我犯了错误,否则真的不应该重复,因为每个新值都会以某种方式与上一个不同。另外,我同意这会导致默认的 30 秒脚本限制被通过,但我通过命令行使用它,所以它会一直运行到程序结束(或无限期地)。
  • 重复我的意思是符号可以在你的行中重复,比如'aaa','bbbcde',并且你在你的例子中指出:>>运行这些组合('!','“ ', ... '~', '!' ... '~~', ' ', 等)。看看thease 2 '~~'
【解决方案3】:

此函数将获取一个数组$permutation,该数组仅包含另一个数组$set 中的元素,并生成最大长度为$max 的下一个排列。

function next_permutation($permutation, $set, $max)
{
    if (array_unique($permutation) === array(end($set)))
    {
        if (count($permutation) === $max)
        {
            return FALSE;
        }

        return array_fill(0, count($permutation) + 1, $set[0]);
    }

    foreach (array_reverse($permutation, TRUE) as $key => $value)
    {
        if ($value !== end($set))
        {
            $permutation[$key] = $set[array_search($value, $set) + 1];
            break;
        }

        $permutation[$key] = $set[0];
    }

    return $permutation;
}

然后可以以这样的方式使用该函数,迭代每个可能的排列并根据散列密码检查它。

$set         = array('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');
$max         = 3;
$permutation = array($set[0]);
$password    = '403926033d001b5279df37cbbe5287b7c7c267fa';

do {
    $string = implode('', $permutation);

    if (sha1($string) === $password)
    {
        echo 'Password found: "'.$string.'"';
        break;
    }
} while ($permutation = next_permutation($permutation, $set, $max));

这将打印Password found: "lol"

【讨论】:

  • 首先,我很抱歉没有解释自己,我的想法更彻底。 I'll never find a programming language that frees me from the burden of clarifying my ideas. 我希望该值是一个字符串,在每次循环运行时对其进行编辑和更改,以便我可以散列并测试它的散列值与另一个散列的值,以确定它是否是用户的密码或不是。
  • 我已经相应地更新了函数。不过,该函数采用数组而不是字符串,以获得更大的灵活性(即,如果您想使用具有多字符元素的集合)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-28
  • 2016-04-13
相关资源
最近更新 更多