我有以下代码:
for($a=1; $a<strlen($string); $a++){
for($b=1; $a+$b<strlen($string); $b++){
for($c=1; $a+$b+$c<strlen($string); $c++){
for($d=1; $a+$b+$c+$d<strlen($string); $d++){
$tempString = substr_replace($string, ".", $a, 0);
$tempString = substr_replace($tempString, ".", $a+$b+1, 0);
$tempString = substr_replace($tempString, ".", $a+$b+$c+2, 0);
$tempString = substr_replace($tempString, ".", $a+$b+$c+$d+3, 0);
echo $tempString."</br>";
}
}
}
}
它的作用是使所有可能的字符串组合成多个点。
示例:
t.est123
te.st123
tes.t123
...
test12.3
然后,我再添加一个点:
t.e.st123
t.es.t123
...
test1.2.3
按照我现在的方式,我需要创建大量的for循环,每个循环都有一定数量的点。我不知道如何将这个例子转化为功能或其他更简单的方法。
答案 0 :(得分:1)
您的问题是一个组合问题。注意:我不是数学家,我只是因为兴趣而研究了这些信息。
http://en.wikipedia.org/wiki/Combination#Number_of_k-combinations
也称为n choose k
。 Binomial coefficient是一个为您提供组合数量的函数。
我在这里找到的一项功能:Calculate value of n choose k
function choose($n, $k) {
if ($k == 0) {return 1;}
return($n * choose($n - 1, $k - 1)) / $k;
}
// 6 positions between characters (test123), 4 dots
echo choose(6, 4); // 15 combinations
要获得所有组合,您还必须在不同算法之间进行选择。
好帖子:https://stackoverflow.com/a/127856/1948627
更新:
我在不同的编程语言中找到了一个带有算法的site。 (但不是PHP)
我已将其转换为PHP:
function bitprint($u){
$s= [];
for($n= 0;$u > 0;++$n, $u>>= 1) {
if(($u & 1) > 0) $s[] = $n;
}
return $s;
}
function bitcount($u){
for($n= 0;$u > 0;++$n, $u&= ($u - 1));
return $n;
}
function comb($c, $n){
$s= [];
for($u= 0;$u < 1 << $n;$u++) {
if(bitcount($u) == $c) $s[] = bitprint($u);
}
return $s;
}
echo '<pre>';
print_r(comb(4, 6));
它输出一个包含所有组合的数组(字符之间的位置)。
下一步是用点替换字符串:
$string = 'test123';
$sign = '.';
$combs = comb(4, 6);
// get all combinations (Th3lmuu90)
/*
$combs = [];
for($i=0; $i<strlen($string); $i++){
$combs = array_merge($combs, comb($i, strlen($string)-1));
}
*/
foreach ($combs as $comb) {
$a = $string;
for ($i = count($comb) - 1; $i >= 0; $i--) {
$a = substr_replace($a, $sign, $comb[$i] + 1, 0);
}
echo $a.'<br>';
}
// output:
t.e.s.t.123
t.e.s.t1.23
t.e.st.1.23
t.es.t.1.23
te.s.t.1.23
t.e.s.t12.3
t.e.st.12.3
t.es.t.12.3
te.s.t.12.3
t.e.st1.2.3
t.es.t1.2.3
te.s.t1.2.3
t.est.1.2.3
te.st.1.2.3
tes.t.1.2.3
答案 1 :(得分:1)
这是一个非常不寻常的问题,但我不禁试图回避你想要做的事情。我的猜测是你想要看到一个字符串的组合有多少个字符在一个字符之间移动,最后在最后一个字符之前休息。
我的理解是你想要一个类似于你在这里看到的字符串的计数和打印输出:
t.est
te.st
tes.t
t.es.t
te.s.t
t.e.s.t
count: 6
为了促进这个功能,我提出了一个类,这样你可以将它移植到代码的其他部分,它可以处理多个字符串。这里需要注意的是字符串必须至少包含两个字符且不包含句点。这是该类的代码:
class DotCombos
{
public $combos;
private function combos($string)
{
$rebuilt = "";
$characters = str_split($string);
foreach($characters as $index => $char) {
if($index == 0 || $index == count($characters)) {
continue;
} else if(isset($characters[$index]) && $characters[$index] == ".") {
break;
} else {
$rebuilt = substr($string, 0, $index) . "." . substr($string, $index);
print("$rebuilt\n");
$this->combos++;
}
}
return $rebuilt;
}
public function allCombos($string)
{
if(strlen($string) < 2) {
return null;
}
$this->combos = 0;
for($i = 0; $i < count(str_split($string)) - 1; $i++) {
$string = $this->combos($string);
}
}
}
要使用该课程,您可以这样做:
$combos = new DotCombos();
$combos->allCombos("test123");
print("Count: $combos->combos");
输出结果为:
t.est123
te.st123
tes.t123
test.123
test1.23
test12.3
t.est12.3
te.st12.3
tes.t12.3
test.12.3
test1.2.3
t.est1.2.3
te.st1.2.3
tes.t1.2.3
test.1.2.3
t.est.1.2.3
te.st.1.2.3
tes.t.1.2.3
t.es.t.1.2.3
te.s.t.1.2.3
t.e.s.t.1.2.3
Count: 21
希望这是你正在寻找的(或至少是有帮助的)......