Day 4 — Camp Cleanup
Part 1
Welcome to Day 4! As usual, we’ll start by splitting our input by line.
const pairs = input.split("\n").filter(Boolean);
Now that we have our pairs, we can start to reduce them down to count the instances where they fully overlap. Since our “pairs” are still a single string at the moment, we’ll use some split and map goodness to get them in a format we can work with.
return pairs.reduce((total, pair) => {
const ranges = pair.split(",").map((range) => {
return range.split("-").map(Number);
});
// ...
return total;
}, 0);
This will essentially take a pair string like 40-51,4-39, and convert it to a nested array that is shaped like so:
[
[40, 51],
[4, 39],
];
Now that we have our ranges, we can start to compare them. There are probably a few ways to do this, but my first instinct was to create a function to generate a range with a start and end value. This will allow us to compare the ranges and see if they overlap.
function createRange(start: number, end: number) {
return Array.from({ length: end + 1 - start }, (_, k) => k + start);
}
createRange(2, 5); // [2, 3, 4, 5]
Now we’ll generate a range for each of our pairs, and compare them using Array.every to see if they overlap. If they do, we’ll add 1 to our total.
return pairs.reduce((total, pair) => {
const ranges = pair.split(",").map((range) => {
return range.split("-").map(Number);
});
const firstRange = createRange(ranges[0][0], ranges[0][1]);
const secondRange = createRange(ranges[1][0], ranges[1][1]);
if (
firstRange.every((i) => secondRange.includes(i)) ||
secondRange.every((i) => firstRange.includes(i))
) {
total++;
}
return total;
}, 0);
And that’s it! We can run our code and get our answer: 560 ✨
Part 2
Probably the easiest part 2 yet! Our solution looks the exact same, but instead of using Array.every we simply use Array.some instead.
Boom! Our answer is 839 😄