Advertisement
Guest User

Stack Overflow Q# 11965455

a guest
Aug 26th, 2012
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.02 KB | None | 0 0
  1. <?php
  2.  
  3. class LineSegment {
  4.     public $user_id;
  5.     public $start_point;
  6.     public $end_point;
  7.    
  8.     public function __construct($user_id, $start_value, $end_value) {
  9.         $this->user_id = $user_id;
  10.         $this->start_point = new Endpoint($start_value, $user_id, TRUE);
  11.         $this->end_point = new Endpoint($end_value, $user_id, FALSE);
  12.     }
  13.    
  14.     public function __toString() {
  15.         return "$user_id [{$start_point->value}, {$end_point->value}]";
  16.     }
  17. }
  18.  
  19. class Endpoint {
  20.     public $value;
  21.     public $user_id;
  22.     public $is_start;
  23.    
  24.     public function __construct($value, $user_id, $is_start) {
  25.         $this->value = $value;
  26.         $this->user_id = $user_id;
  27.         $this->is_start = $is_start;
  28.     }
  29.    
  30.     public function __toString() {
  31.         $location = $this->is_start ? "start" : "end";
  32.         return "{$this->user_id}: {$this->value} ($location)";
  33.     }
  34. }
  35.  
  36. class ResultSegment {
  37.     public $user_ids;
  38.     public $start_value;
  39.     public $end_value;
  40.    
  41.     public $num_users;
  42.     public $duration;
  43.    
  44.     public function __construct($user_ids, $start_value, $end_value) {
  45.         $this->user_ids = $user_ids;
  46.         $this->start_value = $start_value;
  47.         $this->end_value = $end_value;
  48.         $this->num_users = count($user_ids);
  49.         $this->duration = $end_value - $start_value; //assumption: values are numeric (insert your own function here)
  50.     }
  51. }
  52.  
  53. class Sweepline {
  54.     public $last_endpoint_value; //value of last encountered endpoint
  55.     public $last_endpoint_was_end; //last encountered endpoint was an end (right) endpoint
  56.     public $active_users; //set of user IDs (user_id => user_id)
  57.     public $result_segments; //value-sorted array of LineSegments (with user_id being the number of available users)
  58.    
  59.     public function __construct() {
  60.         $this->last_endpoint_value = 0;
  61.         $this->last_endpoint_was_end = false;
  62.         $this->active_users = array();
  63.     }
  64.    
  65.     public function execute($endpoints) {
  66.         $this->result_segments = array();
  67.         foreach ($endpoints as $endpoint) {
  68.             $this->advance($endpoint);
  69.         }
  70.         return $this->result_segments;
  71.     }
  72.    
  73.     public function advance(Endpoint $next_endpoint) {
  74.         echo "next endpoint: " . $next_endpoint, "\n";
  75.         $user_id = $next_endpoint->user_id;
  76.         if ($next_endpoint->is_start) {
  77.             $this->active_users[$user_id] = $user_id;
  78.         } else {
  79.             //when multiple segments end at the same value, you only need one result
  80.             if (!$this->last_endpoint_was_end) {
  81.                 $result = new ResultSegment(array_values($this->active_users), $this->last_endpoint_value, $next_endpoint->value);
  82.                 $this->result_segments[] = $result;
  83.             }
  84.             unset($this->active_users[$user_id]);
  85.         }
  86.         $this->last_endpoint_was_end = !$next_endpoint->is_start;
  87.         $this->last_endpoint_value = $next_endpoint->value;
  88.     }
  89. }
  90.  
  91.  
  92. function endpoint_comparer(Endpoint &$point1, Endpoint &$point2) {
  93.     if ($point1->value == $point2->value) {
  94.         if ($point1->is_start != $point2->is_start) {
  95.             return $point1->is_start ? -1 : 1; //ending points before starting
  96.         }
  97.     }
  98.     return $point1->value > $point2->value;
  99. }
  100.  
  101. function result_comparer(ResultSegment &$line1, ResultSegment &$line2) {
  102.     if ($line1->num_users == $line2->num_users) {
  103.         return $line1->duration > $line2->duration;
  104.     }
  105.     return $line1->num_users > $line2->num_users;
  106. }
  107.  
  108.  
  109. //1) Create line-segments (assumption: for each line-segment, start_value is less than end_value)
  110. $segments = array(
  111.         new LineSegment(1, 10, 20),
  112.         new LineSegment(1, 40, 74),
  113.         new LineSegment(2, 19, 25),
  114.         new LineSegment(2, 34, 50),
  115.         new LineSegment(3, 15, 25),
  116.         new LineSegment(3, 55, 90),
  117.     );
  118.  
  119. //1a) TODO: merge same-user segments that start/end at the same time.
  120.  
  121. //2) create a sorted array of all endpoints (start and end)
  122. $endpoints = array();
  123. foreach ($segments as $segment) {
  124.     $endpoints[] = $segment->start_point;
  125.     $endpoints[] = $segment->end_point;
  126. }
  127. usort($endpoints, 'endpoint_comparer');
  128.  
  129. //3) Initialize sweep-line
  130. $sweepline = new Sweepline();
  131.  
  132. //4) Execute sweep-line
  133. $results = $sweepline->execute($endpoints);
  134.  
  135. //5) Sort results
  136. usort($results, 'result_comparer');
  137. $results = array_reverse($results);
  138.  
  139.  
  140. echo "<pre>";
  141. print_r($results);
  142. echo "</pre>";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement