Back to Freecodecamp

Challenge 195: 2026 Winter Games Day 16: Curling

curriculum/challenges/english/blocks/daily-coding-challenges-javascript/697a49e9860d24853adef680.md

latest4.7 KB
Original Source

--description--

Given a 5x5 matrix representing the "house" at the end of a curling round, determine which team scores and how many points they score.

The layout:

  • The center cell (index [2, 2]) is the "button".
  • The 8 cells directly surrounding the button represent ring 1.
  • And the 16 cells on the outer edge of the house represent ring 2.

In the given matrix:

  • "." represents an empty space.
  • "R" represents a space with a red stone.
  • "Y" represents a space with a yellow stone.

Scoring rules:

  • Only one team can score per round.
  • The team with the stone closest to the button scores.
  • The scoring team earns 1 point for each of their stones that is closer to the button than the opponent's closest stone.
  • The lower the ring number, the closer to the center the stone is.
  • If both teams' closest stone is the same distance from the center, no team scores.

Return:

  • A string in the format "team: number_of_points". e.g: "R: 2".
  • or "No points awarded" if neither team scored any points.

For example, given:

js
[
  [".", ".", "R", ".", "."],
  [".", "R", ".", ".", "."],
  ["Y", ".", ".", ".", "."],
  [".", "R", ".", ".", "."],
  [".", ".", ".", ".", "."]
]

Return "R: 2". The two red stones in ring 1 are tied for the closest and are the only two stones closer than yellows closest.

--hints--

scoreCurling([[".", ".", "R", ".", "."], [".", "R", ".", ".", "."], ["Y", ".", ".", ".", "."], [".", "R", ".", ".", "."], [".", ".", ".", ".", "."]]) should return "R: 2".

js
assert.equal(scoreCurling([[".", ".", "R", ".", "."], [".", "R", ".", ".", "."], ["Y", ".", ".", ".", "."], [".", "R", ".", ".", "."], [".", ".", ".", ".", "."]]), "R: 2");

scoreCurling([[".", ".", "R", ".", "."], [".", ".", ".", ".", "."], [".", ".", "Y", ".", "R"], [".", ".", "Y", "Y", "."], [".", "Y", "R", "R", "."]]) should return "Y: 3".

js
assert.equal(scoreCurling([[".", ".", "R", ".", "."], [".", ".", ".", ".", "."], [".", ".", "Y", ".", "R"], [".", ".", "Y", "Y", "."], [".", "Y", "R", "R", "."]]), "Y: 3");

scoreCurling([[".", "R", "Y", ".", "."], ["Y", ".", ".", ".", "."], [".", ".", ".", ".", "."], [".", "Y", "R", "Y", "."], [".", ".", "R", "R", "."]]) should return "No points awarded".

js
assert.equal(scoreCurling([[".", "R", "Y", ".", "."], ["Y", ".", ".", ".", "."], [".", ".", ".", ".", "."], [".", "Y", "R", "Y", "."], [".", ".", "R", "R", "."]]), "No points awarded");

scoreCurling([[".", "Y", "Y", ".", "."], ["Y", ".", ".", "R", "."], [".", ".", "R", ".", "."], [".", ".", "R", "R", "."], [".", "Y", "R", "Y", "."]]) should return "R: 4".

js
assert.equal(scoreCurling([[".", "Y", "Y", ".", "."], ["Y", ".", ".", "R", "."], [".", ".", "R", ".", "."], [".", ".", "R", "R", "."], [".", "Y", "R", "Y", "."]]), "R: 4");

scoreCurling([["Y", "Y", "Y", "Y", "Y"], ["Y", "R", "R", "R", "Y"], ["Y", "R", "Y", "R", "Y"], ["Y", "R", "R", "R", "Y"], ["Y", "Y", "Y", "Y", "Y"]]) should return "Y: 1".

js
assert.equal(scoreCurling([["Y", "Y", "Y", "Y", "Y"], ["Y", "R", "R", "R", "Y"], ["Y", "R", "Y", "R", "Y"], ["Y", "R", "R", "R", "Y"], ["Y", "Y", "Y", "Y", "Y"]]), "Y: 1");

scoreCurling([["Y", "R", "Y", "R", "Y"], ["R", ".", ".", ".", "R"], ["Y", ".", ".", ".", "Y"], ["R", ".", ".", ".", "R"], ["Y", ".", ".", "R", "Y"]]) should return "No points awarded".

js
assert.equal(scoreCurling([["Y", "R", "Y", "R", "Y"], ["R", ".", ".", ".", "R"], ["Y", ".", ".", ".", "Y"], ["R", ".", ".", ".", "R"], ["Y", ".", ".", "R", "Y"]]), "No points awarded");

--seed--

--seed-contents--

js
function scoreCurling(house) {

  return house;
}

--solutions--

js
function scoreCurling(house) {
  const stones = { R: [], Y: [] };

  for (let i = 0; i < 5; i++) {
    for (let j = 0; j < 5; j++) {
      const cell = house[i][j];
      if (cell === 'R' || cell === 'Y') {
        const distance = Math.max(Math.abs(i - 2), Math.abs(j - 2));
        stones[cell].push(distance);
      }
    }
  }

  const redClosest = stones.R.length > 0 ? Math.min(...stones.R) : Infinity;
  const yellowClosest = stones.Y.length > 0 ? Math.min(...stones.Y) : Infinity;

  if (redClosest === Infinity && yellowClosest === Infinity) {
    return "No points awarded";
  }

  if (redClosest === yellowClosest) {
    return "No points awarded";
  }

let winner, opponentClosest, winningStones;
  if (redClosest < yellowClosest) {
    winner = 'R';
    opponentClosest = yellowClosest;
    winningStones = stones.R;
  } else {
    winner = 'Y';
    opponentClosest = redClosest;
    winningStones = stones.Y;
  }

  const points = winningStones.filter(d => d < opponentClosest).length;

  return points === 0 ? "No points awarded" : `${winner}: ${points}`;
}