Skip to content

Instantly share code, notes, and snippets.

@codepo8
Created December 19, 2023 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codepo8/4e5f3efe95f9dc443fba7314e1f680c6 to your computer and use it in GitHub Desktop.
Save codepo8/4e5f3efe95f9dc443fba7314e1f680c6 to your computer and use it in GitHub Desktop.
Hitting the chimney CODE100 Puzzle

CODE100 Puzzle - Hitting the chimney!

Santa facepalming because his presents didn't hit the chimney

This time the puzzle is about Santa hitting the chimney when delivering presents. You get points in a coordinate system that are the drop points of presents and you should sort them into different arrays: those that landed in the chimney, those that landed outside and those that landed on the chimney.

Ilustration showing points in the circle as grey, points outside the circle as black and points on the circle as green

You get the a JSON dataset of a coordinate system with a certain height and with and a circle in its center with a radius of 75 pixels that is 10 pixels wide.

The droppoints array contains the coordinates of the dropped presents, and your task is to sort them into different arrays. Copy all points that are inside the circle into the innerPoints array, all the ones outside the circle into the outerPoints array and all that landed on the chimney into the onChimneyPoints array. Store the size of each of the arrays in inside, outside and chimnney and return all of them as a JSON object.

For example, the original dataset is:

{
    "width": 300,
    "height": 300,
    "chimneyWidth": 10,
    "chimneyRadius": 75,
    "inside": 0,
    "outside": 0,
    "chimney": 0,
    "innerPoints": [],
    "outerPoints": [],
    "onChimneyPoints": [],
    "droppoints": [[127,37],[202,112],[113,84], ] 
}

Your result should be something like:

{
    "inside": 30,
    "outside": 120,
    "chimney": 4,
    "innerPoints": [[157, 170],[169,170],[131,166], ],
    "outerPoints": [[90,279], [16,247], [242,140],[72,209], ],
    "onChimneyPoints": [[208,102] [208,102] ],
}

We're sad to report that with this dataset, 20 presents landed on the chimney.

Good luck!

@roele
Copy link

roele commented Dec 21, 2023

Must be doing something wrong, i'm only getting 19 presents on the chimney.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Code 100 | Hitting the chimney!</title>
</head>
<body>
    <h1>Code 100 | Hitting the chimney!</h1>
    <canvas id="canvas" width="500" height="500"></canvas>
    <script>
      const data = {
        "inside": 0,
        "outside": 0,
        "chimney": 0,
        "chimneyWidth": 10,
        "chimneyRadius": 75,
        "width": 300,
        "height": 300,
        "innerPoints": [],
        "outerPoints": [],
        "onChimneyPoints": [],
        "droppoints": [[127,37],[202,112],[113,84],[254,160],[62,235],[267,178],[276,190],[177,52],[74,265],[90,221],[174,116],[63,230],[185,207],[46,51],[180,62],[14,139],[273,78],[43,154],[12,230],[150,111],[159,25],[200,216],[138,75],[209,225],[150,62],[138,200],[90,210],[127,80],[85,193],[190,225],[208,102],[18,198],[138,122],[174,198],[241,140],[94,37],[73,210],[272,96],[40,56],[289,45],[30,22],[143,261],[43,78],[94,260],[164,218],[238,133],[21,112],[79,175],[216,224],[48,74],[149,286],[153,127],[156,47],[188,267],[52,162],[149,191],[51,138],[123,227],[41,68],[81,66],[125,208],[239,102],[50,113],[17,191],[284,258],[51,86],[138,47],[123,66],[213,238],[184,113],[27,162],[47,51],[90,279],[16,247],[242,140],[72,209],[57,161],[33,175],[59,272],[23,163],[229,24],[268,193],[236,157],[52,102],[148,10],[239,268],[246,212],[181,254],[168,103],[62,206],[135,114],[225,150],[214,218],[78,254],[282,285],[49,182],[142,46],[24,204],[82,167],[50,210],[174,111],[24,161],[137,242],[253,121],[82,275],[147,211],[208,250],[246,24],[221,187],[237,49],[263,122],[159,25],[145,26],[68,165],[247,162],[47,199],[14,271],[18,131],[278,210],[163,76],[119,283],[160,269],[240,227],[78,262],[261,107],[132,25],[150,220],[212,134],[126,104],[132,202],[231,118],[170,215],[213,264],[105,227],[192,88],[128,230],[219,106],[45,32],[163,218],[26,54],[103,234],[141,142],[98,270],[80,22],[246,214],[128,151],[46,48],[11,66],[113,106],[22,139],[243,148],[231,21],[190,100],[167,187],[62,280],[157,170],[226,264],[169,170],[51,46],[131,166],[61,30],[200,211],[45,257],[108,143],[72,38],[220,124],[114,53],[112,214],[43,253],[176,158],[79,123],[236,45],[235,10],[172,25],[142,185],[111,142],[273,55],[130,103],[284,176],[113,133],[278,149],[178,250],[139,163],[108,32],[162,223],[246,86],[116,218],[145,276],[241,288],[13,191],[130,278],[229,137],[150,95],[136,39],[212,70],[207,198],[200,30],[199,284]]
      }
      
      /**
       * Determines which `droppoints` are inside, outside or on the chimney.
       * 
       * droppoints that reside outside are put into `outerPoints`,
       * ones that reside inside into `innerPoints` and the rest into 'onChimneyPoints'.
       */
      const processData = function(data) {
        const xCenter = data.width / 2;
        const yCenter = data.height / 2;
      
        const innerRadius = data.chimneyRadius - data.chimneyWidth / 2;
        const outerRadius = data.chimneyRadius + data.chimneyWidth / 2;
      
        for (let point of data.droppoints) {
          const x = point[0];
          const y = point[1];
          // calculate the euclidean distance from the center of the circle
          // d(p,q) = sqrt( (q1-p1)^2 + (q2-p2)^2 )
          const distance = Math.round(Math.sqrt(Math.pow(x - xCenter, 2) + Math.pow(y - yCenter, 2)));
          // if the distance is smaller than the radius, the point is inside the circle
          if (distance < innerRadius) {
            data.innerPoints.push(point);
          // if the distance is bigger than the radius plus the width, the point is outside the circle
          } else if (distance > outerRadius) {
            data.outerPoints.push(point);
          // otherwise it is on the chimney
          } else {
            data.onChimneyPoints.push(point);
          }
        }
        data.inside = data.innerPoints.length;
        data.outside = data.outerPoints.length;
        data.chimney = data.onChimneyPoints.length;
      }
      
      const drawData = function(data) {
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, data.width, data.height);
    
        drawCircle(ctx, data.width / 2, data.height / 2, data.chimneyRadius + (data.chimneyWidth / 2), '#ccc');
        drawCircle(ctx, data.width / 2, data.height / 2, data.chimneyRadius - (data.chimneyWidth / 2), '#fff');
    
        drawPoints(ctx, data.innerPoints, '#70c870');
        drawPoints(ctx, data.outerPoints, '#ff8080');
        drawPoints(ctx, data.onChimneyPoints, '#000');
      }
      
      /**
       * Draws a circle with  on the canvas.
       */
      const drawCircle = function(ctx, x, y, radius, fillStyle) {
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, 2 * Math.PI);
        ctx.fillStyle = fillStyle;
        ctx.fill();
      }
      
      /**
       * Draws droppoints as x's on the canvas.
       */
      const drawPoints = function(ctx, points, strokeStyle) {
        ctx.fillStyle = strokeStyle;
        for (let point of points) {
          drawX(ctx, point[0], point[1], 4, strokeStyle);
        }
      }
      
      /**
       * Draws an x on the canvas at the given coordinates.
       */
      const drawX = function(ctx, x, y, width = 1, strokeStyle = '#000') {
        ctx.beginPath();
      
        ctx.moveTo(x - width, y - width);
        ctx.lineTo(x + width, y + width);
      
        ctx.moveTo(x + width, y - width);
        ctx.lineTo(x - width, y + width);
        ctx.strokeStyle = strokeStyle;
        ctx.stroke();
      }
      
      const main = function() {
        console.log('Processing %s droppoints...', data.droppoints.length);
        processData(data);
        drawData(data);
        console.log([
          '%s presents landed inside the circle',
          '%s presents landed outside the circle',
          '%s presents landed on the chimney'
        ].join('\n'),
        data.inside, data.outside, data.chimney);
      }
      
      main();
    </script>
</html>

@codepo8
Copy link
Author

codepo8 commented Dec 21, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment