Add solution for "Day 2: Red-Nosed Reports", part 2
This commit is contained in:
parent
fe67687bf7
commit
50fd4efc75
|
@ -131,6 +131,7 @@
|
|||
<ClCompile Include="AdventOfCode2024.cpp" />
|
||||
<ClCompile Include="HistorianHysteria.cpp" />
|
||||
<ClCompile Include="Program.cpp" />
|
||||
<ClCompile Include="RedNosedReportData.cpp" />
|
||||
<ClCompile Include="RedNosedReports.cpp" />
|
||||
<ClCompile Include="Solver.cpp" />
|
||||
<ClCompile Include="SolverEngine.cpp" />
|
||||
|
@ -138,7 +139,9 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="HistorianHysteria.h" />
|
||||
<ClInclude Include="Program.h" />
|
||||
<ClInclude Include="RedNosedReportData.h" />
|
||||
<ClInclude Include="RedNosedReports.h" />
|
||||
<ClInclude Include="Slope.h" />
|
||||
<ClInclude Include="Solver.h" />
|
||||
<ClInclude Include="SolverEngine.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
<ClCompile Include="RedNosedReports.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RedNosedReportData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SolverEngine.h">
|
||||
|
@ -50,5 +53,11 @@
|
|||
<ClInclude Include="RedNosedReports.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RedNosedReportData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Slope.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1 @@
|
|||
#include "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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include<vector>
|
||||
|
||||
#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<int> levels{};
|
||||
};
|
|
@ -15,9 +15,9 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "RedNosedReports.h"
|
||||
#include <iomanip>
|
||||
|
||||
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
|
||||
{
|
||||
prev = next;
|
||||
if (slope == Slope::Unknown)
|
||||
// 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)
|
||||
{
|
||||
slope = delta > 0 ? Slope::Increasing : Slope::Decreasing;
|
||||
// X
|
||||
// 1 1
|
||||
data.isSafe = data.canUseDampener;
|
||||
data.canUseDampener = false;
|
||||
}
|
||||
else if (delta > 0)
|
||||
{
|
||||
checkLastLevel(Slope::Increasing, Slope::Decreasing, delta, 1, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
checkLastLevel(Slope::Decreasing, Slope::Increasing, -delta, -1, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSafe)
|
||||
if (data.isSafe)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
enum class Slope { Unknown, Increasing, Decreasing };
|
|
@ -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: <https://adventofcode.com/2024/day/2>, :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
|
||||
|
|
Loading…
Reference in New Issue