Skip to content

Commit c679857

Browse files
committed
Added hard/intersecting_lines
1 parent efb6457 commit c679857

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

hard/intersecting_lines.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* Using the JavaScript language, have the function intersectingLines(strArr)
3+
* take strArr which will be an array of 4 coordinates in the form: (x,y). Your
4+
* program should take these points where the first 2 form a line and the last 2
5+
* form a line, and determine whether the lines intersect, and if they do, at
6+
* what point. For example: if strArr is ["(3,0)","(1,4)","(0,-3)","(2,3)"],
7+
* then the line created by (3,0) and (1,4) and the line created by (0,-3) (2,3)
8+
* intersect at (9/5,12/5). Your output should therefore be the 2 points in
9+
* fraction form in the following format: (9/5,12/5). If there is no denominator
10+
* for the resulting points, then the output should just be the integers like
11+
* so: (12,3). If any of the resulting points is negative, add the negative sign
12+
* to the numerator like so: (-491/63,-491/67). If there is no intersection,
13+
* your output should return the string "no intersection". The input points and
14+
* the resulting points can be positive or negative integers.
15+
*
16+
* https://www.coderbyte.com/results/bhanson:Intersecting%20Lines:JavaScript
17+
*
18+
* @param {array} strArr
19+
* @return {string}
20+
*/
21+
function intersectingLines(strArr) {
22+
// https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
23+
const [x1, y1, x2, y2, x3, y3, x4, y4] = strArr
24+
.join('')
25+
.match(/-?\d+/g)
26+
.map(Number);
27+
28+
// https://wikimedia.org/api/rest_v1/media/math/render/svg/c51a9b486a6ef5a7a08b92d75e71a07888034a9a
29+
const pxNumerator =
30+
(x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
31+
const pxDenominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
32+
33+
const pyNumerator =
34+
(x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
35+
const pyDenominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
36+
37+
// The problem is solved at this point, but we need to format the answer to spec
38+
39+
if (pxDenominator === 0 || pyDenominator === 0) {
40+
return 'no intersection';
41+
}
42+
43+
const pxString = formatFractionToString(pxNumerator, pxDenominator);
44+
const pyString = formatFractionToString(pyNumerator, pyDenominator);
45+
46+
return `(${pxString},${pyString})`;
47+
}
48+
49+
function greatestCommonFactor(num0, num1) {
50+
num0 = Math.abs(num0);
51+
num1 = Math.abs(num1);
52+
53+
if (num0 === 0) return num1;
54+
if (num1 === 0) return num0;
55+
56+
const max = Math.min(num0, num1);
57+
let gcf = 1;
58+
for (let i = 1; i <= max; i++) {
59+
if (num0 % i === 0 && num1 % i === 0) {
60+
gcf = i;
61+
}
62+
}
63+
return gcf;
64+
}
65+
66+
function formatFractionToString(numerator, denominator) {
67+
// Reduce fraction
68+
const gcf = greatestCommonFactor(numerator, denominator);
69+
numerator /= gcf;
70+
denominator /= gcf;
71+
72+
// Combine signs and remove from elements to add at end
73+
sign = Math.sign(numerator) * Math.sign(denominator) === 1 ? '' : '-';
74+
numerator = Math.abs(numerator);
75+
denominator = Math.abs(denominator);
76+
77+
let str;
78+
if (numerator === 0) {
79+
str = '0';
80+
} else if (numerator === denominator || denominator === 1) {
81+
str = `${sign}${numerator}`;
82+
} else {
83+
str = `${sign}${numerator}/${denominator}`;
84+
}
85+
86+
return str;
87+
}
88+
89+
module.exports = intersectingLines;

hard/intersecting_lines.test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const intersectingLines = require('./intersecting_lines');
2+
3+
describe('intersectingLines()', () => {
4+
test('passes Coderbyte.com tests', () => {
5+
expect(intersectingLines(['(3,0)', '(1,4)', '(0,-3)', '(2,3)'])).toBe(
6+
'(9/5,12/5)'
7+
);
8+
9+
expect(
10+
intersectingLines(['(0,15)', '(3,-12)', '(2,1)', '(13,7)'])
11+
).toBe('(166/105,27/35)');
12+
13+
expect(
14+
intersectingLines(['(1,2)', '(3,4)', '(-5,-6)', '(-7,-8)'])
15+
).toBe('no intersection');
16+
17+
expect(
18+
intersectingLines(['(10,11)', '(12,16)', '(6,7)', '(18,-4)'])
19+
).toBe('(318/41,221/41)');
20+
21+
expect(intersectingLines(['(0,0)', '(0,-1)', '(1,1)', '(0,1)'])).toBe(
22+
'(0,1)'
23+
);
24+
25+
expect(
26+
intersectingLines(['(9,-2)', '(-2,9)', '(3,4)', '(10,11)'])
27+
).toBe('(3,4)');
28+
29+
expect(
30+
intersectingLines(['(100,5)', '(6,2)', '(2,6)', '(5,100)'])
31+
).toBe('(170/91,170/91)');
32+
33+
expect(
34+
intersectingLines(['(1,-1)', '(1,1)', '(-5,-5)', '(-7,-7)'])
35+
).toBe('(1,1)');
36+
37+
expect(
38+
intersectingLines(['(6,12)', '(7,14)', '(-100,-3)', '(-3,-5)'])
39+
).toBe('(-491/196,-491/98)');
40+
41+
expect(
42+
intersectingLines(['(4,3)', '(2,1)', '(-7,-6)', '(-4,-1)'])
43+
).toBe('(-10,-11)');
44+
});
45+
});

0 commit comments

Comments
 (0)