PHP 任意组合求合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP 任意组合求合相关的知识,希望对你有一定的参考价值。

比如我有数组array(1,2,3,4,5,6,7,8,9)
现要从中抽取任意个元素相加让它等于10(比如1+9,2+8,3+7,2+3+5等等),只要匹配上一个就停止不再继续。
php代码应该如何写

$arr=array(1,2,3,4,5,6,7,8,9);

function isten($arr)
if(!is_array($arr))throw new Exception("传入的必须是数组");
$len=count($arr);
$count=mt_rand(1,$len);
$num=0;
$tem=array();
for($i=0;$i<$count;++$i)
$n=mt_rand(0,$len-1);
$num+=$arr[$n];
$tem[]=$arr[$n];

    $re=array(
       'num'=>$num,
       'tem'=>$tem,
     );
    return $re;


/*//要了解具体的执行过程,可以用这段代码
$times=0;
$plus=0;
while($plus!=10)
$re=isten($arr);
$times++;
echo "尝试次数:".$times,",";
echo "随机抽取".count($re['tem']).'个元素: ';
    $str="";
    foreach($re['tem'] as $v)
     $str.=$v."+";
    
    $str=substr($str,0,strlen($str)-1);
    echo $str;
echo '='.$re['num'],"<br>";
$plus=$re['num'];
*/

//每次要获取结果为10时,所需要尝试的资料
function get_times($arr)
$times=0;
while(true)
$re=isten($arr);
$num=$re['num'];
$times++;
       if($num==10)
        return $times;break;
       




// echo get_times($arr);
//计算平均需要尝试的次数:
$t=0;
for($i=0;$i<100000;++$i)
  $t+=get_times($arr);


echo "平均需要尝试的次数是:".$t/100000;

//结论:通过100000次的计算,得出的平均尝试次数是51-52次之间。

参考技术A <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
$array=array(
1,2,3,4,5,6,7,8,9,3,1,5
);
echo "第一种嵌套循环求合<br/>";
$flag=false;
for($i=1;$i<count($array);$i++)

for($j=0;$j<count($array);$j++)

if($i==$j)

continue;

if(($array[$j]+$array[$i])==10)

echo "检查到".$array[$j]."+".$array[$i]."=".($array[$j]+$array[$i]);
$flag=true;
break;


if($flag)

break;


echo "<br/>第二种方式:随机位相加求合<br/>";
getrandom($array);
function getrandom($array)

$flag=false;
$len=count($array);
while(!$flag)

$a=rand(0,$len);
$b=rand(0,$len);
if($a!=$b)

if(($array[$a]+$array[$b])==10)

echo "$array[$a]+$array[$b]=10";
$flag= true;


else

$flag= false;



?>

以上只是简单处理,可以实现功能,但效率如何需要进一步验证。
希望对你有帮助。
参考技术B

之前这位朋友提供的方法,只能算两位的匹配,三位的做不到。

因此我也写了个,可以实现三位或者四位的相加等于10,并且可以扩展

<?php
header("Content-Type: text/html; charset=utf-8");
$nums_all =0;
main($nums_all);

function main($nums_all)
//echo $nums_all;//用来监视执行的次数
$he = 10;//要求和为多少

$nums_all++;
$array = range(1,9);


$nums = rand(1,count($array));

$new = array();
$output = array();
for($i=1;$i<=$nums;$i++)
    $tmp=array_rand($array);
    $new[]=$array[$tmp];
    unset($array[$tmp]);


foreach($new as $v)
    $output[]=$v;
    if(array_sum($output)==$he)
        echo  join('+',$output).'='.$he;
        return false;
    

main($nums_all);

?>

在类常量PHP中组合位标志[重复]

【中文标题】在类常量PHP中组合位标志[重复]【英文标题】:Combining bit flags in a class constant PHP [duplicate] 【发布时间】:2012-02-18 21:23:15 【问题描述】:

可能重复:Workaround for basic syntax not being parsed

我试图让开发人员指定任意位组合,以指定他们希望在响应中包含哪些数据。

    class ClassName 
            const BUILD_DATE_RFC = 1; 
            const BUILD_DATE_SQL = 2;
            const BUILD_DATE_SQLTIME = 4;
            const BUILD_DATE_UNIX = 8;

           // ....
   

从某种意义上说,当我像这样实例化类时:

$whatever = new ClassName(BUILD_DATE_RFC|BUILD_DATE_SQL);

这个逻辑会被执行:

    if (self::BUILD_DATE_RFC & $this->metaBits)    
        $dateMeta['RFC'] = date('r');
    
    if (self::BUILD_DATE_SQL & $this->metaBits) 
        $dateMeta['SQL'] = date('Y-m-d');
    
    if (self::BUILD_DATE_SQLTIME & $this->metaBits) 
        $dateMeta['SQL_time'] = date('Y-m-d H:i:s');
    

所有这一切都很好,除了我想定义“快捷方式位”之类的东西个人。

我试过了,但它抛出了一个错误:

const BUILD_DATE_ALL =  (self::BUILD_DATE_RFC|self::BUILD_DATE_SQL|self::BUILD_DATE_SQLTIME|self::BUILD_DATE_UNIX);

我也尝试了不同的方法/语法:

const BUILD_REQUEST_ALL =   self::BUILD_IP |
                self::BUILD_USERAGENT |
                self::BUILD_REFERER;

我尝试过的另一种方法:

const BUILD_DEFAULT = self::BUILD_DATE_ALL|self::BUILD_REQUEST_ALL^self::BUILD_REFERER^self::BUILD_USERAGENT;

我得到的错误是:

ErrorException: 语法错误,意外'('

我得到的其他方法的错误是:

ErrorException: 语法错误,意外 '|',期待 ',' 或 ';'

看起来 PHP 不想在常量定义中计算太多,只想要一个值而不是派生值。我假设这是基于它不想要括号也不想要 | 的事实。做进一步的计算。此外,我尝试使用 '-' 而不是 |只是为了测试我的理论。是的,它抱怨 + 也出乎意料。

我该如何解决这个问题,以便我可以定义一个“快捷方式位”,它是其他已定义常量范围的总和。

【问题讨论】:

您需要使用纯数值定义该常量(通过自己添加标志)。 从docs 开始,PHP 5.6.0 中添加了常量表达式支持。因此,您的以下初始方法不会引发错误。 const BUILD_DATE_ALL = (self::BUILD_DATE_RFC|self::BUILD_DATE_SQL|self::BUILD_DATE_SQLTIME|self::BUILD_DATE_UNIX); 【参考方案1】:

你可以自己计算。因为这些是位标志,所以有一个模式。

class ClassName 
        const BUILD_DATE_RFC = 1; 
        const BUILD_DATE_SQL = 2;
        const BUILD_DATE_SQLTIME = 4;
        const BUILD_DATE_UNIX = 8;
        const BUILD_DATE_ALL = 15; // 15 = 1|2|4|8;
       // ....

【讨论】:

有点烦人,因为我想展示实际包含的位,以便其他开发人员可以查看并弄清楚,但这就是 cmets 的用途。我将实施此解决方法。谢谢! 如果您设置了BUILD_DATE_ALL = -1,那么您就不需要解决它,因为-1 无论如何都会将所有位设置为1。 ALL 标志的最佳实践。【参考方案2】:

引用手册:

值必须是常量表达式,而不是(例如)变量、属性、数学运算的结果或函数调用。

使用 |运算符是运算的结果,因此不允许

【讨论】:

很遗憾 PHP 只允许使用原语。其他语言也会出现这种情况吗?

以上是关于PHP 任意组合求合的主要内容,如果未能解决你的问题,请参考以下文章

求一个PHP计算数组内元素的不同组合,请看案例

石子合并问题

php中:计算任意一维数字数组的奇数个数、偶数个数?代码怎么写.

1到40任意4数组合,能有多少个组合?

python 给定数组任意组合等于一个定值的所有解

匹配多个字段或字段的任意组合