#include <vector>
#include <algorithm>
#include <numeric>
#include <iterator>
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstddef>
#include <cassert>
#include <cmath>
struct pos {
double x, y;
};
std::ostream &operator<<( std::ostream &os, const pos &p ) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
class color {
private:
std::string name;
explicit color( const std::string &s ): name(s) { }
public:
std::string get_name( ) const { return name; }
static const color BLACK;
static const color RED;
static const color WHITE;
};
const color color::BLACK( "black" );
const color color::RED( "red" );
const color color::WHITE( "blue" );
std::ostream &operator<<( std::ostream &os, const color &c ) {
os << c.get_name( );
return os;
}
class Shape {
private:
virtual double area_impl( ) const = 0;
virtual void print_impl( std::ostream &os ) const = 0;
public:
double area( ) const { return area_impl( ); }
void print( std::ostream &os ) const { print_impl( os ); }
};
std::ostream &operator<<( std::ostream &os, const Shape &s ) {
s.print( os );
return os;
}
class Triangle: public Shape {
private:
pos p[3];
color col;
double area_impl( ) const {
double x1 = std::fabs( p[1].x-p[0].x );
double x2 = std::fabs( p[2].x-p[0].x );
double y1 = std::fabs( p[1].y-p[0].y );
double y2 = std::fabs( p[2].y-p[0].y );
return std::fabs( x1*y2 - x2*y1 )/2.0;
}
void print_impl( std::ostream &os ) const {
os << "color=" << col << ", p[0]=" << p[0] << ", p[1]=" << p[1] << ", p[2]=" << p[2];
}
public:
Triangle( const pos (&px)[3], const color &c ): col(c) {
std::copy( px, px+3, p );
}
};
class Circle: public Shape {
private:
pos centre;
double radius;
color col;
double area_impl( ) const {
return radius * radius * 3.14;
}
void print_impl( std::ostream &os ) const {
os << "color=" << col << ", centre=" << centre << ", radious=" << radius;
}
public:
Circle( const pos &c, double r, const color &cx ): centre(c), radius(r), col(cx) { }
};
// ------------------------------------------------------------
namespace {
static const double x_min = 0.0; // excl.
static const double x_max = 500.0; // excl.
static const double y_min = 0.0; // excl.
static const double y_max = 600.0; // excl.
static const double r_min = x_min; // excl.
static const double r_max = x_max; // excl.
static const unsigned int n_min = 3; // incl.
static const unsigned int n_max = 10; // incl.
}
double generate_random_double( double dmin, double dmax ) {
double diff = dmax-dmin;
double dr = static_cast<double>(std::rand( )) / RAND_MAX;
if( dr == 0 ) return generate_random_double( dmin, dmax );
return dmin + diff * dr;
}
color generate_random_color( ) {
switch( std::rand( ) % 3 ) {
case 0: return color::BLACK;
case 1: return color::RED;
default: return color::WHITE;
}
}
pos generate_random_pos( ) {
pos p = { generate_random_double( x_min, x_max ), generate_random_double( y_min, y_max ) };
return p;
}
Triangle *generate_random_triangle( ) {
color c = generate_random_color( );
pos p[3];
for( int i = 0; i < sizeof(p)/sizeof(p[0]); ++i ) p[i] = generate_random_pos( );
return new Triangle( p, c );
}
Circle *generate_random_circle( ) {
color c = generate_random_color( );
pos p = generate_random_pos( );
double r = generate_random_double( r_min, r_max );
return new Circle( p, r, c );
}
int main( ) {
assert( n_min >= 2 );
unsigned int n = std::rand( ) % ( n_max-n_min + 1 ) + n_min;
std::vector<Shape*> v;
v.push_back( generate_random_triangle( ));
v.push_back( generate_random_circle( ));
for( unsigned int i = 0; i < n-2; ++i ) {
if( std::rand( ) & 1 ) {
v.push_back( generate_random_triangle( ));
}
else {
v.push_back( generate_random_circle( ));
}
}
for( std::vector<Shape*>::iterator it = v.begin( ); it != v.end( ); ++it ) {
std::cout << **it << std::endl;
}
std::vector<double> areas;
std::transform( v.begin( ), v.end( ), std::back_inserter( areas ), std::mem_fun( &Shape::area ));
std::cout << "sum_area = " << std::accumulate( areas.begin( ), areas.end( ), 0.0 ) << std::endl;
for( std::vector<Shape*>::iterator it = v.begin( ); it != v.end( ); ++it ) {
delete *it;
}
}