Advent of code 2015/15
Ajax Direct

Answer

Part 1 :
Part 2 :
$ingredients = $input->lines->map(function ($line) {
    preg_match("/^(\w+): capacity (-?\d+), durability (-?\d+), flavor (-?\d+), texture (-?\d+), calories (-?\d+)$/", $line, $matches);
    return array_slice($matches, 2);
});

function solve($ingredients, $calories_target = null)
{
    $best = 0;
    for ($i = 0; $i <= 100; $i++) {
        for ($j = 0; $j <= 100 - $i; $j++) {
            for ($k = 0; $k <= 100 - $i - $j; $k++) {
                $l = 100 - $i - $j - $k;
                $score = 1;

                if ($calories_target !== null) {
                    $calories = $ingredients[0][4] * $i + $ingredients[1][4] * $j + $ingredients[2][4] * $k + $ingredients[3][4] * $l;
                    if ($calories != $calories_target) continue;
                }

                foreach ([0, 1, 2, 3] as $prop) {
                    $score *= max(0, $ingredients[0][$prop] * $i + $ingredients[1][$prop] * $j + $ingredients[2][$prop] * $k + $ingredients[3][$prop] * $l);
                }
                $best = max($best, $score);
            }
        }
    }
    return $best;
}

// ==================================================
// > PART 1
// ==================================================
$solution_1 = solve($ingredients);
$solution_2 = solve($ingredients, 500);