Generate all possible combinations using a set of strings

前端 未结 4 1187
小鲜肉
小鲜肉 2020-12-16 08:17

I\'m trying to generate all possible combinations of a set of strings, using each string maximum once.

  • The length of the output string isn\'t defined (the max
相关标签:
4条回答
  • 2020-12-16 08:30

    What you require over the array is essentially a cartesian product. This is an aspect of set mathematics and is common in database systems as well as formal modelling languages. There will be a number of implementation solutions if you google this term for PHP.

    (I've never done any PHP directly which is why I don't want to post you an incorrect (or hacky) solution, but hopefully this will help lead you down the correct path)!

    0 讨论(0)
  • 2020-12-16 08:37

    In mathematical terminology, you are asking for all possible nonempty ordered subsets of the input set. In the Online Encyclopedia of Integer Sequences, the number of such sequences appears as sequence A007526 - note that this sequence begins with 4, 15, 64, 325 exactly as you have discovered.

    This problem admits a very short, efficient solution in Python, so I'm going to post that solution first:

    def gen_nos(s):
        for i in sorted(s):
            yield i
            s.remove(i)
            for j in gen_nos(s):
                yield i+j
            s.add(i)
    

    Example:

    >>> list(gen_nos(set(['a', 'b', 'c'])))
    ['a', 'ab', 'abc', 'ac', 'acb', 'b', 'ba', 'bac', 'bc', 'bca', 'c', 'ca', 'cab', 'cb', 'cba']
    

    Note that sorted is not strictly necessary; it just ensures that the output is lexicographically sorted (otherwise, the elements are iterated in set order, which is essentially arbitrary).

    To convert this to PHP, we have to essentially use a recursive function with an extra array parameter to hold the result:

    function gen_nos(&$set, &$results) {
        for($i=0; $i<count($set); $i++) {
            $results[] = $set[$i];
            $tempset = $set;
            array_splice($tempset, $i, 1);
            $tempresults = array();
            gen_nos($tempset, $tempresults);
            foreach($tempresults as $res) {
                $results[] = $set[$i] . $res;
            }
        }
    }
    

    Example:

    $results = array();
    $set = array("a", "b", "c");
    gen_nos($set, $results);
    var_dump($results);
    

    produces

    array(15) {
      [0]=>
      string(1) "a"
      [1]=>
      string(2) "ab"
      [2]=>
      string(3) "abc"
      [3]=>
      string(2) "ac"
      [4]=>
      string(3) "acb"
      [5]=>
      string(1) "b"
      [6]=>
      string(2) "ba"
      [7]=>
      string(3) "bac"
      [8]=>
      string(2) "bc"
      [9]=>
      string(3) "bca"
      [10]=>
      string(1) "c"
      [11]=>
      string(2) "ca"
      [12]=>
      string(3) "cab"
      [13]=>
      string(2) "cb"
      [14]=>
      string(3) "cba"
    }
    
    0 讨论(0)
  • 2020-12-16 08:47

    Here's my naive recursive implementation:

    <?php
    // Lists all ways to choose X from an array
    function choose($x, array $arr) {
        $ret = array();
        if ($x === 0) {
            // I don't think this will come up.
            return array();
        } else if ($x === 1) {
            foreach ($arr as $val) {
                $ret[] = array($val);
            }
        } else {
            $already_chosen = choose($x - 1, $arr);
            for ($i = 0, $size_i = sizeof($arr); $i < $size_i; $i++) {
                for ($j = 0, $size_j = sizeof($already_chosen); $j < $size_j; $j++) {
                    if (!in_array($arr[$i], $already_chosen[$j])) {
                        $ret[] = array_merge(
                            array($arr[$i]),
                            $already_chosen[$j]
                        );
                    }
                }
            }
        }
        return $ret;
    }
    
    function choose_all($arr) {
        for ($i = 1, $size = sizeof($arr); $i <= $size; $i++) {
            foreach (choose($i, $arr) as $val) {
                echo implode(":", $val).PHP_EOL;
            }
        }
    }
    
    choose_all(array(
        "A",
        "B",
    ));
    echo "--".PHP_EOL;
    choose_all(array(
        "ABC",
        "Z",
    ));
    echo "--".PHP_EOL;
    choose_all(array(
        'T',
        'O',
        'RS'
    ));
    

    (No idea what I did, of course)

    http://codepad.org/5OKhsCJg

    0 讨论(0)
  • 2020-12-16 08:52

    Here is my implementation which I have written for quite some time using basic mathematical definiton of combination and permutation. Maybe this could help.

    <?php
    /**
     * Generate all the combinations of $num elements in the given array
     *
     * @param array  $array   Given array
     * @param int    $num     Number of elements ot chossen
     * @param int    $start   Starter of the iteration
     * @return array          Result array
     */
    function combine($array, $num, $start = 0) {
    
        static $level = 1;
    
        static $result = array();
    
        $cnt = count($array);
    
        $results = array();
    
        for($i = $start;$i < $cnt;$i++) {
            if($level < $num ) {
                $result[] = $array[$i];
                $start++;
                $level++;
                $results = array_merge($results, combine($array, $num, $start));
                $level--;
                array_pop($result);
            }
            else {
                $result[] = $array[$i];
                $results[] = $result;
                array_pop($result);
            }
        }
    
        return $results;
    }
    
    /**
     * Generate all the permutations of the elements in the given array
     */
    function permute($array) {
    
        $results = array();
    
        $cnt = count($array);
    
        for($i=0;$i<$cnt;$i++) {
            $first = array_shift($array);
    
            if(count($array) > 2 ) {
                $tmp = permute($array);
            }
            elseif(count($array) == 2) {
                $array_ = $array;
                krsort($array_);
                $tmp = array($array, $array_);
            }
            elseif(count($array) == 1) {
                $tmp = array($array);
            }
            elseif(count($array) == 0) {
                $tmp = array(array());
            }
    
            foreach($tmp as $k => $t) {
                array_unshift($t, $first);
                $tmp[$k] = $t;
            }
    
            $results = array_merge($results, $tmp);
    
            array_push($array, $first);
        }
    
        return $results;
    }
    
    $strings = array('T', 'O', 'RS');
    $strings_count = count($strings);
    
    
    $combinations = array();
    for ($i = 1; $i <= $strings_count; $i++) {
      $combination = combine($strings, $i, 0);
      $combinations = array_merge($combinations, $combination);
    }
    
    $permutations = array();
    foreach($combinations as $combination) {
      $permutation = permute($combination);
      $permutations = array_merge($permutations, $permutation);
    }
    
    print_r($combinations);
    print_r($permutations);
    
    0 讨论(0)
提交回复
热议问题