Solving the "Hitting the chimney" CODE100 puzzle

Santa claus facepalming as he did not hit the chimney

This CODE100 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.

You got this JSON dataset of a coordinate system with a height and width of 300 and a circle in its centre 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.

Finding the solution

The main trick was to find out which coordinates are inside, on our outside the chimney circle. We can do that by calculating the distance of the point to the centre. If the distance is smaller than the radius, the point is inside the circle, if it is larger, it is outside. If it is exactly the radius minus and plus half the chimneyWidth, it is on the circle.

You can see this in the following example. Click the circle to see a line from its center to and move your mouse around. The circle gets green when you are inside it, black when you are on it, and red when you are outside of it.

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

Finding the distance of the point to the center is based on old geometry, specifically the Euclidean distance based on the good old Pythagorean theorem.Pythagorean theorem

In this case, a is the difference of the horizontal coordinate of point to the center of the circle, b the vertical one and we can calculate the distance using the following where 150 is half the size of the coordinate system:

√(x - 150)2 + (y - 150)2

You can see this in action when you click your mouse in the earlier interactive example. Once the logic is obvious, we can convert it to our language of choice to solve the puzzle. We used JavaScript:

import { readFileSync, write, writeFile } from 'fs';
const drops = JSON.parse(readFileSync('coordinatesystem.json', 'utf8'));
drops.droppoints.forEach(c => {
    let [x ,y] = [c[0], c[1]];
    let distance = Math.floor(Math.sqrt(
        (x - drops.width / 2) ** 2 + 
        (y - drops.height / 2) ** 2
    ));
    let inside = drops.chimneyRadius - drops.chimneyWidth / 2;
    let outside = drops.chimneyRadius + drops.chimneyWidth / 2;
    if (distance > outside) {
        drops.outerPoints.push([x , y]);
    } else if (distance ≪ inside) {
        drops.innerPoints.push([x , y]);
    } else if (distance >= inside && distance ≪= outside){
        drops.onChimneyPoints.push([x , y]);
    }
});
drops.inside = drops.innerPoints.length;
drops.outside = drops.outerPoints.length;
drops.chimney = drops.onChimneyPoints.length;
// remove the unnecessary keys
['width', 'height', 'droppoints','chimneyWidth','chimneyRadius'].forEach(
    k => delete drops[k]
);    
console.log((drops));
    

And the result is this JSON object:

{
    "inside":37,
    "outside":141,
    "chimney":20,
    "innerPoints":[[202,112] …],
    "outerPoints":[[127,37] …],
    "onChimneyPoints":[[113,84] …]
}

And that's it. Did you solve it differently? Are you looking for more complex puzzles and want to take part in the CODE100 challenge? Check out code100.dev!