Contents
raw puzzle

Codingame Solution: Darts

Robert Eisele

Original Problem

A group of your friends want to have a dart throwing competition with a unique target. They've asked you, their tech savvy friend, to automate the scoring as they often squabble over scoring, and have trouble keeping track of who's turn it is to throw.

The target is a square. The square has a circle inscribed within whose diameter matches the width of the square. The circle, in turn, encompasses a diamond whose width from corner to corner matches the circle's diameter.

Darts landing within the square but not within the circle or diamond are worth 5 points. Darts landing within the circle but not within the diamond are worth 10 points. Darts landing within the diamond are worth 15 points.

In the event of a tie, competitors should be ordered as they were in the name list, so competitors appearing earlier in the name list are listed earlier in ties.

Note: darts landing on the edge of a shape are considered within the shape.
Note: The center of the square, circle, and diamond are at (0,0).
Input
Line 1: SIZE of square as integer.
Line 2: The number of competitors in name list, N
Next N lines: name of a single competitor in name list.
Line N+1: Number of throws, T
Next TLines: Name of competitor, integer x coordinate, integer y coordinate of throw each separated by a space name X Y.
Output
A line with competitor's name, a space, and that competitor's score, in descending order by score.
Constraints
10 <= SIZE <= 100
1 <= N <= 10
1 <= T <= 50
-300 <= X <= 300
-300 <= Y <= 300

Solution

The first step is to transform the rules into inequalities describing the dart board. We start from the smallest, the diamond, continue to the circle and finally check if the board was hit at all. To simplify the calculation, we work with the radius instead of the diameter:

function calcScore(x, y) {

  if (Math.abs(x) + Math.abs(y) <= R)
    return 15; // Diamond

  if (Math.hypot(x, y) <= R)
    return 10; // Circle

  if (-R <= Math.min(x, y) && Math.max(x, y) <= R)
    return 5; // Square

  return 0; // Fail
}

Now the second step is, we read in the radius, store the names in a map holding the final score and add all game rounds to the map, calculated by the function before. At the end we sort the names extracted from the keys by their score and print it to the console:

const map = {};
const R = +readline() / 2;

const N = +readline();
for (let i = 0; i < N; i++) {
  const name = readline();
  map[name] = 0;
}

const T = +readline();
for (let i = 0; i < T; i++) {
  const inputs = readline().split(' ');
  map[inputs[0]]+= calcScore(+inputs[1], +inputs[2]);
}

Object.keys(map)
  .sort((a, b) => (map[b] - map[a]) || (a - b))
  .forEach(x => print(x + " "+ map[x]));