Question

I am looking for an algorithm that will take numbers or words and find all possible variations of them together and also let me define how many values to look for together.

Example lets say the string or array is:

cat  
dog  
fish  

then the results for a value of 2 could be:

cat dog  
cat fish  
dog cat  
dog fish  
fish cat  
fish dog   

SO the results from the set of 3 items are 6 possible variations of it at 2 results matching
with 3 results matching it would be:

cat dog fish  
cat fish dog  
dog cat fish  
dog fish cat  
fish cat dog  
fish dog cat  

...probably more options even

I have found a link on Stackoverflow to this example that does this but it is in javascript, I am wondering if anyone knows how to do this in PHP maybe there is something already built?

http://www.merriampark.com/comb.htm (dead link)

Was it helpful?

Solution

Take a look at http://pear.php.net/package/Math_Combinatorics

<?php
require_once 'Math/Combinatorics.php';
$words = array('cat', 'dog', 'fish');
$combinatorics = new Math_Combinatorics;
foreach($combinatorics->permutations($words, 2) as $p) {
  echo join(' ', $p), "\n"; 
}

prints

cat dog
dog cat
cat fish
fish cat
dog fish
fish dog

OTHER TIPS

If your looking for how something like this works, this is how i acheived it with no php libraries using binary.

function search_get_combos($query){
$list = explode(" ", $query);
$bits = count($list); //bits of binary number equal to number of words in query;
//Convert decimal number to binary with set number of bits, and split into array
$dec = 1;
$binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
while($dec < pow(2, $bits)) {
    //Each 'word' is linked to a bit of the binary number.
    //Whenever the bit is '1' its added to the current term.
    $curterm = "";
    $i = 0;
    while($i < ($bits)){
        if($binary[$i] == 1) {
            $curterm .= $list[$i]." ";
        }
        $i++;
    }
    $terms[] = $curterm;
    //Count up by 1
    $dec++;
    $binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
}
return $terms;
}

Note that this will return only unique combinations though, but can easily be extended to get every possible order of combinations so in your example this outputs:

Array
(
    [0] => fish 
    [1] => dog 
    [2] => dog fish 
    [3] => cat 
    [4] => cat fish 
    [5] => cat dog 
    [6] => cat dog fish 
)

Edit (More clarification)

Basic theory

So firstly, binary numbers as you probably know are a string of 1's and 0's. The length of the number is the number of 'bits' it has, eg. the number 011001 has 6 bits (The numbers 25 in case you interested). Then if each bit of the number corresponds to one of the terms, each time it counts up, if the bit is 1, the term is included in the output, whereas if it's 0, it is ignored. So thats the basic theory of what's happening.

Delving into the code

PHP has no way of counting in binary, but you can convert decimals to binary. So this function actually counts up in decimal, and converts that to binary. But because the number of bits is important, as each term needs its own bit, you need to add leading 0's, so thats what this bit does: str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT)

Now this function uses a while loop, but as the number of times it needs to loop changes depending on how many terms there are, a bit of maths needs to be done. If you have ever worked with binary, you will know that the maximum number you can make is the 2^n (where n is the number of bits).

I think that should have covered all the confusing bits of the function, let me know if I've missed anything.

See what's happening

Use the following code to output the logic used, it may make a bit more sense seeing it this way!

function search_get_combos_demo($query){
    $list = explode(" ", $query);
    $bits = count($list);
    $dec = 1;
    while($dec < pow(2, $bits)) {
        $binary = str_split(str_pad(decbin($dec), $bits, '0', STR_PAD_LEFT));
        $curterm = "";
        $i = 0;
        while($i < ($bits)){
            if($binary[$i] == 1) {
                $curterm[] = $list[$i]." ";
            }
            $i++;
        }
        //-----DISPLAY PROCESS-----//
        echo "Iteration: $dec <table cellpadding=\"5\" border=\"1\"><tr>";
        foreach($binary as $b){
            echo "<td>$b</td>";
        }
        echo "</tr><tr>";
        foreach($list as $l){
            echo "<td>$l</td>";
        }
        echo "</tr></table>Output: ";
        foreach($curterm as $c){
            echo $c." ";
        }
        echo "<br><br>";
        //-----END DISPLAY PROCESS-----//
        $terms[] = $curterm;
        $dec++;
    }
    return $terms;
}

You can try this open source code for this. It implements the iterator. Click

Available in PHP, Java.

You need to extend it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top