Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <cassert>
- #include <iostream>
- #include <fstream>
- #include <sstream>
- #include <vector>
- #include <iterator>
- #include <algorithm>
- #include <unordered_set>
- #include <boost/container_hash/hash.hpp>
- #include <range/v3/algorithm/count_if.hpp>
- #include <range/v3/algorithm/copy.hpp>
- #include <range/v3/view/transform.hpp>
- #include <range/v3/view/filter.hpp>
- #include <range/v3/view/remove.hpp>
- #include <range/v3/view/iota.hpp>
- #include <range/v3/view/cartesian_product.hpp>
- #include <range/v3/range/conversion.hpp>
- inline std::string read_file(std::string_view path) {
- std::ifstream is(path.data());
- return static_cast<std::stringstream const&>(std::stringstream() << is.rdbuf()).str();
- }
- namespace day17 {
- namespace a {
- using point = std::array<int, 3>;
- using point_set = std::unordered_set<point, boost::hash<point>>;
- point_set step(const point_set& from) {
- using namespace ranges;
- auto ret = point_set{};
- auto done = point_set{};
- auto q = std::vector<point>( from.begin(), from.end() );
- auto get_neighbours = [](point p) {
- static const auto offsets = views::cartesian_product(
- views::ints(-1, 2),
- views::ints(-1, 2),
- views::ints(-1, 2))
- | views::remove(std::tuple{ 0,0,0 })
- | views::transform([](auto t) { auto [x, y, z] = t; return point{ x,y,z }; })
- | to<std::vector>();
- return offsets | views::transform([&](point offset) -> point {
- std::transform(p.begin(), p.end(), offset.begin(), offset.begin(), std::plus<>());
- return offset;
- });
- };
- while (!q.empty()) {
- auto p = q.back(); q.pop_back();
- done.insert(p);
- auto neighbours = get_neighbours(p);
- auto active_neighbours = count_if(neighbours, [&](point a) { return from.count(a); });
- if (from.count(p)) {
- if (active_neighbours == 2 || active_neighbours == 3) {
- ret.insert(p);
- }
- copy(neighbours | views::filter([&](point a) { return !done.count(a); }), std::back_inserter(q));
- } else if (active_neighbours == 3) {
- ret.insert(p);
- }
- }
- return ret;
- }
- inline auto execute(std::string s) {
- auto active = point_set{ };
- auto iss = std::istringstream{ s };
- auto line = std::string{ };
- auto y = 0;
- while (std::getline(iss, line)) {
- auto x = 0;
- for (auto c : line) {
- if (c == '#')
- active.insert({x,y,0});
- ++x;
- }
- ++y;
- }
- for (int i = 0; i < 6; ++i) {
- active = step(std::move(active));
- }
- return active.size();
- }
- inline void run() {
- auto sample_result = 112;
- assert(execute(read_file("day17.sample")) == sample_result);
- std::cout << "day17a: " << execute(read_file("day17.txt")) << std::endl;
- }
- }
- namespace b {
- using point = std::array<int, 4>;
- using point_set = std::unordered_set<point, boost::hash<point>>;
- point_set step(const point_set& from) {
- using namespace ranges;
- auto ret = point_set{};;
- auto done = point_set{};
- auto q = std::vector<point>( from.begin(), from.end() );
- auto get_neighbours = [](point p) {
- static const auto offsets = views::cartesian_product(
- views::ints(-1, 2),
- views::ints(-1, 2),
- views::ints(-1, 2),
- views::ints(-1, 2))
- | views::remove(std::tuple{ 0,0,0,0 })
- | views::transform([](auto t) { auto [x, y, z, w] = t; return point{ x,y,z,w }; })
- | to<std::vector>();
- return offsets | views::transform([&](point offset) -> point {
- std::transform(p.begin(), p.end(), offset.begin(), offset.begin(), std::plus<>());
- return offset;
- });
- };
- while (!q.empty()) {
- auto p = q.back(); q.pop_back();
- done.insert(p);
- auto neighbours = get_neighbours(p);
- auto active_neighbours = count_if(neighbours, [&](point a) { return from.count(a); });
- if (from.count(p)) {
- if (active_neighbours == 2 || active_neighbours == 3) {
- ret.insert(p);
- }
- copy(neighbours | views::filter([&](point a) { return !done.count(a); }), std::back_inserter(q));
- } else if (active_neighbours == 3) {
- ret.insert(p);
- }
- }
- return ret;
- }
- inline auto execute(std::string s) {
- auto active = point_set{};
- auto iss = std::istringstream{ s };
- auto line = std::string{};
- auto y = 0;
- while (std::getline(iss, line)) {
- auto x = 0;
- for (auto c : line) {
- if (c == '#')
- active.insert({x,y,0,0});
- ++x;
- }
- ++y;
- }
- for (int i = 0; i < 6; ++i) {
- active = step(std::move(active));
- }
- return active.size();
- }
- inline void run() {
- auto sample_result = 848;
- assert(execute(read_file("day17.sample")) == sample_result);
- std::cout << "day17 sample" << execute(read_file("day17.sample")) << std::endl;
- std::cout << "day17b: " << execute(read_file("day17.txt")) << std::endl;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement