Files
freeCodeCamp/curriculum/challenges/russian/08-coding-interview-prep/rosetta-code/circles-of-given-radius-through-two-points.russian.md

6.9 KiB
Raw Blame History

title, id, challengeType, forumTopicId, localeTitle
title id challengeType forumTopicId localeTitle
Circles of given radius through two points 5951815dd895584b06884620 5 302231 Круги заданного радиуса через две точки

Description

Учитывая две точки на плоскости и радиус, обычно через две точки могут быть проведены два круга заданного радиуса.

Исключения: радиус нуля должен рассматриваться как никогда не описывающий круги (за исключением случая, когда точки совпадают). Если точки совпадают, то может быть проведено бесконечное число кругов с точкой на их окружности, если радиус не равен нулю, а затем сворачивает круги в точку. Если точки образуют диаметр, верните один круг. Если точки слишком далеки друг от друга, круги не могут быть нарисованы. Задача: выполнить функцию, которая принимает две точки и радиус и возвращает два круга через эти точки. Для каждого результирующего круга укажите координаты для центра каждого круга, округленного до четырех десятичных цифр. Возвращает каждую координату в виде массива и координирует ее как массив массивов. Для краевых случаев возвращайте следующее: если точки находятся на диаметре, верните одну точку. Если радиус также равен нулю, верните "Radius Zero" . Если точки совпадают, верните "Coincident point. Infinite solutions" . Если точки находятся дальше друг от друга, чем диаметр, верните "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
Ref: Поиск центра круга из двух точек и радиуса из математического форума @ Drexel

Instructions

Implement a function that takes two points and a radius and returns the two circles through those points. For each resulting circle, provide the coordinates for the center of each circle rounded to four decimal digits. Return each coordinate as an array, and coordinates as an array of arrays. For edge cases, return the following:
  • 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".
Sample inputs:
      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 Tests

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;
}