MikoAndras.hu/en

Personal pages for Andras MIKO

Code optimizations in PHP

Code v2 – dinamic programming

Theory behind dinamic programming is to divide the problem into smaller pieces. It is most efficient in cases where these smaller pieces overlap, and they should be calculated multiple times before we get to the final solution.

Basic idea is simple: each time we calculate such a smaller piece, we should save – memorize – the result, and when we should calculate this again we simply use the result from the previous calculation.

Division

The problem with equations for four guests looked like:
Q(4) = unique( Q(3) + Q(2) + Q(1) + 1 )

Further divided:
Q(4) = unique( unique(Q(2) + Q(1) + 1 ) + Q(2) + Q(1) + 1 )
Q(4) = unique( unique( unique(Q(1) + 1 ) + Q(1) + 1) + unique(Q(1) + 1 ) + Q(1) + 1 )

So Q(4) calls the smaller parts:

  • 3 guests: 1 time
  • 2 guests: 2 times
  • 1 guest: 4 times

The list will rise exponentially with each additional guest. This rise can be observed on the first version time graph.

Calculation time

Calculation time

We have more than one way to memorize smaller results, my choice fell on the shared variable. To use this we have to modify the parameterlist and the call for the function.

<?php
  // cache-array has the initial value empty for 0 guests
  $variation_cache = array(0 => array());
  // cache will be passed on as pointer not value
  // so we can have the changes in the caller code
  function calc_room_use ($passengers, &$variation_cache) {
    if ($passengers < 1) {
      return 0;
    }
    for ($rn = 1; $rn <= 4; $rn += 1) {
      if ($passengers >= $rn) {
        // we calculate parts only if they were not calc'd already
        if (! isset($variation_cache[$passengers - $rn])) {
          calc_room_use($passengers - $rn, $variation_cache);
        }
        // actual variation is initially empty
        if (! isset($variation_cache[$passengers])) {
          $variation_cache[$passengers] = array();
        }
        $actual_variation = $rn;
        // part-variation-set should be available at this point
        foreach ($variation_cache[$passengers - $rn] as $variation) {
          $actual_variation = explode(',', $variation);
          $actual_variation[] = $rn;
          sort($actual_variation);
          $actual_variation = implode(',', $actual_variation);
          // checks are also done in the cache
          if (! in_array($actual_variation, $variation_cache[$passengers])) {
            // and we also write into
            $variation_cache[$passengers][] = $actual_variation;
          }
        }
        if ($passengers == $rn && ! in_array($rn, $variation_cache[$passengers])) {
          $variation_cache[$passengers][] = $rn;
        }
      }
    }
  }
  calc_room_use($passengers, $variation_cache);
  // variation numbers have to be calculated from the cache,
  // not the function's return value
  echo count($variation_cache[$passengers]);
?>

Resource-usage compared to the first version’s:

Calculation time v2

Calculation time v2

Memory usage v2

Memory usage v2

In text:

  • Calculated in 1 second: 44 fő
  • Calculated in 30 seconds: 76 fő
  • 25 arriving guests: 0.046 seconds
  • 128MB memorylimit: excluded within time limit

Rating: developing.

Second version clearly runs within established boundaries, but it still has potencial.

From now on the motto is “challenge accepted”…

Pages: 1 2 3 4 5 6 7

, , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>