Почти прямоугольный треугольник.
На уроке геометрии Вася узнал, что треугольник называется прямоугольным, если он невырожденный, а один из его углов прямой. Вася тут же захотел нарисовать такой треугольник: он отметил на листке бумаги 3 точки с целочисленными координатами, соединил их отрезками прямых и показал Пете. Но тот сказал, что васин треугольник не прямоугольный, а почти прямоугольный: сам треугольник не является прямоугольным, но можно подвинуть одну из точек на расстояние ровно 1 так, чтобы координаты остались целыми, и треугольник стал прямоугольным. Вася просит вас помочь ему выяснить, не обманывает ли его Петя. По координатам вершин треугольника определите, является ли он прямоугольным, почти прямоугольным, или же не является ни тем, ни другим.
Формат ввода
В первой строке входного файла через пробел записано 6 целых чисел x1, y1, x2, y2, x3, y3 — координаты вершин треугольника. Все координаты целые и не превосходят по модулю 100. Гарантируется, что треугольник невырожденный, т. е. его площадь не равна нулю.
Формат вывода
Если заданный треугольник является прямоугольным, выведите RIGHT, если он является почти прямоугольным, выведите ALMOST, и если он не является ни тем, ни другим, выведите NEITHER.
C/C++
Задача на C++
#include
#include
#include
#include
using namespace std;
class Point {
public:
double length(const Point& p)const {
return sqrt(pow(p.x_ - x_, 2) + pow(p.y_ - y_, 2));
}
void move_x(const int dx) {
x_ += dx;
}
void move_y(const int dy) {
y_ += dy;
}
private:
int x_;
int y_;
friend istream& operator>>(istream& inp, Point& p) {
return inp >> p.x_ >> p.y_;
}
};
class RightTriangle {
public:
bool right()const {
const auto [a, b, c] = sides();
const auto h = (a > b) ? (a > c) ? a : c : (b > c) ? b : c;
const auto mn = (a < b) ? (a < c) ? a : c : (b < c) ? b : c;
const auto md = perimeter() - h - mn;
return fabs(h * h - mn * mn - md * md) < 1e-12;
}
bool almost()const {
auto tmp = *this;
array points{ &tmp.a_, &tmp.b_, &tmp.c_ };
for (auto& point : points) {
for (auto i = 0; i move_y(1); break;
case 1: point->move_x(1); break;
case 2: point->move_y(-1); break;
case 3: point->move_y(-1); break;
case 4: point->move_x(-1); break;
case 5: point->move_x(-1); break;
case 6: point->move_y(1); break;
case 7: point->move_y(1); break;
case 8: point->move_x(1); break;
}
if (tmp.right()) return true;
}
}
return false;
}
double perimeter()const {
const auto [a, b, c] = sides();
return a + b + c;
}
private:
Point a_;
Point b_;
Point c_;
friend istream& operator>>(istream& inp, RightTriangle& rt) {
return inp >> rt.a_ >> rt.b_ >> rt.c_;
}
tuple sides()const {
const auto ab = a_.length(b_);
const auto bc = b_.length(c_);
const auto ca = c_.length(a_);
return { ab, bc, ca };
}
};
int main() {
RightTriangle rt;
cin >> rt;
if (rt.right()) puts("RIGHT");
else if (rt.almost()) puts("ALMOST");
else puts("NEITHER");
}