Advertisement
quang4dev

Traveler Man solver

Feb 13th, 2023
857
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.69 KB | None | 0 0
  1. <?php
  2.  
  3. header('Content-type: text/plain');
  4.  
  5. /**
  6.  * Class City
  7.  */
  8. class City
  9. {
  10.     public $name;
  11.     public $longitude;
  12.     public $latitude;
  13.  
  14.     public function __construct($name, $latitude, $longitude)
  15.     {
  16.         $this->name         = $name;
  17.         $this->latitude     = $latitude;
  18.         $this->longitude    = $longitude;
  19.     }
  20. }
  21.  
  22. /**
  23.  * Class ShortestDistance
  24.  * Get shortest distance
  25.  */
  26. class ShortestDistance
  27. {
  28.     protected $n                = 0;
  29.     protected $locations        = array();
  30.     protected $costMatrix       = array();
  31.     protected $cities           = [];
  32.  
  33.     private $shortestRoutes     = [];
  34.     private $shortestDistance   = 0;
  35.  
  36.     /**
  37.      * Solve the problem
  38.      */
  39.     public function solve()
  40.     {
  41.         $this->cities   = array_reverse($this->cities);
  42.         $currentCity    = null;
  43.         $firstCity      = array_pop($this->cities);
  44.         while (!empty($this->cities)) {
  45.             $currentCity        = $currentCity ?: $firstCity;
  46.             $shortestDistance   = INF;
  47.             $shortestRoute      = [];
  48.             foreach ($this->cities as $key => $city) {
  49.                 $distant = round($this->distance($currentCity, $city), 2);
  50.                 if ($shortestDistance > $distant) {
  51.                     $shortestDistance   = $distant;
  52.                     $shortestRoute      = [$currentCity, $city, 'distant' => $distant];
  53.                     $nearestCity        = $city;
  54.                     $index              = $key;
  55.                 }
  56.             }
  57.             if (isset($index) && isset($nearestCity)) {
  58.                 unset($this->cities[$index]);
  59.                 $currentCity            = $nearestCity;
  60.                 $this->shortestRoutes[] = $shortestRoute;
  61.                 $this->shortestDistance += $shortestDistance;
  62.             } else {
  63.                 break;
  64.             }
  65.         }
  66.         // back to first city
  67.         if ($currentCity) {
  68.             $distant                = round($this->distance($currentCity, $firstCity), 2);
  69.             $this->shortestRoutes[] = [$currentCity, $firstCity, 'distant' => $distant];
  70.             $this->shortestDistance += $distant;
  71.         }
  72.     }
  73.  
  74.     /**
  75.      * Add City
  76.      * @param $name
  77.      * @param $latitude
  78.      * @param $longitude
  79.      */
  80.     public function addCity($name, $latitude, $longitude)
  81.     {
  82.         $this->cities[] = new City($name, $latitude, $longitude);
  83.     }
  84.  
  85.     /**
  86.      * Return Routes
  87.      * @return string
  88.      */
  89.     public function getShortestRoutes()
  90.     {
  91.         $routes = [];
  92.         foreach ($this->shortestRoutes as $route) {
  93.             $routes[] = $route[0]->name;
  94.         }
  95.         return implode("\n", $routes);
  96.     }
  97.  
  98.     /**
  99.      * Return Distance
  100.      * @return int
  101.      */
  102.     public function getShortestDistance()
  103.     {
  104.         return $this->shortestDistance;
  105.     }
  106.  
  107.     /**
  108.      * Code copied from https://www.geodatasource.com/developers/php
  109.      *
  110.      * @param City $currentCity
  111.      * @param City $city
  112.      * @param string $unit
  113.      * @return float|int
  114.      */
  115.     private function distance($currentCity, $city, $unit = 'M')
  116.     {
  117.         $lat1 = $currentCity->latitude;
  118.         $lon1 = $currentCity->longitude;
  119.         $lat2 = $city->latitude;
  120.         $lon2 = $city->longitude;
  121.         if ($lat1 == $lat2 && $lon1 == $lon2) {
  122.             return 0;
  123.         }
  124.         $theta  = $lon1 - $lon2;
  125.         $dist   =
  126.             sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +
  127.             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
  128.         $dist   = acos($dist);
  129.         $dist   = rad2deg($dist);
  130.         $miles  = $dist * 60 * 1.1515;
  131.         $unit   = strtoupper($unit);
  132.  
  133.  
  134.         if ($unit == "K") {
  135.             return ($miles * 1.609344);
  136.         } elseif ($unit == "N") {
  137.             return ($miles * 0.8684);
  138.         } else {
  139.             return $miles;
  140.         }
  141.     }
  142. }
  143.  
  144. try {
  145.     $shortestDistance = new ShortestDistance();
  146.  
  147.     $cities = fopen("cities.txt", "r") or die("Unable to open file!");
  148.     // Output one line until end-of-file
  149.     while (!feof($cities)) {
  150.         $city       = fgets($cities);
  151.         $location   = explode(" ", $city);
  152.         $longitude  = array_pop($location);
  153.         $latitude   = array_pop($location);
  154.         $longitude  = trim(str_replace(array("\n", "\r"), ' ', $longitude));
  155.         $shortestDistance->addCity(implode(" ", $location), (double)$latitude, (double)$longitude);
  156.     }
  157.     fclose($cities);
  158.  
  159.     $shortestDistance->solve();
  160.     echo $shortestDistance->getShortestRoutes();
  161. //    echo "\nTotal distance: " . $shortestDistance->getShortestDistance() . "\n\n";
  162. } catch (Exception $e) {
  163.     echo $e;
  164.     exit;
  165. }
  166.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement