0

I have the following code:

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>";
            }
        }
    }
}

What it does is to make all possible combinatons of a string with several dots.

Example:

t.est123

te.st123

tes.t123

...

test12.3

Then, I add one more dot:

t.e.st123

t.es.t123

...

test1.2.3

Doing the way I'm doing now, I need to create lots and lots of for loops, each for a determined number of dots. I don't know how I can turn that example into a functon or other easier way of doing this.

Th3lmuu90
  • 1,717
  • 2
  • 15
  • 18
  • What is the end result? Dots in between all of the letters? – Crackertastic Sep 20 '14 at 15:59
  • @Crackertastic, you are right, see the above example. Those loops I showed above, makes all possible combinations using 4 dots. – Th3lmuu90 Sep 20 '14 at 16:01
  • If my understanding is right all you need to do is have one function that moves the period through the string (counting as it goes) while also making sure it is stopping before another period in the string. A second function is responsible for looping based on the string size. I've posted an answer for your consideration showing what I mean by that. – Crackertastic Sep 20 '14 at 18:07

2 Answers2

1

Your problem is a combination problem. Note: I'm not a math freak, I only researched this information because of interest.

http://en.wikipedia.org/wiki/Combination#Number_of_k-combinations

Also known as n choose k. The Binomial coefficient is a function which gives you the number of combinations.

A function I found here: 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

To get all combinations you also have to choose between different algorithms.

Good post: https://stackoverflow.com/a/127856/1948627

UPDATE:

I found a site with an algorithm in different programming languages. (But not PHP)

I've converted it to 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));

It outputs an array with all combinations (positions between the chars).

The next step is to replace the string with the dots:

$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
Community
  • 1
  • 1
bitWorking
  • 12,485
  • 1
  • 32
  • 38
1

This is quite an unusual question, but I can't help but try to wrap around what you are tying to do. My guess is that you want to see how many combinations of a string there are with a dot moving between characters, finally coming to rest right before the last character.

My understanding is you want a count and a printout of string similar to what you see here:

t.est
te.st
tes.t
t.es.t
te.s.t
t.e.s.t
count: 6

To facilitate this functionality I came up with a class, this way you could port it to other parts of code and it can handle multiple strings. The caveat here is the strings must be at least two characters and not contain a period. Here is the code for the class:

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);
        }
    }
}

To make use of the class you would do this:

$combos = new DotCombos();
$combos->allCombos("test123");
print("Count: $combos->combos");

The output would be:

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

Hope that is what you are looking for (or at least helps)....

Crackertastic
  • 4,958
  • 2
  • 30
  • 37
  • Sure it helps! Yet there are some other combinations which that class don't generate like t.e.st12.3 – Th3lmuu90 Sep 20 '14 at 18:09
  • Ah, I think I see a little better now what you are after. Well, this should give you a start. I'll leave it up to you to finish it off :) – Crackertastic Sep 20 '14 at 18:15