4

The user requests a Product Category and says what quantity they want of it, ie Sugar 7 lbs.

In the search results, from the database, I have the following items (which are each different products):

Sugar, 8 oz .75

Sugar, 1 lb 1.50

Sugar, 2 lb 4.00

Sugar, 5 lb 7.00

Sugar, 10 lb 11.00

Current process:

  • Get the search results
  • Check for the cheapest option for any one of the results (only 10 lbs would meet it) or multiples of one of the results (however many of 1 needed to match the criteria, so 7 X 1 lb)
  • Put the individual product ids into an array
  • Get the 1:1 permutations, but within that, use some code to add in up to 3 repeats (because 5 lbs + 2 X 1 lbs is the cheapest option, not 5 lbs + 2 lbs)
  • In this, check for different quantity unit (oz vs lb) and be able to convert and compare
  • Compare for cheapest and return cheapest
  • I'm even disregarding where there are more than 6 elements in the permutation to weed out unlikely options and reduce overhead

This works FINE unless there are > 9 product ids (for some I have > 25), then I get this error in the logs (and a completely unrelated error in the browser): Premature end of script headers

This is a lot of code. I'm sorry, just want to be thorough! Is there a more efficient/effective way?

function processCombos($arr, $qty_search, $qty_unit_search){ //$arr is the dataset, $qty_search is 7, $qty_unit_search is 1 for lbs
   $combo=array();
   $pid_arr = arrayifyProductIDs($arr);
   $count = count($pid_arr);
   $members = pow(2,$count);

   for ($i = 0; $i < $members; $i++) {
      $b = sprintf("%0".$count."b",$i);
      $out = array();
      for ($j = 0; $j < $count; $j++) {
         if ($b{$j} == '1'){
            $out[] = $pid_arr[$j];
         }
      }

        $minLength=2;
        $out_max = count($out);
      if ($out_max >= $minLength) {
         // now add in different repeats of each of them
         $repeat_max = 3;
         $indiv = array();

         for($k=0;$k<$out_max;$k++){
           $tmp = array();
           for ($r = 0; $r < $repeat_max; $r++) $tmp[$r] = array_fill(0, $r + 1, $out[$k]);
           $indiv[] = $tmp;
         }

         $x_ct = count($indiv[0]);
         $y_ct = count($indiv[1]);
         $z_ct = count($indiv[2]) > 0 ? count($indiv[2]): 0;
         $perm = array();
         for($x=0;$x<$x_ct;$x++){
            for($y=0;$y<$y_ct;$y++){
               if($z_ct > 0){
                  for($z=0;$z<$z_ct;$z++){
                     $perm = array_merge($indiv[0][$x],$indiv[1][$y],$indiv[2][$z]);
                  }
               }else{
                  $perm = array_merge($indiv[0][$x],$indiv[1][$y]);
               }

               $p=0;
               $max_p=count($perm);
               if($max_p >=7){
               }else{
               $product_ids = array();
               $qty = 0;
               $price = 0;
               while($p < $max_p){
                  $product_id = $perm[$p];
                  $data = $arr[$product_id];
                  if(!$data['qty_unit_id'] OR !$data['qty']){continue;} // go to the next one if it doens't have qty or qty_unit
                  if($data['qty_unit_id'] == $qty_unit_search){
                     $product_ids[] = $product_id;
                     $qty += $data['qty'];
                     $price += $data['price'];
                  }else{
                     $unit_to_convert_data = getQtyUnitName($qty_unit_search);
                     $unit_to_convert = $unit_to_convert_data['abbr'];
                     $unit_to_convert_type = $unit_to_convert_data['conv_file'];
                     if($unit_to_convert_type == $data['conv_file']){
                        if($data['conv_file'] == "Mass"){
                           $product_conv = new PhpUnitsOfMeasure\PhysicalQuantity\Mass($data['qty'], $data['qty_unit']);
                        }else{
                           $product_conv = new PhpUnitsOfMeasure\PhysicalQuantity\Volume($data['qty'], $data['qty_unit']);
                        }

                        $data['qty_CONV'] = number_format($product_conv->toUnit($unit_to_convert),3,".",",");

                        $product_ids[] = $product_id;
                        $qty += $data['qty_CONV'];
                        $price += $data['price'];
                     }
                  }
                  $p++;
                  }
      if(count($combo)==0 AND $qty >= $qty_search){
         $combo = array('product_ids' => $product_ids, 'qty' => $qty, 'price' => $price);
      }elseif(($qty >= $qty_search AND $price < $combo['price']) OR
          ($qty >= $qty_search AND $price == $combo['price'] AND $qty > $combo['qty'])){
         $combo = array('product_ids' => $product_ids, 'qty' => $qty, 'price' => $price);
      }else{
      }
      }/// i think it should go here
               }
            }

         }
      }

   return $combo;
}
2
  • Hm, in that list, we could theoretically discard the 1lb & 2lb as being in our solution directly, because the .5 lb of .75 can combine up to those 2 for the same or less price. Do you want to do that, or is there an advantage (extra dimension) which should prefer larger packaging? Should we find equal 'best' solutions and then prefer the one with the least number of items? Commented Feb 26, 2014 at 22:58
  • @Wrikken larger packaging is optimal, all other factors being equal. That is being handled in the final if/elseif of the included code. Perhaps to conserve time/resources, I could start excluding quantities that are too large though, ie the 10lb product?!? Commented Feb 27, 2014 at 4:41

1 Answer 1

2

Premature end of script headers usually means your script is killed before sending headers to the web server due to a resource limit in RLimitCPU and RLimitMEM directives in the httpd.conf. Either change these directives to allow more CPU and memory to your applications or write more efficient code (3 for loops means processing record^3 times the block inside it. consider rewriting it.)

Sign up to request clarification or add additional context in comments.

1 Comment

I had a much cleaner solution where it loaded all of the permutations in a single array, then processed (compared quantity and price data) in one loop, but it exceeded memory on my shared hosting (124MB, I believe). Any thoughts on a more effective solution? Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.