我在下面的回答会让你成功。
资源
我从this 的答案中借用了一些代码逻辑。
要引用答案(以防将来被删除),请在下面查看。
你可以试试
echo "<pre>";
$sum = 12 ; //SUM
$array = array(6,1,3,11,2,5,12);
$list = array();
# Extract All Unique Conbinations
extractList($array, $list);
#Filter By SUM = $sum $list =
array_filter($list,function($var) use ($sum) { return(array_sum($var) == $sum);});
#Return Output
var_dump($list);
输出
array
0 => array
1 => string '1' (length=1)
2 => string '2' (length=1)
3 => string '3' (length=1)
4 => string '6' (length=1)
1 => array
1 => string '1' (length=1)
2 => string '5' (length=1)
3 => string '6' (length=1)
2 => array
1 => string '1' (length=1)
2 => string '11' (length=2)
3 => array
1 => string '12' (length=2)
使用的功能
function extractList($array, &$list, $temp = array()) {
if(count($temp) > 0 && ! in_array($temp, $list))
$list[] = $temp;
for($i = 0; $i < sizeof($array); $i ++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
extractList($copy, $list, $add);
} else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (! in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
我的回答
下面的代码使用上面引用的代码。我更改了 array_filter 函数的返回功能以将其映射到您的需求。
您唯一要做的就是更改函数,以便它可以捕获多个相同类型的房间。目前,下面的代码只会输出每种房间类型的 1 个(根据上面引用的代码)。解决此问题的一种简单方法是将您发送给函数的数组值乘以您正在搜索房间的客人数量,但最多为可用房间数量。所以:如果您要为 4 位客人预订,并且您没有剩余单人房且只有 1 间双人房,那么您的最佳匹配结果将必须是 2 person room 和 3 person room。我已经添加了一些 brief 功能来添加它(它已被注释掉),尽管我还没有对其进行测试。处理它也可能需要一段时间,因此如果您正在寻找更快的方法,您将不得不使用之前 cmets/answers 中已经提到的更好的算法或解决 P vs NP
下面的代码还为您提供了切换$exact 值的选项。如果设置为true,此值将仅返回完全等于客人数量的匹配项,如果设置为false,将返回至少等于客人数量的所有匹配项客人。
<?php
class Booking {
private $minGuests = 1;
protected $guests = 1;
protected $rooms = [];
public function getRoomCombinations(bool $exact = true) {
$guests = $this->guests;
$list = [];
$rooms = $this->rooms;
/*for($i = 0; $i < $guests-1; $i++) {
$rooms = array_merge($rooms, $this->rooms);
}
asort($rooms);*/
$this->extractList($rooms, $list);
$result = array_filter($list, function($var) use ($guests, $exact) {
if($exact)
return(array_sum(array_map(function($item) { return $item['room_for'];}, $var)) == $guests);
else
return(array_sum(array_map(function($item) { return $item['room_for'];}, $var)) >= $guests && count($var) <= $guests);
});
array_multisort(array_map('count', $result), SORT_ASC, $result);
return $result;
}
private function extractList(array $array, array &$list, array $temp = []) {
if (count($temp) > 0 && !in_array($temp, $list))
$list[] = $temp;
for($i = 0; $i < sizeof($array); $i++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
$this->extractList($copy, $list, $add);
} else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (!in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
public function setGuests(int $guests) {
$this->guests = ($guests >= $this->minGuests ? $guests : $this->minGuests);
return $this;
}
public function setHotelRooms(array $rooms) {
$this->rooms = $rooms;
return $this;
}
}
$booking = (new Booking())
->setGuests(4)
->setHotelRooms([
[
"title" => "1 person room",
"room_for" => 1,
"price" => 79
],
[
"title" => "2 person room with other",
"room_for" => 1,
"price" => 69
],
[
"title" => "2 person room alone",
"room_for" => 1,
"price" => 89
],
[
"title" => "2 person",
"room_for" => 2,
"price" => 69
],
[
"title" => "3 person",
"room_for" => 3,
"price" => 69
]
]);
echo '<pre>' . var_export($booking->getRoomCombinations(true), true) . '</pre>';
?>