Files
advent-of-code-2024/02/RedNosedReports/Report.cs
T

128 lines
3.4 KiB
C#
Raw Normal View History

2024-12-03 02:32:30 -06:00
namespace RedNosedReports;
class Report(List<int> levels)
{
private readonly List<int> _levels = levels;
public string GetDebugOutput()
{
return $"{string.Join(' ', _levels)} {IsSafe()} {IsSafeWithProblemDampener()}";
}
2024-12-03 02:32:30 -06:00
public bool IsSafe()
{
for (var i = 0; i < _levels.Count - 1; i++)
{
var current = _levels[i];
var next = _levels[i + 1];
if (HasExceededLimits(current, next) || HasChangedDirection(current, next))
2024-12-03 02:32:30 -06:00
{
return false;
}
}
return true;
}
public bool IsSafeWithProblemDampener()
{
for (var currentIndex = 0; currentIndex < _levels.Count - 1; currentIndex++)
{
var nextIndex = currentIndex + 1;
var current = _levels[currentIndex];
var next = _levels[nextIndex];
var directionChanged = HasChangedDirection(current, next);
2024-12-03 02:32:30 -06:00
// problem dampener permits us to try to make
// levels work after removing one of them.
// so when we encounter a violation...either direction
// of levels change or levels change so much that they exceed
// the limits we are going to attempt to see if
// the levels will work if we remove one of the levels in
// the current pair.
if (HasExceededLimits(current, next) || directionChanged)
2024-12-03 02:32:30 -06:00
{
// specific edge case where direction changes
// on the second pair of levels after the first
// pair is a valid.
// i.e. 43, 41, 43, 44, 45, 47, 49
// in this case we should attempt to make levels
// work by removing first element so that we can
// essentially reset what the valid direction is.
if (directionChanged && currentIndex is 1)
{
var levelsWithoutFirstElement = _levels.ToList();
levelsWithoutFirstElement.RemoveAt(0);
var isSafeWithoutFirstElement = new Report(levelsWithoutFirstElement).IsSafe();
if (isSafeWithoutFirstElement)
{
return true;
}
}
// check if levels work without the current level
2024-12-03 02:32:30 -06:00
var levelsWithoutCurrent = _levels.ToList();
levelsWithoutCurrent.RemoveAt(currentIndex);
var isSafeWithoutCurrent = new Report(levelsWithoutCurrent).IsSafe();
if (isSafeWithoutCurrent)
{
return true;
}
// check if levels work without the next level
2024-12-03 02:32:30 -06:00
var levelsWithoutNext = _levels.ToList();
levelsWithoutNext.RemoveAt(nextIndex);
var isSafeWithoutNext = new Report(levelsWithoutNext).IsSafe();
if (isSafeWithoutNext)
{
return true;
}
// if won't work with all levels
// or without current or next then doesn't
// work at all.
2024-12-03 02:32:30 -06:00
return false;
}
}
return true;
}
private bool HasExceededLimits(int current, int next)
{
var delta = Math.Abs(next - current);
if (delta > 3 || delta < 1)
{
return true;
}
return false;
}
private bool HasChangedDirection(int current, int next)
2024-12-03 02:32:30 -06:00
{
var direction = _levels[1] > _levels[0]
? Direction.Increasing
: Direction.Decreasing;
var isNextGreaterThanCurrent = next > current;
if (direction is Direction.Increasing && isNextGreaterThanCurrent is false)
{
return true;
2024-12-03 02:32:30 -06:00
}
if (direction is Direction.Decreasing && isNextGreaterThanCurrent)
{
return true;
2024-12-03 02:32:30 -06:00
}
return false;
2024-12-03 02:32:30 -06:00
}
}