-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
/
Copy pathTriangle.js
157 lines (143 loc) · 4.23 KB
/
Triangle.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
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* This class represents a Triangle and provides methods to calculate its area and perimeter
* based on either all three sides or the base and height.
* @see {@link https://en.wikipedia.org/wiki/Triangle}
* @class
*/
export default class Triangle {
/** @private */
#base
/** @private */
#height
/** @private */
#sides
/**
* Creates a triangle instance.
* @constructor
* @param {...number} args - The dimensions of the triangle.
* @throws {Error} Will throw an error if the number of arguments is invalid or if the triangle is invalid.
*/
constructor(...args) {
if (args.length === 2) {
this.#initializeFromBaseAndHeight(...args)
} else if (args.length === 3) {
this.#initializeFromSides(...args)
} else {
throw new Error(
'Invalid number of arguments. Use either (base, height) or (sideA, sideB, sideC).'
)
}
}
/**
* Initializes the triangle from base and height.
* @private
* @param {number} base - The base of the triangle.
* @param {number} height - The height of the triangle.
*/
#initializeFromBaseAndHeight(base, height) {
this.#base = base
this.#height = height
this.#sides = [base, null, null]
}
/**
* Initializes the triangle from three sides.
* @private
* @param {number} sideA - The length of side A.
* @param {number} sideB - The length of side B.
* @param {number} sideC - The length of side C.
* @throws {Error} Will throw an error if the triangle is invalid.
*/
#initializeFromSides(sideA, sideB, sideC) {
if (!this.#isValidTriangle(sideA, sideB, sideC)) {
throw new Error(
'Invalid triangle: The sum of any two sides must be greater than the third side.'
)
}
this.#sides = [sideA, sideB, sideC]
this.#base = sideA // Assuming base is one of the sides for consistency
this.#height = null
}
/**
* Checks if three sides can form a valid triangle.
* @private
* @param {number} a - The length of side A.
* @param {number} b - The length of side B.
* @param {number} c - The length of side C.
* @returns {boolean} True if the triangle is valid; false otherwise.
*/
#isValidTriangle(a, b, c) {
return a + b > c && b + c > a && c + a > b
}
/**
* Calculates the area of the triangle.
* @public
* @returns {number} The area of the triangle.
*/
area() {
if (this.#height !== null) {
return 0.5 * this.#base * this.#height
}
// Using Heron's formula
const [a, b, c] = this.#sides
const s = (a + b + c) / 2
return Math.sqrt(s * (s - a) * (s - b) * (s - c))
}
/**
* Calculates the perimeter of the triangle.
* @public
* @returns {number} The perimeter of the triangle.
* @throws {Error} Will throw an error if not all sides are known.
*/
perimeter() {
if (this.#sides.some((side) => side === null)) {
throw new Error('Cannot calculate perimeter: not all sides are known.')
}
return this.#sides.reduce((sum, side) => sum + side, 0)
}
/**
* Returns a string representation of the triangle.
* @public
* @returns {string} A string describing the triangle's dimensions and area/perimeter.
*/
toString() {
const areaValue = this.area()
let perimeterValue
// Check if all sides are known for perimeter calculation
if (this.#sides.some((side) => side === null)) {
perimeterValue = 'unknown'
} else {
perimeterValue = this.perimeter()
}
return (
`Triangle: base = ${this.#base}, height = ${
this.#height ?? 'unknown'
}, ` +
`sides = ${this.#sides.map((side) => side ?? 'unknown').join(', ')}, ` +
`area = ${areaValue}, perimeter = ${perimeterValue}`
)
}
/**
* Gets the base of the triangle.
* @public
* @returns {number} The base of the triangle.
*/
get base() {
return this.#base
}
/**
* Gets the height of the triangle.
* @public
* @returns {number|null} The height of the triangle or null if not defined.
*/
get height() {
return this.#height
}
/**
* Gets the lengths of all sides of the triangle.
* @public
* @returns {Array<number|null>} An array containing lengths of all three sides or null for unknown sides.
*/
get sides() {
return this.#sides
}
}