Reputation: 800
I have a algorithm to find all unique combinations of an array of foods
. If any of combinations match our calories value
then it should return true.
Here is my approach:
<?php
$food = [
['a', 70],
['b', 5],
['c', 20],
['d', 10]
];
function eat($calories, $food, $k = 0, $p = []) {
for ($i=$k; $i < count($food); $i++) {
$r = array_merge($p, [$i]);
$c = 0;
foreach ($r as $j) {
$c += $food[$j][1];
}
if ($c == $calories) {
echo "success";
return true;
}
eat($calories, $food, $i+1, $r);
}
}
var_dump(eat(100, $food));
?>
The question is: Why this code output 'success' but doesn't return true?
Here is the online execution:
http://codepad.viper-7.com/PnTEKo
Upvotes: 1
Views: 428
Reputation: 5760
You are calling the function recursively. The dumped value will be the returned value of the first call, because you ignore the returned values of other calls.
Here, it seems that you only need to reach one successful call, and after that the function must be terminated. So you can check for the success, and if it has happened, return true, to prevent the function going further, and tell the caller(this can be the first call, or any other calls in recursion) that the call was successful.
<?php
$food = [
['a', 70],
['b', 5],
['c', 20],
['d', 10]
];
function eat($calories, $food, $k = 0, $p = []) {
for ($i=$k; $i < count($food); $i++) {
$r = array_merge($p, [$i]);
$c = 0;
foreach ($r as $j) {
$c += $food[$j][1];
}
if ($c == $calories) {
echo "success";
return true;
}
if(eat($calories, $food, $i+1, $r))
return true;
}
}
var_dump(eat(100, $food));
?>
Upvotes: 1
Reputation: 33813
A slightly different take on the recursive array function would be to use the built in function arrayIterator.
$food = array(
'a'=> 70,
'b'=> 5,
'c'=> 20,
'd'=> 10,
'e'=> 99
);
function eat( $calories, $food, $p=array() ){
$a = new ArrayObject( array_merge( $food, $p ) );
$iterator = $a->getIterator();
while( $iterator->valid() ) {
if( $iterator->current()==$calories ) {
echo 'success: key='.$iterator->key().' value='.$iterator->current();
return true;
}
$iterator->next();
}
return false;
}
eat( 120, $food, array( 'banana'=>500,'apple'=>120 ) );
Upvotes: 1
Reputation: 4695
The original function you call never returns true, the subsequent funtion that is called returns true to its "parent", but that true is never returned to the original caller. A fix would be as follows:
if (eat($calories, $food, $i+1, $r)) {
return true;
}
This checks what the recursive function returns, and if its true
, returns true
again
Upvotes: 1