思路:
因为总共就4个数字,一般也只针对加减乘除运算,所以可以考虑遍历所有组合情况。
1、先取2个数分别做四种运算;
2、将第一步的结果和从剩下2个数字取1个做四种运算;
3、将第二步结果和剩下的1个数字做四种运算;
先将所有的排列组合结果求出来,再带上四种运算符求出所有可能的结果,如果结果等于24点,就是我们想要的组合;
<?php
class Twenyfour
{
private $num = [];
private $stepLogFirst = [];
private $stepLogSecond = [];
private $stepLogThrid = [];
public function __construct($arr)
{
if (count($arr) != 4) {
throw new RuntimeException("the given num is unavailable.");
}
array_walk($arr, function ($int) {
if (!is_numeric($int) || $int < 0 || $int > 10) {
throw new RuntimeException("the type of parameter must be integer and between 1 and 10.");
}
});
$this->num = $arr;
}
public function run()
{
$allCombination = $this->getAllCombination();
$expression = [];
foreach ($allCombination as $sec) {
$result = $this->recursionOperation($sec);
if (in_array(24, $result)) {
$expression = $this->parseLog();
}
}
$uniqueResult = array_unique($expression);
array_walk($uniqueResult, function ($exp) {
preg_match_all("/[1-9]/", $exp, $res);
sort($res[0]);
sort($this->num);
if ($res[0] == $this->num) {
echo $exp . "\n";
}
});
}
function parseLog()
{
$expr = $expression = [];
$firstKeys = $this->array_search_all(24, $this->stepLogThrid);
foreach ($firstKeys as $values) {
$secondPostfix = substr($values, -2);
$second = substr($values, 0, -2);
$secondKeys = $this->array_search_all($second, $this->stepLogSecond);
foreach ($secondKeys as $value) {
$thirdPostfix = substr($value, -2);
$third = substr($value, 0, -2);
$thirdKeys = $this->array_search_all($third, $this->stepLogFirst);
$expr[$secondPostfix][$thirdPostfix] = $thirdKeys;
}
}
foreach ($expr as $ke => $val) {
foreach ($val as $k => $va) {
foreach ($va as $v) {
$expression[] = "(($v)$k)$ke";
}
}
}
return $expression;
}
/*
* search value return keys
*/
function array_search_all($needle, $array):array
{
$keys = [];
foreach ($array as $key => $value) {
if ($value == $needle) {
$keys[] = $key;
}
}
return $keys;
}
/*
* 获取4个数字所有组合情况
*/
function getAllCombination()
{
$first = $this->first($this->num);
$second = $this->second($first, $this->num);
return $second;
}
/*
* 数组相减
*/
function array_subtract($arrayA, $arrayB)
{
foreach ($arrayB as $b) {
$location = array_search($b, $arrayA);
if ($location !== false) {
unset($arrayA[$location]);
}
}
return $arrayA;
}
function recursionOperation($array)
{
$result = [];
if (count($array) > 1) {
$first = array_shift($array);
$second = array_shift($array);
$third = array_shift($array);
$fourth = array_shift($array);
$middle = $this->operation($first, $second, $this->stepLogFirst);
array_walk($middle, function ($fir) use ($third, &$result) {
$result = array_merge($result, $this->operation($fir, $third, $this->stepLogSecond));
});
$middle = $result;
array_walk($middle, function ($fir) use ($fourth, &$result) {
$result = array_merge($result, $this->operation($fir, $fourth, $this->stepLogThrid));
});
return $result;
} else {
return $array;
}
}
//递归不好记录日志
// function recursionOperation($array)
// {
// $result = [];
// if (count($array) > 1) {
// $first = array_shift($array);
// $second = array_shift($array);
// if (is_array($first)) {
// array_walk($first, function ($fir) use ($second, &$result) {
// $result = array_merge($result, $this->operation($fir, $second));
// });
// } else {
// $result = $this->operation($first, $second);
// }
// array_unshift($array, $result);
// return $this->recursionOperation($array);
// } else {
// return $array;
// }
// }
/*
* 第一步
*/
function first($num)
{
return $this->c2($num);
}
/*
* 第二步
*/
function second($array, $rawArray)
{
$result = [];
foreach ($array as $arr) {
$diff = $this->array_subtract($rawArray, $arr);
$result[] = array_merge($arr, $diff);
$result[] = array_merge($arr, array_reverse($diff));
}
return $result;
}
/*
* 一维数组中随机取2个元素
*/
function c2($array)
{
if (count($array) < 3)
return $array;
$result = [];
foreach ($array as $key => $arr) {
foreach ($array as $k => $ar) {
if ($key != $k) {
$sub = [$arr, $ar];
sort($sub);
if (!in_array($sub, $result)) {
$result[] = $sub;
}
}
}
}
return $result;
}
function operation($first, $second, &$log)
{
$result = [];
$a = $first + $second;
$b = $first - $second;
$c = $first * $second;
$d = $first / $second;
$log["$first+$second"] = $a;
$log["$first-$second"] = $b;
$log["$first*$second"] = $c;
$log["$first/$second"] = $d;
array_push($result, $a, $b, $c, $d);
return $result;
}
}
try {
$go = new Twentyfour([2, 7, 5, 1]);
$go->run();
} catch (RuntimeException $e) {
echo $e->getMessage();
}