99 lines
2.7 KiB
C++
99 lines
2.7 KiB
C++
// :autocmd BufWritePost *.cpp :silent exec "!script/async-build 7"
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <numeric>
|
|
#include <ranges>
|
|
#include <set>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
using Grid = std::vector<std::string>;
|
|
using Location = std::tuple<size_t, size_t>;
|
|
|
|
uint64_t part_1(const Grid &grid);
|
|
uint64_t part_2(const Grid &grid);
|
|
|
|
int main() {
|
|
Grid grid;
|
|
std::ifstream file{"input/2025-7.txt"};
|
|
std::string line;
|
|
while (std::getline(file, line)) {
|
|
grid.emplace_back(line);
|
|
}
|
|
std::cout << "Part 1: " << part_1(grid) << std::endl;
|
|
std::cout << "Part 2: " << part_2(grid) << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
char at_loc(const Grid &grid, size_t row, size_t col) {
|
|
if (row >= 0 && row < grid.size() && col >= 0 && col < grid[row].size()) {
|
|
return grid[row][col];
|
|
} else {
|
|
return '.';
|
|
}
|
|
}
|
|
|
|
Location find_start(const Grid &grid) {
|
|
const auto col{grid[0].find_first_of('S')};
|
|
if (col != std::string::npos) {
|
|
return {0, col};
|
|
} else {
|
|
std::unreachable();
|
|
}
|
|
}
|
|
|
|
uint64_t part_1(const Grid &grid) {
|
|
uint64_t ans{0};
|
|
Location start{find_start(grid)};
|
|
const auto [start_row, start_col]{start};
|
|
std::set<size_t> cols{};
|
|
cols.insert(start_col);
|
|
for (size_t row{start_row}; row < grid.size(); ++row) {
|
|
std::set<size_t> next_cols{};
|
|
for (auto col : cols) {
|
|
if (at_loc(grid, row, col) == '^') {
|
|
ans += 1;
|
|
next_cols.insert(col + 1);
|
|
next_cols.insert(col - 1);
|
|
} else {
|
|
next_cols.insert(col);
|
|
}
|
|
}
|
|
cols = next_cols;
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
void insert_or_increment(std::map<size_t, uint64_t> &cols, size_t col,
|
|
uint64_t value) {
|
|
cols.insert({col, 0}).first->second += value;
|
|
}
|
|
|
|
uint64_t part_2(const Grid &grid) {
|
|
Location start = find_start(grid);
|
|
const auto [start_row, start_col]{start};
|
|
using namespace std::ranges;
|
|
auto view = iota_view{start_row, grid.size()};
|
|
std::map<size_t, uint64_t> starting_cols{{start_col, 1}};
|
|
auto cols = fold_left(view, starting_cols, [&grid](auto cols, auto row) {
|
|
return fold_left(cols, std::map<size_t, uint64_t>{},
|
|
[&grid, &row](auto next_cols, auto col_cnt) {
|
|
auto [col, cnt] = col_cnt;
|
|
if (at_loc(grid, row, col) == '^') {
|
|
insert_or_increment(next_cols, col - 1, cnt);
|
|
insert_or_increment(next_cols, col + 1, cnt);
|
|
} else {
|
|
insert_or_increment(next_cols, col, cnt);
|
|
}
|
|
return next_cols;
|
|
});
|
|
});
|
|
return fold_left(cols, 0ull, [](const uint64_t acc, const auto &entry) {
|
|
return acc + entry.second;
|
|
});
|
|
}
|