PHP方法实现1-9数列中添加‘+’,‘-’或'',使和为100,并输出数列

1 篇文章 0 订阅

今天收到个题目:编写一个在1,2,3,4,5,6,7,8,9(顺序不能变)数字之间插入 + 或- 或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。例如 1+2+34-5+67-8+9=100;
一开始在网上找了好久,发现这个问题是在一篇很火的文章《每个程序员1小时内必须解决的5个编程问题》上的第五题 ,如图:
这里写图片描述
都只看到Java编写的程序,但实在看不懂,下面提供一个php的解决方法,如下:

$str = '123456789';
$newStr = '';
function listarr($str, $newStr)
{
    if(strlen($str) == 1){
        $newStr = $newStr.'9';//最后一位9需要手动加上;
        $v = eval("return $newStr"); //计算公式的结果;
        if($v == 100){
            echo $newStr."<hr/>";
        }
    } else {
        $newStr .= substr($str, 0, 1);
        $str = substr($str,1);
        //递归三种可能
        listarr($str, $newStr.'+');
        listarr($str, $newStr.'-');
        listarr($str, $newStr);
    }
}
listarr($str, $newStr);

但是要注意,在求和的时候使用的是eval函数,这个函数是非常非常危险的,很多人都说木马就是利用eval函数,所以基本上所有的服务器都会禁用eval的;
如果不采用eval函数的话,就需要另外写一个方法手动计算公式的值了:

$str = '123456789';
$newStr = '';
function listarr($str, $newStr)
{
    if(strlen($str) == 1){
        $newStr = $newStr.'9';//手动加上最后一个9;
        $res = cal($newStr);
        if($res){
            echo $newStr."<hr/>";
        }
    } else {
        $newStr .= substr($str, 0, 1);
        $str = substr($str, 1);

        //递归三种可能
        listarr($str, $newStr.'+');
        listarr($str, $newStr.'-');
        listarr($str, $newStr);
}
function cal($str)
{
    $arr = explode('+', $str);//分割数列,储存至数组中
    $sum = 0;
    foreach($arr as $v){
        if(is_numeric($v)){   //判断分割的数组是否为纯数字;
            $sum += $v;
        } else {
            $vArr = explode('-', $v); //对含减号的数组再进行一次分割;
            $sum += $vArr[0];   //第一个值前的运算符为+;
            unset($vArr[0]);
            $s = array_sum($vArr);
            $sum -= $s;
        }
    }
    if($sum == 100){
        return true;
    } else {
        return false;
    }
}
listarr($str, $newStr);

再补充一个方法:

function index()
{
    $bol = ['', '-', '+'];
    $num = [0, 0, 0, 0, 0, 0, 0, 0];//8个运算符的位置;
    do{
        $var = "1{$bol[$num[0]]}2{$bol[$num[1]]}3{$bol[$num[2]]}4{$bol[$num[3]]}5{$bol[$num[4]]}6{$bol[$num[5]]}7{$bol[$num[6]]}8{$bol[$num[7]]}9";
        $v = eval("return $var;");
        if($v == 100) echo $var.'<hr/>';
        $num = getNextNum($num);
    } while($num != 'ok');
}

function getNextNum($num, $position=0)
{
    if($position == 8) return 'ok';
    $num[$position] = $num[$position] + 1;
    if($num[$position] < 3){
        return $num;
    } else {
        $num[$position] = 0;
        return getNextNum($num, $position+1);
    }
}
index();

最后补充一个通用模板

/**
 * $data array 要计算的数列组合;
 * $flag array 可用的运算符号
 * $result int 要求的和的值
 */
function think_exp($data, $flag, $result)
{
    $m = count($data);//m个数字
    $n = count($flag);//n个符号
    $num =  str_split( sprintf ( "%0". ($m - 1) ."d",0) ); //生成一个[0,0,0,0,...,0]的数组
    $exp = '';
    while($num != 'Ok' ){
        $line = '';
        for ( $i=0; $i<$m; $i++  )  {
            $line .= $data[$i]; //列出所有的式子;
            if( isset($num[$i]) ) $line .= $flag[$num[$i]];
        }
        if ( eval('return '.$line.';') == $result) {
            $exp .= $line.'='.$result.'<br />';
        }
        $num =  getNext($num , 0, $n);
    }
    return $exp;
}
function getNext($next_num , $position = 0, $n){
    if ($position == count($next_num)) return 'Ok';
    $next_num[$position] = $next_num[$position] + 1;
    if ($next_num[$position] < $n) {
        return $next_num;
    } else {
        $next_num[$position] = 0;
        return getNext($next_num, $position + 1, $n);
    }
}
//计算题目
echo "<font color=red>think_exp(array(1,2,3,4,5,6,7,8,9), array('','+','-','*','/'), 100); </font><br />";
echo think_exp(array(1,2,3,4,5,6,7,8,9), array('','+','-'), 100);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值