Files
AdventOfCode/Days/Day2.cs
2025-01-24 10:19:11 +01:00

139 lines
4.1 KiB
C#

using Spectre.Console;
namespace AdventOfCode.Days;
public class Day2 : Day
{
public override int Number => 2;
public override string Name => "Red-Nosed Reports";
public override void RunPart1(bool display = true)
{
var safeReports = 0;
foreach (var line in Input.AsSpan().EnumerateLines())
{
var isSafe = true;
var levels = line.Split(' ');
var previousDirection = 0;
var previousLevel = int.MinValue;
foreach (var levelRange in levels)
{
var level = int.Parse(line[levelRange]);
// First level, skip to next
if (previousLevel == int.MinValue)
{
previousLevel = level;
continue;
}
// Check that direction is preserved
var direction = level - previousLevel;
if (previousDirection != 0 && Math.Sign(direction) != Math.Sign(previousDirection))
{
isSafe = false;
break;
}
// Check that distance >= 1 and <= 3
if (Math.Abs(direction) is < 1 or > 3)
{
isSafe = false;
break;
}
previousLevel = level;
previousDirection = direction;
}
if (isSafe)
{
safeReports++;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of safe reports: [yellow]{safeReports}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var safeReports = 0;
foreach (var line in Input.AsSpan().EnumerateLines())
{
if (IsSafe(line))
{
safeReports++;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of safe reports: [yellow]{safeReports}[/][/]");
}
return;
bool IsSafe(ReadOnlySpan<char> line, Range? toSkip = null)
{
var levels = line.Split(' ');
var previousDirection = 0;
var previousLevel = int.MinValue;
Range previousLevelRange = default;
Range firstLevelRange = default;
foreach (var levelRange in levels)
{
if (levelRange.Equals(toSkip))
{
// This level can be skipped using the problem dampener
continue;
}
var level = int.Parse(line[levelRange]);
// First level, skip to next
if (previousLevel == int.MinValue)
{
previousLevel = level;
previousLevelRange = levelRange;
firstLevelRange = levelRange;
continue;
}
// Check that direction is preserved
var direction = level - previousLevel;
if (previousDirection != 0 && Math.Sign(direction) != Math.Sign(previousDirection))
{
// Also try by removing current or previous level if it's first try (problem dampener)
return toSkip is null
&& (IsSafe(line, levelRange) || IsSafe(line, previousLevelRange) || IsSafe(line, firstLevelRange));
}
// Check that distance >= 1 and <= 3
if (Math.Abs(direction) is < 1 or > 3)
{
// Also try by removing current or previous level if it's first try (problem dampener)
return toSkip is null
&& (IsSafe(line, levelRange) || IsSafe(line, previousLevelRange) || IsSafe(line, firstLevelRange));
}
previousLevel = level;
previousDirection = direction;
previousLevelRange = levelRange;
}
return true;
}
}
}