Advent of Code 2024 day 2 strategy

Published

This article is for Day 2 of Advent of Code 2024, Red-Nosed Reports. In this post, I will go over one strategy for how to solve this puzzle. There are no direct code snippets here, so this is a good place to start if you're stuck but you still want to do the hard work of coding yourself.

Part 1: How many reports are safe?

The input for this puzzle is a text file with rows of integers separated by spaces. The goal is to check each row for "safety", defined by these rules:

  • For one line, numbers ("levels") can only count up or down - they shouldn't reverse direction.
  • From one number to the next on a line, the numbers should differ by 1, 2, or 3, not 0 and not 4 or more.

Here's one way to go about this:

  1. Get the input data into your environment. Either read the data in programmatically (harder, more like what you would do in a real world situation) or copy/paste the data in (easier).

  2. Split the text data into individual lines ("reports"). This can be done by splitting on the line delimiter (\n).

  3. Set a variable to count your "safe" lines and also, optionally, your "unsafe" lines. You can sum these variables to make sure every line in your input is accounted for.

  4. Write a function that takes an array of numbers (levels) and returns a boolean (true/false) for safe/unsafe. Inside of this function, you will to keep track of some variables:

    • Set variables or your "current" and "next" number (level) in the line.
    • Set a variable for the "direction" the levels are going (this can be blank to start but will become either "increasing" or "decreasing").
  5. Inside the function after you've declared your variables, for each number in the array, get the difference between the current and next numbers. Use the absolute value of the difference (throw away the minus sign if it's a negative number).

    • If the difference is zero, you know the level is "unsafe" and you can return false.
    • If the difference is greater than 3, return false.
    • If the current value is greater than the next value but the direction is meant to be "increasing", return false.
    • Vice versa, if the current value is smaller than the next value but the direction is meant to be "decreasing", return false.
    • At the end of the loop, set the "direction" variable by comparing the current and next values. It's safe to set this every time at the bottom of the loop because of the comparisons we've done above.
  6. Still inside your function, if you've made it through that loop for all the numbers (levels) in the line/report (array of levels), you can return true, because you know the safety conditions have been met.

  7. Outside of your function, it's time to deal with the data from step 2. For each report in the array of reports, get an array of levels by splitting the line/report on the whitespace character " ". This is a good time to parse the string data into a number if you language doesn't do it for you automatically. Now that you have an array of numbers, call your function using this array as your argument. If you get back true, you can add one to your count of safe reports. If you get false, you can add one to the unsafe reports count (which isn't actually used to solve the problem, but can be used as a sanity check).

  8. You should now have the count of safe reports that you need to pass this challenge. Great stuff!

Part 2: How many reports are safe after excluding one bad level from each report?

You can build off of your code for part 1 for part 2. Here, you have one additional rule that liberalizes what counts as "safe":

If you can remove a single bad level from a report, that report should still be considered safe.

Here's one way to do this:

  1. Let's start by writing a function that takes a report (array of levels) and returns true if "any report is safe" if a single element can be removed from the array. Get an array of "hypothetical levels" to check. This means for an array like [1, 2, 3, 4] you should check the arrays:

    • [2, 3, 4] (1 is removed)
    • [1, 3, 4] (2 is removed)
    • [1, 2, 4] (3 is removed)
    • [1, 2, 3] (4 is removed)

Get an array to hold these new hypothetical levels. Loop over your initial report argument, and for each element, push a new array into your array of hypothetical levels. Include every element except the one you're looking at.

  1. In your function, once you have your hypothetical levels to be checked, set a variable that holds whether "any report is safe". This can be set to false to start. Remember, we only need one hypothetical report to be true here. That would meet the extra Part 2 constraint that a single bad level can be removed to make the report safe.

  2. Still inside your new function, for each hypothetical level, use your existing function from part 1 to check if it's safe. If any one of the hypothetical levels if safe, you can set the value of your variable from step 2 to true.

  3. At the end of your new function, return the value of the boolean variable. This will be false if none of the hypothetical values set it to true.

  4. Now that your new function is finished, update the for you used in Part 1. This loop is already checking for whether the entire report from the raw data is safe. We want an extra step that says "Well, if the whole thing isn't safe, check if any hypothetical reports from it are safe". You know, that thing we just wrote a function for!

  5. With this new step to check if any hypothetical report is safe, we are done, and we should have a count of safe reports that is equal to or greater than the count from Part 1. Subsequently, the count of unsafe reports should be equal to or less than the count from Part 1. The sum of these counts should be the same as part 1.

Happy hacking!