--- Day 2: Reporting on reports ---

December 2

Listening to: Vinesauce


Almost immediately after yesterday, I realized that I use the sample input a lot, so I need an easy way to both get the input, and switch between the example and real input easily. I added a few prompts that ask for either the real input or (by default) the example input.

// Fetch input for day
Console.Write("Use Real Input? (y/N): ");
var response = Console.ReadKey();

string[] input = response.Key == ConsoleKey.Y ? await Website.GetInput(2024, 1) : await Website.GetExampleInput(2024, 1);

Combined with a prompt to paste the example input, if it hasn't already been saved, and save it to disk for future use

public static async Task<string[]> GetExampleInput(int year, int day)
{
    string filename = $"{exampleDirectory}/{day:d2}.txt";
    if (File.Exists(filename))
    {
        return await File.ReadAllLinesAsync(filename);
    }

    Console.WriteLine("Input Sample (blank to cancel):\n");
    var result = new List<string>();
    while (true)
    {
        string? line = Console.ReadLine();
        if (string.IsNullOrEmpty(line)) break;

        result.Add(line);
    }

    Directory.CreateDirectory(exampleDirectory);
    await File.WriteAllLinesAsync(filename, result);

    return result.ToArray();
}

Nothing too fancy, but it works


For part 1, it's just doing a test against each line:

  • Is it always increasing or always decreasing?
  • Is the change always between 1 and 3 inclusive?

If both are true, it's safe.

private bool isIncreasing(List<int> report)
{
    for (int i = 0; i < report.Count - 1; i++)
    {
        if (report[i + 1] <= report[i])
        {
            return false;
        }
    }

    return true;
}

private bool isGentle(List<int> report)
{
    for (int i = 0; i < report.Count - 1; i++)
    {
        int diff = Math.Abs(report[i + 1] - report[i]);
        if (diff < 1 || diff > 3) return false;
    }

    return true;
}

Part 2 is a little annoying; a report is potentially safe if it's still safe with some value removed.

I can probably just do the same logic as part 1, but also test each iteration of a value removed.

for (int i = 0; i < report.Count; i++)
{
    var reportCopy = new List<int>(report);
    reportCopy.RemoveAt(i);

    if (isSafe(reportCopy))
    {
        safe++;
        break;
    }
}

Time taken: 20 minutes

My solutions for today's puzzles