diff --git a/AdventOfCode2024/AdventOfCode2024.vcxproj b/AdventOfCode2024/AdventOfCode2024.vcxproj
index 7b8c698..d648ef5 100644
--- a/AdventOfCode2024/AdventOfCode2024.vcxproj
+++ b/AdventOfCode2024/AdventOfCode2024.vcxproj
@@ -131,6 +131,7 @@
+
@@ -138,7 +139,9 @@
+
+
diff --git a/AdventOfCode2024/AdventOfCode2024.vcxproj.filters b/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
index 399c5a9..56695fd 100644
--- a/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
+++ b/AdventOfCode2024/AdventOfCode2024.vcxproj.filters
@@ -33,6 +33,9 @@
Source Files
+
+ Source Files
+
@@ -50,5 +53,11 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/AdventOfCode2024/RedNosedReportData.cpp b/AdventOfCode2024/RedNosedReportData.cpp
new file mode 100644
index 0000000..f0010e5
--- /dev/null
+++ b/AdventOfCode2024/RedNosedReportData.cpp
@@ -0,0 +1 @@
+#include "RedNosedReportData.h"
diff --git a/AdventOfCode2024/RedNosedReportData.h b/AdventOfCode2024/RedNosedReportData.h
new file mode 100644
index 0000000..1da4240
--- /dev/null
+++ b/AdventOfCode2024/RedNosedReportData.h
@@ -0,0 +1,32 @@
+// Solutions to the Advent Of Code 2024.
+// Copyright (C) 2024 Stefan Müller
+//
+// This program is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see .
+
+#pragma once
+
+#include
+
+#include "Slope.h"
+
+class RedNosedReportData
+{
+public:
+ bool isSafe{ true };
+ bool canUseDampener{ true };
+ bool mustSkipPrevious{ false };
+ bool mustCheckSlopeReversal{ false };
+ bool mustAwaitFourLevels{ false };
+ Slope slope{ Slope::Unknown };
+ std::vector levels{};
+};
diff --git a/AdventOfCode2024/RedNosedReports.cpp b/AdventOfCode2024/RedNosedReports.cpp
index 7587854..157f082 100644
--- a/AdventOfCode2024/RedNosedReports.cpp
+++ b/AdventOfCode2024/RedNosedReports.cpp
@@ -15,9 +15,9 @@
#include
#include
+#include
#include "RedNosedReports.h"
-#include
std::string RedNosedReports::getPuzzleName() const
{
@@ -29,41 +29,148 @@ std::string RedNosedReports::getInputFileName() const
return "red-nosed_reports.txt";
}
+// 'X' in the comments here and below marks the level that must be ignored to
+// make the report safe.
+// 'first' means that this series starts at the beginning of the line.
+// 'next' means that the level(s) from the next loop iteration(s) will determine
+// which level to ignore.
void RedNosedReports::processDataLine(const std::string& line)
{
- auto isSafe{ true };
- auto slope{ Slope::Unknown };
+ RedNosedReportData data{};
std::stringstream stream{ line };
std::string token;
std::getline(stream, token, ' ');
- auto prev{ std::stoi(token) };
+ data.levels.push_back(std::stoi(token));
- while (isSafe && std::getline(stream, token, ' '))
+ while (data.isSafe && std::getline(stream, token, ' '))
{
- auto next{ std::stoi(token) };
- auto delta{ next - prev };
- if (delta == 0 || delta > 3 || delta < -3
- || (delta > 0 && slope == Slope::Decreasing)
- || (delta < 0 && slope == Slope::Increasing))
+ do
{
- isSafe = false;
+ data.levels.push_back(std::stoi(token));
+ } while (data.mustAwaitFourLevels && data.levels.size() < 4
+ && std::getline(stream, token, ' '));
+
+ if (data.mustCheckSlopeReversal)
+ {
+ auto it = data.levels.rbegin();
+ if (data.slope == Slope::Decreasing && *it > *(++it))
+ {
+ // X
+ // first 3 2 6 7
+ data.slope = Slope::Increasing;
+ }
+ else if (data.slope == Slope::Increasing && *it < *(++it))
+ {
+ // X
+ // first 6 7 3 2
+ data.slope = Slope::Decreasing;
+ }
+ else
+ {
+ // X
+ // first 3 2 6 1
+ // first 6 7 3 8
+ data.mustSkipPrevious = true;
+ }
+ }
+ data.mustCheckSlopeReversal = false;
+
+ auto it = data.levels.rbegin();
+ auto delta{ *it };
+ delta -= *(++(data.mustSkipPrevious ? ++it : it));
+ data.mustSkipPrevious = false;
+
+ if (delta == 0)
+ {
+ // X
+ // 1 1
+ data.isSafe = data.canUseDampener;
+ data.canUseDampener = false;
+ }
+ else if (delta > 0)
+ {
+ checkLastLevel(Slope::Increasing, Slope::Decreasing, delta, 1, data);
}
else
{
- prev = next;
- if (slope == Slope::Unknown)
- {
- slope = delta > 0 ? Slope::Increasing : Slope::Decreasing;
- }
+ checkLastLevel(Slope::Decreasing, Slope::Increasing, -delta, -1, data);
}
}
- if (isSafe)
+ if (data.isSafe)
{
- part1++;
+ if (data.canUseDampener)
+ {
+ part1++;
+ }
+ part2++;
}
}
void RedNosedReports::finish()
{
}
+
+void RedNosedReports::checkLastLevel(const Slope sameSlope, const Slope otherSlope,
+ const int delta, const int sign, RedNosedReportData& data)
+{
+ if (data.slope == sameSlope)
+ {
+ if (delta > 3)
+ {
+ // X X
+ // 1 2 6 8 7 3
+ data.mustSkipPrevious = true;
+ data.isSafe = data.canUseDampener;
+ data.canUseDampener = false;
+ }
+ }
+ else if (data.slope == otherSlope)
+ {
+ if (data.levels.size() == 3 && sign * (data.levels[2] - data.levels[0]) <= 3)
+ {
+ // X X next X X next
+ // first 3 2 6 ??? first 6 7 3 ???
+ data.mustCheckSlopeReversal = true;
+ }
+ else
+ {
+ // X X
+ // first 3 2 7 first 6 7 2
+ // 3 2 1 4 6 7 8 5
+ data.mustSkipPrevious = true;
+ }
+ data.isSafe = data.canUseDampener;
+ data.canUseDampener = false;
+ }
+ else // slope == Slope::Unknown
+ {
+ if (delta <= 3)
+ {
+ data.slope = sameSlope;
+ }
+ if (data.mustAwaitFourLevels)
+ {
+ if (delta <= 3
+ && ((0 < sign * (data.levels[2] - data.levels[0]) && sign * (data.levels[2] - data.levels[0]) <= 3)
+ || (0 < sign * (data.levels[2] - data.levels[1]) && sign * (data.levels[2] - data.levels[1]) <= 3)))
+ {
+ // X X X X
+ // first 1 5 3 4 first 8 4 6 5
+ data.mustAwaitFourLevels = false;
+ }
+ else
+ {
+ data.isSafe = false;
+ }
+ }
+ else if (delta > 3)
+ {
+ // X X next X X next
+ // first 1 5 ??? first 8 4 ???
+ data.mustAwaitFourLevels = true;
+ data.isSafe = data.canUseDampener;
+ data.canUseDampener = false;
+ }
+ }
+}
diff --git a/AdventOfCode2024/RedNosedReports.h b/AdventOfCode2024/RedNosedReports.h
index ea8cd0c..3386c7f 100644
--- a/AdventOfCode2024/RedNosedReports.h
+++ b/AdventOfCode2024/RedNosedReports.h
@@ -15,7 +15,9 @@
#pragma once
+#include "Slope.h"
#include "Solver.h"
+#include "RedNosedReportData.h"
class RedNosedReports :
public Solver
@@ -25,6 +27,7 @@ class RedNosedReports :
std::string getInputFileName() const override;
void processDataLine(const std::string& line) override;
void finish() override;
+private:
+ void checkLastLevel(const Slope sameSlope, const Slope otherSlope,
+ const int delta, const int sign, RedNosedReportData& data);
};
-
-enum class Slope { Unknown, Increasing, Decreasing };
diff --git a/AdventOfCode2024/Slope.h b/AdventOfCode2024/Slope.h
new file mode 100644
index 0000000..3aef8e4
--- /dev/null
+++ b/AdventOfCode2024/Slope.h
@@ -0,0 +1,18 @@
+// Solutions to the Advent Of Code 2024.
+// Copyright (C) 2024 Stefan Müller
+//
+// This program is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your option) any later
+// version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see .
+
+#pragma once
+
+enum class Slope { Unknown, Increasing, Decreasing };
diff --git a/README.md b/README.md
index 42536f0..df55d83 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,12 @@ The solution contains a unit test project to help troubleshoot issues and preven
I'm using a `std::multiset` to collect and sort the values for both lists. This allows to use a single iteration of the left list and two iterations of the right list simultaneously to solve both parts. Nice application of iterators.
+### Day 2: Red-Nosed Reports
+
+:mag_right: Puzzle: , :white_check_mark: Solver: [`HistorianHysteria.cpp`](AdventOfCode2024/RedNosedReports.cpp)
+
+Here, we have a few conditionals to determine on the fly which of the numbers would make the report safe if dropped. The amount of cases is actually quite manageable.
+
## License
Copyright (C) 2024 Stefan Müller