Advertisement
Guest User

Untitled

a guest
Dec 17th, 2020
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.61 KB | None | 0 0
  1. #include <cassert>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <sstream>
  5.  
  6. #include <vector>
  7. #include <iterator>
  8. #include <algorithm>
  9. #include <unordered_set>
  10. #include <set>
  11.  
  12. #include <boost/container_hash/hash.hpp>
  13. #include <boost/fusion/algorithm/auxiliary/copy.hpp>
  14. #include <boost/fusion/adapted/std_array.hpp>
  15. #include <boost/fusion/adapted/std_tuple.hpp>
  16.  
  17. #include <range/v3/algorithm/count_if.hpp>
  18. #include <range/v3/algorithm/copy.hpp>
  19. #include <range/v3/view/transform.hpp>
  20. #include <range/v3/view/filter.hpp>
  21. #include <range/v3/view/remove.hpp>
  22. #include <range/v3/view/iota.hpp>
  23. #include <range/v3/view/join.hpp>
  24. #include <range/v3/view/concat.hpp>
  25. #include <range/v3/view/cartesian_product.hpp>
  26. #include <range/v3/range/conversion.hpp>
  27.  
  28. inline std::string read_file(std::string_view path) {
  29.     std::ifstream is(path.data());
  30.     return static_cast<std::stringstream const&>(std::stringstream() << is.rdbuf()).str();
  31. }
  32.  
  33. namespace day17 {
  34.  
  35.     template <class point>
  36.     auto get_neighbours_impl(point p) {
  37.         using namespace ranges;
  38.  
  39.         constexpr auto I = std::tuple_size_v<point>;
  40.         static const auto offsets =
  41.             [] {
  42.             if constexpr (I == 3) {
  43.                 return views::cartesian_product(
  44.                     views::ints(-1, 2),
  45.                     views::ints(-1, 2),
  46.                     views::ints(-1, 2))| views::transform([](auto t) { point ret; boost::fusion::copy<std::tuple<int,int,int>, std::array<int,3>>(t, ret); return ret; });
  47.             } else {
  48.                 static_assert(I == 4, "I must be 3 or 4");
  49.                 return views::cartesian_product(
  50.                     views::ints(-1, 2),
  51.                     views::ints(-1, 2),
  52.                     views::ints(-1, 2),
  53.                     views::ints(-1, 2))| views::transform([](auto t) { point ret; boost::fusion::copy<std::tuple<int,int,int,int>, std::array<int,4>>(t, ret); return ret; });
  54.             } }()
  55.                 | views::remove(point{})
  56.                 | to<std::vector>();
  57.  
  58.         return offsets | views::transform([&,p](point offset) -> point {
  59.             std::transform(p.begin(), p.end(), offset.begin(), offset.begin(), std::plus<>());
  60.             return offset;
  61.         });
  62.     }
  63.  
  64.     template <class point_set>
  65.     auto step(const point_set& from) {
  66.         using namespace ranges;
  67.  
  68.         auto ret = point_set{};
  69.         auto is_active = [&](auto p) { return from.count(p); };
  70.         auto get_neighbours = [](auto p) { return get_neighbours_impl(p); };
  71.  
  72.         auto cubes_to_check = views::concat(from, from | views::transform(get_neighbours) | views::join) | to<point_set>();
  73.         auto should_be_active = [&](auto p) {
  74.             auto active_neighbours = count_if(get_neighbours(p), is_active);
  75.             if (is_active(p)) {
  76.                 return active_neighbours == 2 || active_neighbours == 3;
  77.             } else {
  78.                 return active_neighbours == 3;
  79.             }
  80.         };
  81.         return cubes_to_check | views::filter(should_be_active) | to<point_set>();
  82.     }
  83.  
  84.     template <int dims>
  85.     inline auto execute(std::string s) {
  86.         using point = std::array<int, dims>;
  87.         using point_set = std::unordered_set<point, boost::hash<point>>;
  88.  
  89.         auto active = point_set{ };
  90.         auto iss = std::istringstream{ s };
  91.         auto line = std::string{ };
  92.         auto y = 0;
  93.         while (std::getline(iss, line)) {
  94.             auto x = 0;
  95.             for (auto c : line) {
  96.                 if (c == '#')
  97.                     active.insert({x,y});
  98.                 ++x;
  99.             }
  100.             ++y;
  101.         }
  102.  
  103.         for (int i = 0; i < 6; ++i) {
  104.             active = step(std::move(active));
  105.         }
  106.         return active.size();
  107.     }
  108.  
  109.     namespace a {
  110.  
  111.         inline void run() {
  112.             auto sample_result = 112;
  113.             assert(execute<3>(read_file("day17.sample")) == sample_result);
  114.             std::cout << "day17a sample: " << execute<3>(read_file("day17.sample")) << ", expected: " << sample_result << std::endl;
  115.             std::cout << "day17a: " << execute<3>(read_file("day17.txt")) << std::endl;
  116.         }
  117.     }
  118.  
  119.     namespace b {
  120.  
  121.         inline void run() {
  122.             auto sample_result = 848;
  123.             assert(execute<4>(read_file("day17.sample")) == sample_result);
  124.             std::cout << "day17b sample: " << execute<4>(read_file("day17.sample")) << ", expected: " << sample_result << std::endl;
  125.             std::cout << "day17b: " << execute<4>(read_file("day17.txt")) << std::endl;
  126.         }
  127.     }
  128. }
  129.  
  130. int main() {
  131.     day17::a::run();
  132.     day17::b::run();
  133. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement