James Williams
LinkedInMastodonGithub

Advent Of Code 2022 - Day 4 - Camp Cleanup

Titled Camp Cleanup, Day 4's problem is a genre of problem that shows up a lot for Advent of Code: the numeric range problem.

I had the misfortune of having to do this problem twice. I coded it, got my stars, and then went on a trip without saving the code to version control. So apologies if this entry seems too polished.

Numeric range problems can ask you to determine if ranges overlap, don't overlap, if one is fully contained in the other or what values to add or remove to optimize them somehow.

In Kotlin, you can lean on the IntRange type to assist with these problems.

Part I

For Part I, you need to determine if one range is fully contained in the other. It's a matter of calling contains on the range and checking if both the .first and .endInclusive are contained.

override fun part01(): Any? {
    var count = 0
    while (scan.hasNextLine()) {
        val parts = scan.nextLine().split(",")
        val r1 = parts[0].split("-").map { it.toInt() }
        val r2 = parts[1].split("-").map { it.toInt() }
        val range1 = IntRange(r1[0], r1[1])
        val range2 = IntRange(r2[0], r2[1])

        if (range1.contains(range2.first) &&
            range1.contains(range2.endInclusive) ||
            range2.contains(range1.first) &&
            range2.contains(range1.endInclusive)) {
                count++
        }
    }
    return count
}
 

Part II

For this star, you needed to determine overlap but not full containment. All contained ranges are by default overlapping so by quick mental map you could ballpark that the correct answer would be higher than that of part one.

The logic was largely similar with a loosening of conditions so either the first or end needed to be contained to be deemed overlapping.

override fun part02(): Any? {
    var count = 0
    // part 1 saved computed IntRanges into an array of Pair
    part2Cache.forEach {
        val range1 = it.first
        val range2 = it.second
        if (range1.contains(range2.first) || range1.contains(range2.endInclusive) ||
            range2.contains(range1.first) || range2.contains(range1.endInclusive)) {
                count++
        }
    }
    return count
}