Day6
This commit is contained in:
parent
43448aaeb6
commit
b922c94b43
6 changed files with 273 additions and 5 deletions
244
day6/main.cpp
Normal file
244
day6/main.cpp
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <cstddef>
|
||||
#include <expected>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <mdspan>
|
||||
#include <numeric>
|
||||
#include <print>
|
||||
#include <ranges>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
struct ColumnData {
|
||||
std::vector<int> numbers;
|
||||
char op;
|
||||
};
|
||||
|
||||
struct Diagram {
|
||||
std::vector<char> data;
|
||||
size_t width;
|
||||
size_t height;
|
||||
|
||||
using GridView = std::mdspan<char, std::dextents<size_t, 2>>;
|
||||
|
||||
auto grid() { return GridView(data.data(), height, width); }
|
||||
};
|
||||
|
||||
auto printDiagram(Diagram &diagram) {
|
||||
auto grid = diagram.grid();
|
||||
for (auto row = 0UZ; row != grid.extent(0); row++) {
|
||||
for (auto col = 0UZ; col != grid.extent(1); col++) {
|
||||
std::print("{}", grid[row, col]);
|
||||
}
|
||||
std::println();
|
||||
}
|
||||
// std::println("Map: {}", diagram.data);
|
||||
std::println("Width: {}", diagram.width);
|
||||
std::println("Height: {}", diagram.height);
|
||||
}
|
||||
|
||||
template <typename T> auto parseLine(std::string_view line) -> std::vector<T> {
|
||||
auto to_value = [](auto &&subrange) -> T {
|
||||
auto str = std::string_view(subrange);
|
||||
T value{};
|
||||
if constexpr (std::is_same_v<T, char>) {
|
||||
return str[0];
|
||||
} else {
|
||||
std::from_chars(str.data(), str.data() + str.size(), value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
return line | std::views::split(' ') | std::views::filter([](auto &&range) -> bool { return !range.empty(); }) |
|
||||
std::views::transform(to_value) | std::ranges::to<std::vector<T>>();
|
||||
}
|
||||
|
||||
static auto parseInput(const std::string &filename) -> std::expected<std::vector<ColumnData>, std::string> {
|
||||
std::ifstream inputF{filename};
|
||||
|
||||
if (!inputF) {
|
||||
return std::unexpected{"Some file open error."};
|
||||
}
|
||||
std::vector<ColumnData> puzzleInput{};
|
||||
|
||||
std::vector<std::string> rawLines;
|
||||
std::string puzzleLine;
|
||||
while (std::getline(inputF, puzzleLine)) {
|
||||
if (!puzzleLine.empty()) {
|
||||
rawLines.push_back(std::move(puzzleLine));
|
||||
}
|
||||
}
|
||||
if (rawLines.empty()) {
|
||||
return std::unexpected{"No lines."};
|
||||
}
|
||||
|
||||
auto operatorLine = rawLines.back();
|
||||
auto num_lines = rawLines | std::views::take(rawLines.size() - 1);
|
||||
|
||||
std::vector<char> ops = parseLine<char>(operatorLine);
|
||||
|
||||
auto grid =
|
||||
num_lines |
|
||||
std::views::transform([](const std::string &string) -> std::vector<int> { return parseLine<int>(string); }) |
|
||||
std::ranges::to<std::vector<std::vector<int>>>();
|
||||
|
||||
size_t width = ops.size();
|
||||
bool consistent = std::ranges::all_of(grid, [width](const auto &row) -> bool { return row.size() == width; });
|
||||
if (!consistent) {
|
||||
return std::unexpected{"Error: Row width mismatch."};
|
||||
}
|
||||
|
||||
auto columns = std::views::iota(0UZ, width) | std::views::transform([&](size_t col_idx) -> ColumnData {
|
||||
// Collect numbers for this column from the grid
|
||||
auto col_nums = grid |
|
||||
std::views::transform([col_idx](const auto &row) { return row[col_idx]; }) |
|
||||
std::ranges::to<std::vector<int>>();
|
||||
|
||||
return ColumnData{.numbers = std::move(col_nums), .op = ops[col_idx]};
|
||||
}) |
|
||||
std::ranges::to<std::vector<ColumnData>>();
|
||||
std::cout << "Parsed " << columns.size() << " columns with " << grid.size() << " operands each:\n";
|
||||
|
||||
for (const auto &col : columns) {
|
||||
std::cout << "[ ";
|
||||
for (int n : col.numbers) {
|
||||
std::cout << n << " ";
|
||||
}
|
||||
std::cout << "] Op: " << col.op << "\n";
|
||||
}
|
||||
return std::move(columns);
|
||||
}
|
||||
|
||||
static auto parseInput_p2(const std::string &filename) -> std::expected<Diagram, std::string> {
|
||||
std::ifstream inputF{filename};
|
||||
|
||||
if (!inputF) {
|
||||
return std::unexpected{"Some file open error."};
|
||||
}
|
||||
Diagram puzzleInput{};
|
||||
int maxWidth = 0;
|
||||
std::string puzzleLine;
|
||||
while (std::getline(inputF, puzzleLine)) {
|
||||
if (!puzzleLine.empty()) {
|
||||
std::ranges::reverse(puzzleLine);
|
||||
for (auto c : puzzleLine) {
|
||||
puzzleInput.data.emplace_back(c);
|
||||
}
|
||||
puzzleInput.width = puzzleLine.length();
|
||||
puzzleInput.height++;
|
||||
}
|
||||
}
|
||||
|
||||
std::println("{}", puzzleInput.data);
|
||||
printDiagram(puzzleInput);
|
||||
return puzzleInput;
|
||||
}
|
||||
|
||||
auto calculate_column(const ColumnData &col) -> long long {
|
||||
if (col.op == '+') {
|
||||
return std::ranges::fold_left(col.numbers, 0LL, std::plus());
|
||||
}
|
||||
if (col.op == '*') {
|
||||
return std::ranges::fold_left(col.numbers, 1LL, std::multiplies());
|
||||
}
|
||||
return 0; // Fallback
|
||||
}
|
||||
|
||||
auto cephalopodMath(const std::vector<ColumnData> &columns) -> long long {
|
||||
long long grand_total = std::ranges::fold_left(columns | std::views::transform(calculate_column), 0LL, std::plus{});
|
||||
return grand_total;
|
||||
}
|
||||
auto cephalopodMath_p2(Diagram &diagram) -> long long {
|
||||
long long grandTotal{};
|
||||
|
||||
long long currentNumber = 0;
|
||||
std::vector<long long> columnNumbers{};
|
||||
auto grid = diagram.grid();
|
||||
for (auto col = 0UZ; col != grid.extent(1); col++) {
|
||||
for (auto row = 0UZ; row != grid.extent(0); row++) {
|
||||
char cur = grid[row, col];
|
||||
|
||||
if (cur == ' ' && currentNumber == 0) {
|
||||
// std::print("s");
|
||||
continue;
|
||||
} else if (cur == ' ') {
|
||||
columnNumbers.emplace_back(currentNumber);
|
||||
currentNumber = 0;
|
||||
std::print("_");
|
||||
continue;
|
||||
} else if (cur == '*') {
|
||||
if (currentNumber != 0) {
|
||||
columnNumbers.emplace_back(currentNumber);
|
||||
}
|
||||
std::print("*");
|
||||
auto total = std::ranges::fold_left(columnNumbers, 1LL, std::multiplies());
|
||||
grandTotal += total;
|
||||
std::print("\nMultiplying {}: Result: {}\n", columnNumbers, total);
|
||||
currentNumber = 0;
|
||||
columnNumbers.clear();
|
||||
continue;
|
||||
} else if (cur == '+') {
|
||||
if (currentNumber != 0) {
|
||||
columnNumbers.emplace_back(currentNumber);
|
||||
}
|
||||
std::print("+");
|
||||
auto total = std::ranges::fold_left(columnNumbers, 0LL, std::plus());
|
||||
grandTotal += total;
|
||||
std::print("\nAdding {}: Result: {}\n", columnNumbers, total);
|
||||
|
||||
currentNumber = 0;
|
||||
columnNumbers.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
// cur must be a digit...
|
||||
currentNumber = (currentNumber * 10) + (cur - '0');
|
||||
std::print("{}", cur);
|
||||
}
|
||||
}
|
||||
return grandTotal;
|
||||
}
|
||||
|
||||
auto main() -> int {
|
||||
// auto testCase = parseInput("test_input");
|
||||
// if (testCase) {
|
||||
|
||||
// auto testResult = cephalopodMath(*testCase);
|
||||
// std::println("P1 Testcase result: {}", testResult);
|
||||
// } else {
|
||||
// std::print("{}\n", testCase.error());
|
||||
// }
|
||||
|
||||
auto testCase_p2 = parseInput_p2("test_input");
|
||||
if (testCase_p2) {
|
||||
auto testResult_p2 = cephalopodMath_p2(*testCase_p2);
|
||||
std::println("P2 Testcase result: {}", testResult_p2);
|
||||
} else {
|
||||
std::print("{}\n", testCase_p2.error());
|
||||
}
|
||||
|
||||
auto realPuzzle = parseInput_p2("puzzle_input");
|
||||
if (realPuzzle) {
|
||||
// auto realResult = cephalopodMath(*realPuzzle);
|
||||
// std::println("P1 Real result: {}", realResult);
|
||||
|
||||
auto realResultP2 = cephalopodMath_p2(*realPuzzle);
|
||||
std::println("P2 Real result: {}", realResultP2);
|
||||
} else {
|
||||
std::print("{}\n", realPuzzle.error());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue