2015-08-28 3 views
1

У меня есть алгоритм для поиска всех уникальных комбинаций массива foods. Если какая-либо из комбинаций соответствует нашему calories value, тогда она должна возвращать значение true.PHP Функция 'return' not возвращающее значение

Вот мой подход:

<?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)); 

?> 

вопрос: почему «успех» Этот код продукции, но не возвращает истину?

Вот онлайн исполнение:

http://codepad.viper-7.com/PnTEKo

+3

Ваша функция вызывает себя рекурсивно, но никогда не передает предыдущие возвращаемые значения обратно. – mario

+0

Как я могу это исправить? Какова временная сложность этого алгоритма? Это лучше, чем комбинации с использованием побитового оператора? – whyguy

+0

Кто написал этот код? (Расширение вашего вопроса с помощью сложности алгоритма и вопрос об альтернативах немного широк). Исправление действительно зависит от того, как он должен себя вести. По крайней мере, сохраните предыдущий результат '$ success = eat (...);' recursion. Или возвращайтесь преждевременно, когда это правда, или сохраняйте его до тех пор, пока цикл не будет, и тогда он не вернется. – mario

ответ

1

оригинальная функция, которую вы не вызовете не возвращает истинно, то последующее Funtion, что называется возвращается верным своему «родитель», но это правда, никогда не возвращаются к исходному абоненту. Исправление будет выглядеть следующим образом:

if (eat($calories, $food, $i+1, $r)) { 
    return true; 
} 

Это проверяет, что рекурсивная функция возвращает, и если его true, возвращает true снова

+0

Теперь я понял. Любая дополнительная информация о временной сложности и альтернативных решениях? Спасибо! – whyguy

1

Вы вызываете функцию рекурсивно. Сбрасываемое значение будет возвращенным значением первого вызова, поскольку вы игнорируете возвращаемые значения других вызовов.

Здесь, похоже, вам нужно только выполнить один успешный вызов, после чего функция должна быть прервана. Таким образом, вы можете проверить успех, и если это произошло, верните true, чтобы предотвратить дальнейшую работу функции, и сообщите вызывающему абоненту (это может быть первый вызов или любые другие вызовы в рекурсии), что вызов был успешным.

<?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)); 

?> 
+3

Это может ответить на вопрос, но вы не объясните, что вы сделали. Поэтому этот ответ не очень полезен для будущих читателей. – KhorneHoly

+0

Я отредактировал это и немного объяснил. – Ahmad

1

Немного другой взгляд на рекурсивной функции массива будет использовать встроенный 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)); 
Смежные вопросы