1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <iomanip>
struct stop
{
int stop_id ;
int start_time ;
int end_time ;
};
void print_stop( const stop& st )
{
std::cout << "stop #" << std::setw(2) << st.stop_id
<< "{start:" << st.start_time
<< " end:" << st.end_time << "}\n" ;
}
// return true if a and b share the same open and close times
bool have_same_times( stop a, stop b )
{ return a.start_time == b.start_time && a.end_time == b.end_time ; }
// return a random position in the container of size container_size
// uses the legacy random number generator std::rand()
// and a somewhat simplistic modulo division to fit the value in range
std::size_t random_pos( std::size_t container_size )
{ return std::rand() % container_size ; }
// pick two random stop positions with the same start and end times
// invariant: for every stop, there is at least one other stop with the same start and end times
std::pair<int,int> random_stops_with_same_times( const std::vector<stop>& stops )
{
// pick a random first stop
const stop stop_a = stops[ random_pos( stops.size() ) ] ;
// pick a different second stop with he same times at random
stop stop_b = stop_a ;
// caveat: unbounded loop
while( stop_b.stop_id == stop_a.stop_id || !have_same_times( stop_a, stop_b ) )
stop_b = stops[ random_pos( stops.size() ) ] ;
std::cout << "picked stops " ;
print_stop(stop_a) ;
std::cout << " and " ;
print_stop(stop_b) ;
return std::make_pair( stop_a.stop_id, stop_b.stop_id ) ;
}
// swap two random stops with the same start and end times in the route
void random_swap( std::vector<int>& route, const std::vector<stop>& stops )
{
// pick two random stops with the same start and end times
const std::pair<int,int> stops_to_be_swapped = random_stops_with_same_times(stops) ;
// locate the position of the stops in the route
const auto iter_a = std::find( route.begin(), route.end(), stops_to_be_swapped.first ) ;
const auto iter_b = std::find( route.begin(), route.end(), stops_to_be_swapped.second ) ;
// swap them
if( iter_a != route.end() && iter_b != route.end() )
{
std::cout << "swapping stops " << *iter_a << " and " << *iter_b << '\n' ;
std::iter_swap( iter_a, iter_b ) ;
}
}
void print_route( const std::vector<int>& route )
{
for( int v : route ) std::cout << std::setw(3) << v ;
std::cout << '\n' ;
}
int main()
{
std::srand( std::time(nullptr) ) ; // seed the legacy rng
// a route is a sequence of stops (identified by stop_ids)
// every stop in included once in a route
std::vector< std::vector<int> > routes =
{
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
{ 11, 9, 7, 5, 3, 12, 10, 8, 6, 4, 2, 1 },
{ 12, 6, 5, 4, 7, 8, 9, 3, 2, 1, 11, 10 }
};
// stop_id, start_time and end_time for each stop
std::vector<stop> stops
{
{ 1, 0, 24 },
{ 2, 0, 24 },
{ 3, 7, 24 },
{ 4, 0, 24 },
{ 5, 0, 7 },
{ 6, 7, 24 },
{ 7, 7, 24 },
{ 8, 0, 7 },
{ 9, 0, 24 },
{ 10, 0, 24 },
{ 11, 0, 24 },
{ 12, 7, 24 }
};
for( auto& rt : routes )
{
print_route(rt) ;
random_swap( rt, stops ) ;
print_route(rt) ;
std::cout << "\n\n" ;
}
}
| |