Php 获取具有固定值和数组模型的数组的所有可能组合

Php 获取具有固定值和数组模型的数组的所有可能组合,php,arrays,combinations,Php,Arrays,Combinations,我有一个函数,它给我所有的值的组合,在一个固定长度的数组中,一个固定的和: // $n_valeurs is the length of the array // $x_entrees is the sum function distributions_possibles($n_valeurs, $x_entrees, $combi_presences = array()) { if ($n_valeurs == 1) { $combi_prese

我有一个函数,它给我所有的值的组合,在一个固定长度的数组中,一个固定的和:

// $n_valeurs is the length of the array
// $x_entrees is the sum
    function distributions_possibles($n_valeurs, $x_entrees, $combi_presences = array()) {
        if ($n_valeurs == 1) {
            $combi_presences[] = $x_entrees;
            return array($combi_presences);
        }

        $combinaisons = array();

        // on fait appel à une fonction récursive pour générer les distributions
        for ($tiroir = 0; $tiroir <= $x_entrees; $tiroir++) {
            $combinaisons = array_merge($combinaisons, distributions_possibles(
                $n_valeurs - 1,
                $x_entrees - $tiroir,
                array_merge($combi_presences, array($tiroir))));
        }
        return $combinaisons;
    }
我需要生成所有可能的组合,添加另一个参数:一个引用数组$ref,其值被视为限制

生成的所有组合$combi必须遵守规则:$combi[x]distri_cach[$x]==$distri[$x]){ $distri_possi[$x]=$distri[$x]+.1; } 否则{ $distri_possi[$x]=$distri[$x]+.2; } } 否则{ $distri_possi[$x]=$distri[$x]; } } 如果($verif){ $possibilites[]=$distri_possil; } } 返回$possibilites; } 这个函数使我生成并过滤一个带有新参数的组合的大列表。 我需要一个只生成我想要的组合的函数。
你有什么想法吗?

老实说,最简单的解决方案是生成全套可能性,然后过滤不合适的结果。试图在这样的递归函数上应用掩码将是一大堆工作,这可能只会使过程复杂化和陷入困境

也就是说,我认为有两种方法可以优化你们这一代人

  • 缓存

    编写一个简单的缓存层,这样您就不会不断地重新计算较小的子列表,例如:

    function cached\u distributions\u possibles($n\u valeurs,$x\u entres,$combi\u presence=array()){
    $key=“$n_valeurs:$x_entres”;
    如果(!key_存在($key$this->cache)){
    $this->cache[$key]=可能的发行版($n\u valeurs、$x\u entres、$combi\u presence);
    }
    返回$this->cache[$key];
    }
    
    您可能希望对要缓存的列表的大小设置一个下限,以便在内存使用和CPU时间之间取得平衡

  • 发电机:

    目前,函数基本上是在内存中构建许多冗余的组合子树,您可能会遇到内存使用问题,这取决于可能性集的范围有多广。 而不是像:

    函数foo(){
    $result=[];
    对于(…){
    结果[]=foo(…);
    }
    返回$result;
    }
    
    比如:

    函数foo(){
    对于(…){
    产量foo(…);
    }
    }
    
    现在,您实际上只在内存中保存您当前感兴趣的子列表段的一个副本,以及一些协同路由,而不是整个子树


  • 我找到了一个解决方案,它是:

    function sous($dist, $d){
        $l = count($dist);
        $L = [[]];
        foreach(range(0,$l - 1) as $i){
            $K = [];
            $s = array_sum(array_slice($dist, $i+1));
            foreach($L as $p){
                $q = array_sum($p);
                $m = max($d-$q-$s, 0);
                $M = min($dist[$i], $d-$q);
                foreach(range($m, $M) as $j){
                    $p_copy = $p;
                    $p_copy[] = $j;
                    $K[] = $p_copy;
                }
            }
            $L = $K;
        }
        return $L;
    }
    

    非常感谢,但我需要找到一个解决方案,它不会强迫我创建无用的组合。
    // $distribution is the array reference
    // $similitude is the sum of values
        function SETpossibilites1distri($distribution, $similitude){
            $possibilites = [];
            $all_distri = distributions_possibles(count($distribution), $similitude);
    
            foreach($all_distri as $distri){
                $verif = true;
                $distri_possi = [];
    
                for($x = 0; $x < count($distri); $x++){
                    if($distri[$x] > $distribution[$x]){
                        $verif = false;
                        break;
                    }
    
                    if($distribution[$x] == 0){
                        $distri_possi[$x] = null;
                    }
    
                    elseif($distribution[$x] > $distri[$x] && $distri[$x] != 0){
                        // si c'est une valeur fixée qui informe sur la distri_cach
                        if($this->distri_cach[$x] == $distri[$x]){
                            $distri_possi[$x] = $distri[$x]+.1;
                        }
    
                        else{
                            $distri_possi[$x] = $distri[$x]+.2;
                        }
                    }
                    else{
                        $distri_possi[$x] = $distri[$x];
                    }
                }
                if($verif){
                    $possibilites[] = $distri_possi;
                }
            }
            return $possibilites;
        }
    
    function sous($dist, $d){
        $l = count($dist);
        $L = [[]];
        foreach(range(0,$l - 1) as $i){
            $K = [];
            $s = array_sum(array_slice($dist, $i+1));
            foreach($L as $p){
                $q = array_sum($p);
                $m = max($d-$q-$s, 0);
                $M = min($dist[$i], $d-$q);
                foreach(range($m, $M) as $j){
                    $p_copy = $p;
                    $p_copy[] = $j;
                    $K[] = $p_copy;
                }
            }
            $L = $K;
        }
        return $L;
    }