whyguy
whyguy

Reputation: 800

PHP Function 'return' not returning value

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

Answers (3)

Ahmad
Ahmad

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

Professor Abronsius
Professor Abronsius

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

BobbyTables
BobbyTables

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

Related Questions