Skip to content

Commit 9accd60

Browse files
committed
Rewrite 2024 day 2
The original solution bothered me. So after I determined which edge cases tripped up my initial implementation, I was able to make a more readable version.
1 parent 350a7d8 commit 9accd60

File tree

2 files changed

+49
-57
lines changed

2 files changed

+49
-57
lines changed

2024.Tests/Day02Tests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,24 @@ 1 3 6 7 9
3939

4040
answer.Should().Be(4);
4141
}
42+
43+
[Fact]
44+
public static void Part2EdgeCases()
45+
{
46+
var solution = new Day02();
47+
48+
// These edge cases are the ones that tripped
49+
// up my initial solution. It anticipates the
50+
// fact that increase or decrease are determined
51+
// using the first two numbers, and then go
52+
// into the other direction. Well played, Eric.
53+
const string input = """
54+
88 86 88 89 90 93 95
55+
47 50 47 46 44 41 38 37
56+
""";
57+
58+
var answer = solution.SolvePart2(input);
59+
60+
answer.Should().Be(2);
61+
}
4262
}

2024/D02/Day02.cs

Lines changed: 29 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,84 +15,56 @@ protected override List<List<int>> ParseInput(string input)
1515
protected override object SolvePart1(List<List<int>> reports)
1616
{
1717
return reports
18-
.Select(report => report.Steps().ToList())
19-
.Count(steps => steps.AllInRange() && (steps.AllIncreasing() || steps.AllDecreasing()));
18+
.Count(report => report.Steps().AreSafe());
2019
}
2120

2221
protected override object SolvePart2(List<List<int>> reports)
2322
{
2423
var safeReports = reports
25-
.Where(report =>
26-
{
27-
var steps = report.Steps().ToList();
28-
return steps.AllInRange() && (steps.AllIncreasing() || steps.AllDecreasing());
29-
})
30-
.ToList();
31-
32-
var unsafeReports = reports.Except(safeReports).ToList();
33-
34-
unsafeReports.ForEach(report =>
35-
{
36-
var wrongStep = report.Steps().ToList().FindIndex((number) => report.IsIncreasing() ? number is < 1 or > 3 : number is < -3 or > -1);
37-
38-
for (var index = Math.Max(0, wrongStep - 1); index < Math.Min(wrongStep + 2, report.Count); index++)
39-
{
40-
var filteredReport = report.ToList();
41-
filteredReport.RemoveAt(index);
42-
var steps = filteredReport.Steps().ToList();
24+
.Where(report => report.Steps().AreSafe())
25+
.ToArray();
4326

44-
if (steps.AllInRange() && (steps.AllIncreasing() || steps.AllDecreasing()))
45-
{
46-
safeReports.Add(report);
47-
break;
48-
}
49-
}
50-
});
27+
var fixedReports = reports
28+
.Except(safeReports)
29+
.Select(report => (Report: report, Steps: report.Steps(), Increasing: report[^1] > report[0]))
30+
.Select(data => (Report: data.Report, WrongStep: data.FindFirstWrongStep()))
31+
.Count(data => data.Report.CompensateForStep(data.WrongStep).Any(report => report.Steps().AreSafe()));
5132

52-
return safeReports.Count;
33+
return safeReports.Length + fixedReports;
5334
}
5435
}
5536

5637
internal static class Day02Extensions
5738
{
58-
internal static bool AllInRange(this List<int> numbers)
39+
internal static bool AreSafe(this IEnumerable<int> steps)
5940
{
60-
return numbers.Count(number => Math.Abs(number) is >= 1 and <= 3) == numbers.Count;
61-
}
62-
63-
internal static bool AllDecreasing(this List<int> numbers)
64-
{
65-
return numbers.CountDecreasing() == numbers.Count;
66-
}
67-
68-
internal static bool AllIncreasing(this List<int> numbers)
69-
{
70-
return numbers.CountIncreasing() == numbers.Count;
41+
return steps.All(n => n is >= 1 and <= 3)
42+
|| steps.All(n => n is >= -3 and <= -1);
7143
}
7244

73-
internal static IEnumerable<int> Steps(this IEnumerable<int> numbers)
45+
internal static int FindFirstWrongStep(this (List<int> Report, List<int> Steps, bool Increasing) data)
7446
{
75-
foreach (var levelSet in numbers.SlidingWindow(2))
76-
{
77-
var left = levelSet[0];
78-
var right = levelSet[1];
79-
80-
yield return right - left;
81-
}
47+
return data
48+
.Steps
49+
.FindIndex((number) => data.Increasing ? number is < 1 or > 3 : number is < -3 or > -1);
8250
}
8351

84-
internal static bool IsIncreasing(this List<int> numbers)
52+
internal static List<int>[] CompensateForStep(this List<int> report, int position)
8553
{
86-
return numbers[1] > numbers[0];
87-
}
88-
89-
private static int CountDecreasing(this List<int> numbers)
90-
{
91-
return numbers.Count(number => number < 0);
54+
return
55+
[
56+
// Create new reports without the values that cause the
57+
// wrong step at "position" in an attempt to compensate.
58+
[..report[..position], ..report[(position+1)..]],
59+
[..report[..(position+1)], ..report[(position+2)..]]
60+
];
9261
}
9362

94-
private static int CountIncreasing(this List<int> numbers)
63+
internal static List<int> Steps(this IEnumerable<int> numbers)
9564
{
96-
return numbers.Count(number => number > 0);
65+
return numbers
66+
.Zip(numbers.Skip(1), Tuple.Create)
67+
.Select(tuple => tuple.Item2 - tuple.Item1)
68+
.ToList();
9769
}
9870
}

0 commit comments

Comments
 (0)