Soluție HackerRank pentru A Circle and a Square, subdomeniul Geometry, în C++14. Include cerința formatată, exemple, explicația pașilor și cod sursă.

  • Problemă: A Circle and a Square
  • Domeniu: Geometry
  • Limbaj: C++14

Challenge: A Circle and a Square

Scor cont: 35.0 / 35

Submission status: Accepted

Submission score: 1.0

Submission ID: 464727903

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/a-circle-and-a-square/problem

Cerință

In this challenge, you must implement part of a [raster graphics](https://en.wikipedia.org/wiki/Raster_graphics) editor that takes the coordinates of a circle and a square as input and draws them as filled-in shapes on a rectangular canvas.

---

The rectangular canvas consists of uniformly sized square pixels, and is w pixels wide, and h pixels high. Each point on the canvas belongs to a pixel, the intersection of two pixels has zero area, and each pixel is completely contained within the canvas.

The [Cartesian coordinate system](https://en.wikipedia.org/wiki/Cartesian_coordinate_system) set up in the following way:

- Point (0, 0) is the center of the top-left pixel of the canvas.
- Point (w - 1, 0) is the center of the top-right pixel of the canvas.
- Point (0, h - 1) is the center of the bottom-left pixel of the canvas.
- Point (w - 1, h - 1) is the center of the bottom-right pixel of the canvas.

Thus, all pixel centers have integer coordinates and if the center of a pixel has coordinates (x_c, y_c), then point (x, y) belongs to the pixel if and only if x in [x_c-0.5,x_c+0.5] and y in [y_c-0.5,y_c+0.5]. The two shapes should be drawn like so:

- The *circle* is centered at the integer coordinates (x_circle, y_circle) and has non-negative integer radius r. A pixel should be *black* as a part of the circle if and only if the Euclidean distance from the pixel's center to the center of the circle is *not* greater than r.

![image](https://s3.amazonaws.com/hr-assets/0/1487518469-2517e4de82-image-circle.png)

- The *square* is defined by the integer coordinates of two of its opposite corners (x_1, y_1) and (x_3, y_3). A pixel should be *black* as a part of the square if and only if its center falls within the square or along its border. The coordinates of different corners of the square do not coincide.

![image](https://s3.amazonaws.com/hr-assets/0/1487517200-3693c19c3f-image-square.png)

Given h, w, and the definition of the circle and the square, print a raster image of the canvas where each character is either a `.` (denoting a *white* pixel outside of both shapes) or a `#` (denoting a *black* pixel that's part of a shape).

Note: The first pixel of the first line of output should correspond to the top-left corner of the canvas.

Input Format

The first line contains two space-separated integers describing the respective values of w (canvas width) and h (canvas height).
The second line contains three space-separated integers describing the respective values of x_circle, y_circle, and r defining a circle with radius r centered at (x_circle, y_circle).
The third line contains four space-separated integers describing the respective values of x_1, y_1, x_3, y_3 defining a square with opposite corners at (x_1, y_1) and (x_3, y_3).

Output Format

Print h lines where each line contains w characters. Each character must be either a `.` (to denote a white pixel) or a `#` (to denote a black pixel). The first pixel of the first line of output corresponds to the top-left corner of the canvas.

Constraints

- 10 ≤ w, h ≤ 100
- -100 ≤ x_circle, y_circle, x_1, y_1, x_3, y_3 ≤ 200
- 0 ≤ r ≤ 100

Cod sursă

#include <bits/stdc++.h>

using namespace std;

int sgn( int x ) {
    if( x==0 ) return 0;
    return ( x < 0 ? -1 : 1 );
}

struct point {
    int x, y;

    point() : x(0), y(0) {}
    point( int a, int b) : x(a), y(b) {}

    bool operator == (const point &p ) const { return (x==p.x && y==p.y);}
    void operator *= (const int k ) { this->x *= k; this->y *= k; }

    point operator - (const point &p ) const { return point(x-p.x, y-p.y); }
    point operator + (const point &p ) const { return point(x+p.x, y+p.y); }

    point rotate ( ) { return point( -y, x ); }
    int distance( const point &p ) const { return (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y); }
    int cross( const point &p ) const { return x*p.y - p.x*y; }
};

int n, m, radius;
point centerCircle;
vector<point> rectangule( 5 );

bool isInCircle( const point &p ) {
    return (p.distance( centerCircle ) <= radius*radius);
}

void buildRectangule( int x1, int y1, int x2, int y2){
    point centerRectangule((x1+x2)/2, (y1+y2)/2);

    rectangule[ 0 ] = point(x1,y1);
    rectangule[ 1 ] = centerRectangule + (rectangule[ 0 ] - centerRectangule).rotate();
    rectangule[ 2 ] = point(x2,y2);
    rectangule[ 3 ] = centerRectangule + (rectangule[ 2 ] - centerRectangule).rotate();
    rectangule[ 4 ] = rectangule[ 0 ];
}

bool isInRectangule( const point &p ) {
    int sgns[ 4 ];
    for( int i = 0; i < 4; ++i ) {
        point vector1 = rectangule[ i+1 ] - rectangule[ i ];
        point vector2 = p - rectangule[ i ];
        sgns[ i ] = sgn( vector1.cross(vector2) );
    }
		
		// the sign of parallel edges have to be the same or 0
    return ( sgns[ 0 ]*sgns[ 2 ] >= 0 && sgns[ 1 ]*sgns[ 3 ] >= 0);
}

int main() {
    int x1,y1,x2,y2;
    cin >> m >> n;

    cin >> centerCircle.y >> centerCircle.x >> radius;
    centerCircle *= 10; radius *= 10;
    
    cin >> y1 >> x1 >> y2 >> x2;
    buildRectangule(x1*10, y1*10, x2*10, y2*10);

    point current;
    for( int x=0; x < n; ++x ) {
        for( int y=0; y < m; ++y ) {
            current = point( x, y );
            current *= 10;

            if( isInCircle( current ) || isInRectangule( current ) )
                cout << "#";
            else
                cout << ".";
        }
        cout << endl;
    }
    return 0;
}
HackerRank Geometry – A Circle and a Square