-
Notifications
You must be signed in to change notification settings - Fork 2
/
E.js
88 lines (73 loc) · 4.43 KB
/
E.js
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
const getTrianglePointVectorProducts = ({ A: [xA, yA], B: [xB, yB], C: [xC, yC] }, [pointX, pointY]) => {
const ABxAP = (xA - pointX) * (yB - yA) - (xB - xA) * (yA - pointY);
const BCxBP = (xB - pointX) * (yC - yB) - (xC - xB) * (yB - pointY);
const CAxCP = (xC - pointX) * (yA - yC) - (xA - xC) * (yC - pointY);
return [ABxAP, BCxBP, CAxCP];
};
const distanceBetweenTwoPoint = ([x1, y1], [x2, y2]) => Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
/**
* "E. Точка и треугольник" {@link "https://contest.yandex.ru/contest/28730/problems/E}
*
* @param { number } cathetus натуральное число d (не превосходящее 1000)
* @param { [ number, number ] } pointXY координаты точки X – два целых числа из диапазона от –1000 до 1000.
*
* @return { 0|1|2|3 } Если точка лежит внутри, на стороне треугольника или совпадает с одной из
* вершин, то выведите число 0. Если точка лежит вне треугольника, то выведите номер вершины
* треугольника, к которой она расположена ближе всего (1 – к вершине A, 2 – к B, 3 – к C). Если
* точка расположена на одинаковом расстоянии от двух вершин, выведите ту вершину, номер которой
* меньше.
*/
function calcBetterCoordForBuildSchool(cathetus, pointXY) {
const triangleVertices = { A: [0, 0], B: [cathetus, 0], C: [0, cathetus] };
const vectorProducts = getTrianglePointVectorProducts(triangleVertices, pointXY);
if (
vectorProducts.some((v) => v === 0) ||
vectorProducts.every((v) => v > 0) ||
vectorProducts.every((v) => v < 0)
) {
// Если все три значения одинакового знака, то точка внутри треугольника.
// Если значение равно нулю, значит точка лежит на стороне треугольника.
// В ином случае, точка вне треугольника.
return 0;
}
const distanceFromPointToTriangleVertices = Object.values(triangleVertices).map((coord) =>
distanceBetweenTwoPoint(pointXY, coord)
);
const minDistanceToVerticesTriangleFromPoint = Math.min(...distanceFromPointToTriangleVertices);
return distanceFromPointToTriangleVertices.indexOf(minDistanceToVerticesTriangleFromPoint) + 1;
}
// eslint-disable-next-line no-unused-vars
function inputProcessing(lines) {
const cathetus = Number(lines[0]);
const pointXY = lines[1].split(' ').map(Number);
return calcBetterCoordForBuildSchool(cathetus, pointXY);
}
// SECOND
const getAreaTriangleByCoords = ({ A: [xA, yA], B: [xB, yB], C: [xC, yC] }) =>
Math.abs((xB - xA) * (yC - yA) - (xC - xA) * (yB - yA)) / 2;
// eslint-disable-next-line no-unused-vars
function calcBetterCoordForBuildSchoolByArea(cathetus, pointXY) {
// Метод сравнения площадей - по формуле Герона находятся площади 3-х треугольников которые
// образует точка с каждой стороной треугольника, далее находится площадь самого треугольника и
// сравнивается с суммой 3ех предыдущих треугольников, если суммы равны то значит точка
// принадлежит треугольнику.
const triangleVertices = { A: [0, 0], B: [cathetus, 0], C: [0, cathetus] };
const triangleArea = getAreaTriangleByCoords(triangleVertices);
const trianglesPointWithSide = [
{ ...triangleVertices, A: pointXY },
{ ...triangleVertices, B: pointXY },
{ ...triangleVertices, C: pointXY },
];
const trianglesPointWithSideAreasSum = trianglesPointWithSide
.map(getAreaTriangleByCoords)
.reduce((sum, n) => sum + n, 0);
if (triangleArea === trianglesPointWithSideAreasSum) {
return 0;
}
const distanceFromPointToTriangleVertices = Object.values(triangleVertices).map((coord) =>
distanceBetweenTwoPoint(pointXY, coord)
);
const minDistanceToVerticesTriangleFromPoint = Math.min(...distanceFromPointToTriangleVertices);
return distanceFromPointToTriangleVertices.indexOf(minDistanceToVerticesTriangleFromPoint) + 1;
}
export default inputProcessing;