Make Grid iterable
This commit is contained in:
parent
9e6223f886
commit
d6fc0396cb
|
@ -17,13 +17,13 @@ auto Part1(aocpp::Grid const &input, std::int64_t reps = 10'000) -> std::int64_t
|
||||||
std::unordered_set<aocpp::Coord> infected;
|
std::unordered_set<aocpp::Coord> infected;
|
||||||
|
|
||||||
// Initialize set of infected locations
|
// Initialize set of infected locations
|
||||||
input.each([&infected](auto const pos, auto const cell)
|
for (auto [pos, cell] : input)
|
||||||
{
|
{
|
||||||
if (cell == '#')
|
if (cell == '#')
|
||||||
{
|
{
|
||||||
infected.insert(pos);
|
infected.insert(pos);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// Start in the middle
|
// Start in the middle
|
||||||
aocpp::Coord pos;
|
aocpp::Coord pos;
|
||||||
|
@ -62,13 +62,13 @@ auto Part2(aocpp::Grid const &input, std::int64_t reps = 10'000'000) -> std::int
|
||||||
std::unordered_map<aocpp::Coord, char> cells;
|
std::unordered_map<aocpp::Coord, char> cells;
|
||||||
|
|
||||||
// Initialize set of infected locations
|
// Initialize set of infected locations
|
||||||
input.each([&cells](auto const pos, auto const cell)
|
for (auto [pos, cell] : input)
|
||||||
{
|
{
|
||||||
if (cell == '#')
|
if (cell == '#')
|
||||||
{
|
{
|
||||||
cells.try_emplace(pos, '#');
|
cells.try_emplace(pos, '#');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// Start in the middle
|
// Start in the middle
|
||||||
aocpp::Coord pos;
|
aocpp::Coord pos;
|
||||||
|
|
|
@ -60,11 +60,11 @@ Game::Game(Grid grid)
|
||||||
, debug_out_{}
|
, debug_out_{}
|
||||||
{
|
{
|
||||||
// set each unit to its initial hit points
|
// set each unit to its initial hit points
|
||||||
grid_.each([&](auto k, auto v) {
|
for (auto [k, v] : grid_) {
|
||||||
if (IsUnit(v)) {
|
if (IsUnit(v)) {
|
||||||
units_[k] = initial_hp;
|
units_[k] = initial_hp;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the game as seen in the examples
|
// Render the game as seen in the examples
|
||||||
|
@ -166,9 +166,9 @@ auto Game::Simulate() -> std::optional<int> {
|
||||||
|
|
||||||
// Detect when no targets remain for this unit and end the game
|
// Detect when no targets remain for this unit and end the game
|
||||||
auto game_over = true;
|
auto game_over = true;
|
||||||
grid_.each([&](auto k, auto v) {
|
for (auto [k, v] : grid_) {
|
||||||
if (IsOpposed(active_team, v)) game_over = false;
|
if (IsOpposed(active_team, v)) game_over = false;
|
||||||
});
|
}
|
||||||
if (game_over) {
|
if (game_over) {
|
||||||
int total_hp = 0;
|
int total_hp = 0;
|
||||||
for (auto const& [_,v] : units_) { total_hp += v; }
|
for (auto const& [_,v] : units_) { total_hp += v; }
|
||||||
|
|
12
2019/10.cpp
12
2019/10.cpp
|
@ -70,23 +70,23 @@ auto ClearView(Grid const& grid, Coord src, Coord dst) -> bool {
|
||||||
auto Part1(Grid const& grid) {
|
auto Part1(Grid const& grid) {
|
||||||
std::size_t best = 0;
|
std::size_t best = 0;
|
||||||
Coord base {};
|
Coord base {};
|
||||||
grid.each([&](Coord src, char s) {
|
for (auto [src, s] : grid) {
|
||||||
if ('#' == s) {
|
if ('#' == s) {
|
||||||
std::size_t visible = 0;
|
std::size_t visible = 0;
|
||||||
grid.each([&](Coord dst, char d){
|
for (auto [dst, d] : grid) {
|
||||||
if ('#' == d && src != dst) {
|
if ('#' == d && src != dst) {
|
||||||
if (ClearView(grid, src, dst)) {
|
if (ClearView(grid, src, dst)) {
|
||||||
visible++;
|
visible++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (visible > best) {
|
if (visible > best) {
|
||||||
best = visible;
|
best = visible;
|
||||||
base = src;
|
base = src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return std::make_pair(best, base);
|
return std::make_pair(best, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +94,11 @@ auto Part2(Grid const& grid, Coord base, std::size_t n) {
|
||||||
std::map<Rational<std::int64_t>, std::vector<Coord>> targets;
|
std::map<Rational<std::int64_t>, std::vector<Coord>> targets;
|
||||||
|
|
||||||
// arrange all the other asteroids by their angle relative to the base
|
// arrange all the other asteroids by their angle relative to the base
|
||||||
grid.each([&](Coord c, char v){
|
for (auto [c, v] : grid){
|
||||||
if (c != base && v == '#') {
|
if (c != base && v == '#') {
|
||||||
targets[angle(c-base)].push_back(c);
|
targets[angle(c-base)].push_back(c);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
// Sort to vectors per angle such that the nearest asteroids are at
|
// Sort to vectors per angle such that the nearest asteroids are at
|
||||||
// the end of the list
|
// the end of the list
|
||||||
|
|
|
@ -66,14 +66,14 @@ auto ComputePath(Grid const& grid)
|
||||||
{
|
{
|
||||||
// Determine starting location and direction
|
// Determine starting location and direction
|
||||||
Coord start{}, step{};
|
Coord start{}, step{};
|
||||||
grid.each([&](Coord c, char v) {
|
for (auto [c, v] : grid) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case '^': start = c; step = { 0, -1}; break;
|
case '^': start = c; step = { 0, -1}; break;
|
||||||
case '>': start = c; step = { 0, 1}; break;
|
case '>': start = c; step = { 0, 1}; break;
|
||||||
case '<': start = c; step = {-1, 0}; break;
|
case '<': start = c; step = {-1, 0}; break;
|
||||||
case 'v': start = c; step = { 0, 1}; break;
|
case 'v': start = c; step = { 0, 1}; break;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
auto is_path = [&](Coord c) {
|
auto is_path = [&](Coord c) {
|
||||||
return grid.contains(c) && grid[c] == '#';
|
return grid.contains(c) && grid[c] == '#';
|
||||||
|
|
|
@ -41,11 +41,11 @@ auto SetKey(Doors& doors, char key) {
|
||||||
|
|
||||||
auto FindFeatures(Grid const& grid) -> Features {
|
auto FindFeatures(Grid const& grid) -> Features {
|
||||||
Features features;
|
Features features;
|
||||||
grid.each([&](Coord c, char v) {
|
for (auto [c, v] : grid) {
|
||||||
if ('#' != v && '.' != v) {
|
if ('#' != v && '.' != v) {
|
||||||
features[v] = c;
|
features[v] = c;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ auto FindBugs(Grid const& grid) -> std::vector<Coord> {
|
||||||
std::int64_t w = grid.Cols();
|
std::int64_t w = grid.Cols();
|
||||||
std::int64_t h = grid.Rows();
|
std::int64_t h = grid.Rows();
|
||||||
|
|
||||||
grid.each([&](Coord c, char v) {
|
for (auto [c, v] : grid) {
|
||||||
if (v == '#') result.push_back(c);
|
if (v == '#') result.push_back(c);
|
||||||
});
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ Dir directions[4] {Up, Down, Left, Right};
|
||||||
auto Part1(Grid const& grid) -> std::int64_t
|
auto Part1(Grid const& grid) -> std::int64_t
|
||||||
{
|
{
|
||||||
std::int64_t result {0};
|
std::int64_t result {0};
|
||||||
grid.each([&](Coord const c, char const v) {
|
for (auto [c, v] : grid) {
|
||||||
result += std::any_of(
|
result += std::any_of(
|
||||||
std::begin(directions), std::end(directions),
|
std::begin(directions), std::end(directions),
|
||||||
[&](Dir const dir) {
|
[&](Dir const dir) {
|
||||||
|
@ -31,14 +31,14 @@ auto Part1(Grid const& grid) -> std::int64_t
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Part2(Grid const& grid) -> std::int64_t
|
auto Part2(Grid const& grid) -> std::int64_t
|
||||||
{
|
{
|
||||||
std::int64_t result {0};
|
std::int64_t result {0};
|
||||||
grid.each([&](Coord const c, char const v) {
|
for (auto [c, v] : grid) {
|
||||||
auto score = std::transform_reduce(
|
auto score = std::transform_reduce(
|
||||||
std::begin(directions), std::end(directions),
|
std::begin(directions), std::end(directions),
|
||||||
std::int64_t{1}, std::multiplies(), // product
|
std::int64_t{1}, std::multiplies(), // product
|
||||||
|
@ -51,7 +51,7 @@ auto Part2(Grid const& grid) -> std::int64_t
|
||||||
return count;
|
return count;
|
||||||
});
|
});
|
||||||
if (result < score) result = score;
|
if (result < score) result = score;
|
||||||
});
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,13 @@ auto Parse(std::istream & in) -> std::tuple<Coord, std::vector<Coord>, Coord, Gr
|
||||||
auto& end = std::get<2>(result);
|
auto& end = std::get<2>(result);
|
||||||
auto& grid = std::get<3>(result);
|
auto& grid = std::get<3>(result);
|
||||||
|
|
||||||
grid.each([&](Coord c, char v) {
|
for (auto [c, v] : grid) {
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 'S': grid[c] = 'a'; start1 = c; break;
|
case 'S': grid[c] = 'a'; start1 = c; break;
|
||||||
case 'E': grid[c] = 'z'; end = c; break;
|
case 'E': grid[c] = 'z'; end = c; break;
|
||||||
case 'a': starts2.push_back(c); break;
|
case 'a': starts2.push_back(c); break;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
add_library(aocpp src/Startup.cpp src/Coord.cpp src/Parsing.cpp)
|
add_library(aocpp src/Startup.cpp src/Coord.cpp src/Parsing.cpp src/Grid.cpp)
|
||||||
target_include_directories(aocpp PUBLIC include)
|
target_include_directories(aocpp PUBLIC include)
|
||||||
target_link_libraries(aocpp Boost::headers)
|
target_link_libraries(aocpp Boost::headers)
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef AOCPP_GRID_HPP_
|
#ifndef AOCPP_GRID_HPP_
|
||||||
#define AOCPP_GRID_HPP_
|
#define AOCPP_GRID_HPP_
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -12,6 +11,31 @@
|
||||||
|
|
||||||
namespace aocpp {
|
namespace aocpp {
|
||||||
|
|
||||||
|
struct Grid;
|
||||||
|
|
||||||
|
struct GridElement {
|
||||||
|
const Coord pos;
|
||||||
|
char elt;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GridIterator {
|
||||||
|
Grid const& grid_;
|
||||||
|
std::int64_t x_, y_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GridIterator(Grid const& grid, std::int64_t x, std::int64_t y)
|
||||||
|
: grid_{grid}, x_{x}, y_{y} {}
|
||||||
|
|
||||||
|
auto operator++() -> GridIterator&;
|
||||||
|
|
||||||
|
auto operator*() -> GridElement;
|
||||||
|
|
||||||
|
auto operator==(GridIterator const& rhs) const -> bool
|
||||||
|
{
|
||||||
|
return x_ == rhs.x_ && y_ == rhs.y_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Grid {
|
struct Grid {
|
||||||
std::vector<std::string> rows;
|
std::vector<std::string> rows;
|
||||||
std::size_t columns;
|
std::size_t columns;
|
||||||
|
@ -57,28 +81,16 @@ struct Grid {
|
||||||
}
|
}
|
||||||
result.rows.emplace_back(std::move(line));
|
result.rows.emplace_back(std::move(line));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
result.columns = 0;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
auto begin() const -> GridIterator {
|
||||||
* @brief Apply the callback function across all elements of the grid.
|
return GridIterator{*this, 0, 0};
|
||||||
*
|
|
||||||
* @tparam F Type of callback
|
|
||||||
* @param f Callback function
|
|
||||||
*/
|
|
||||||
template <std::invocable<Coord, char> F>
|
|
||||||
auto each(F f = F{}) const -> void {
|
|
||||||
auto const h = rows.size();
|
|
||||||
for (std::size_t y = 0; y < h; y++) {
|
|
||||||
auto const& row = rows[y];
|
|
||||||
auto const w = row.size();
|
|
||||||
for (std::size_t x = 0; x < w; x++) {
|
|
||||||
f(Coord{static_cast<std::int64_t>(x), static_cast<std::int64_t>(y)}, row[x]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto end() const -> GridIterator {
|
||||||
|
return GridIterator{*this, 0, static_cast<std::int64_t>(rows.size())};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
19
lib/src/Grid.cpp
Normal file
19
lib/src/Grid.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "aocpp/Grid.hpp"
|
||||||
|
|
||||||
|
namespace aocpp {
|
||||||
|
auto GridIterator::operator*() -> GridElement
|
||||||
|
{
|
||||||
|
return {{x_, y_}, grid_[Coord{x_, y_}]};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GridIterator::operator++() -> GridIterator &
|
||||||
|
{
|
||||||
|
if (++x_ == grid_.columns)
|
||||||
|
{
|
||||||
|
x_ = 0;
|
||||||
|
y_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
} // namespace
|
Loading…
Reference in New Issue
Block a user