4.8 KiB
4.8 KiB
title | id | challengeType | forumTopicId |
---|---|---|---|
Circles of given radius through two points | 5951815dd895584b06884620 | 5 | 302231 |
Description
- A radius of zero should be treated as never describing circles (except in the case where the points are coincident).
- If the points are coincident then an infinite number of circles with the point on their circumference can be drawn, unless the radius is equal to zero as well which then collapses the circles to a point.
- If the points form a diameter then return a single circle.
- If the points are too far apart then no circles can be drawn.
Instructions
- If points are on the diameter, return one point. If the radius is also zero however, return
"Radius Zero"
. - If points are coincident, return
"Coincident point. Infinite solutions"
. - If points are farther apart than the diameter, return
"No intersection. Points further apart than circle diameter"
.
p1 p2 r 0.1234, 0.9876 0.8765, 0.2345 2.0 0.0000, 2.0000 0.0000, 0.0000 1.0 0.1234, 0.9876 0.1234, 0.9876 2.0 0.1234, 0.9876 0.8765, 0.2345 0.5 0.1234, 0.9876 0.1234, 0.9876 0.0
Tests
tests:
- text: <code>getCircles</code> is a function.
testString: assert(typeof getCircles === 'function');
- text: <code>getCircles([0.1234, 0.9876], [0.8765, 0.2345], 2.0)</code> should return <code>[[1.8631, 1.9742], [-0.8632, -0.7521]]</code>.
testString: assert.deepEqual(getCircles(...testCases[0]), answers[0]);
- text: <code>getCircles([0.0000, 2.0000], [0.0000, 0.0000], 1.0)</code> should return <code>[0, 1]</code>
testString: assert.deepEqual(getCircles(...testCases[1]), answers[1]);
- text: <code>getCircles([0.1234, 0.9876], [0.1234, 0.9876], 2.0)</code> should return <code>Coincident point. Infinite solutions</code>
testString: assert.deepEqual(getCircles(...testCases[2]), answers[2]);
- text: <code>getCircles([0.1234, 0.9876], [0.8765, 0.2345], 0.5)</code> should return <code>No intersection. Points further apart than circle diameter</code>
testString: assert.deepEqual(getCircles(...testCases[3]), answers[3]);
- text: <code>getCircles([0.1234, 0.9876], [0.1234, 0.9876], 0.0)</code> should return <code>Radius Zero</code>
testString: assert.deepEqual(getCircles(...testCases[4]), answers[4]);
Challenge Seed
function getCircles(...args) {
// Good luck!
return true;
}
After Test
const testCases = [
[[0.1234, 0.9876], [0.8765, 0.2345], 2.0],
[[0.0000, 2.0000], [0.0000, 0.0000], 1.0],
[[0.1234, 0.9876], [0.1234, 0.9876], 2.0],
[[0.1234, 0.9876], [0.8765, 0.2345], 0.5],
[[0.1234, 0.9876], [0.1234, 0.9876], 0.0]
];
const answers = [
[[1.8631, 1.9742], [-0.8632, -0.7521]],
[0, 1],
'Coincident point. Infinite solutions',
'No intersection. Points further apart than circle diameter',
'Radius Zero'
];
Solution
const hDist = (p1, p2) => Math.hypot(...p1.map((e, i) => e - p2[i])) / 2;
const pAng = (p1, p2) => Math.atan(p1.map((e, i) => e - p2[i]).reduce((p, c) => c / p, 1));
const solveF = (p, r) => t => [parseFloat((r * Math.cos(t) + p[0]).toFixed(4)), parseFloat((r * Math.sin(t) + p[1]).toFixed(4))];
const diamPoints = (p1, p2) => p1.map((e, i) => parseFloat((e + (p2[i] - e) / 2).toFixed(4)));
function getCircles(...args) {
const [p1, p2, s] = args;
const solve = solveF(p1, s);
const halfDist = hDist(p1, p2);
let msg = [];
switch (Math.sign(s - halfDist)) {
case 0:
msg = s ? diamPoints(p1, p2) :
'Radius Zero';
break;
case 1:
if (!halfDist) {
msg = 'Coincident point. Infinite solutions';
}
else {
const theta = pAng(p1, p2);
const theta2 = Math.acos(halfDist / s);
[1, -1].map(e => solve(theta + e * theta2)).forEach(
e => msg.push(e));
}
break;
case -1:
msg = 'No intersection. Points further apart than circle diameter';
break;
default:
msg = 'Reached the default';
}
return msg;
}