Advertisement
Guest User

Untitled

a guest
Dec 16th, 2020
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.22 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <cassert>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <sstream>
  7. #include <vector>
  8. #include <iterator>
  9. #include <algorithm>
  10. #include <unordered_set>
  11.  
  12. #include <boost/container_hash/hash.hpp>
  13.  
  14. #include <range/v3/algorithm/count_if.hpp>
  15. #include <range/v3/algorithm/copy.hpp>
  16. #include <range/v3/view/transform.hpp>
  17. #include <range/v3/view/filter.hpp>
  18. #include <range/v3/view/remove.hpp>
  19. #include <range/v3/view/iota.hpp>
  20. #include <range/v3/view/cartesian_product.hpp>
  21. #include <range/v3/range/conversion.hpp>
  22.  
  23. inline std::string read_file(std::string_view path) {
  24.     std::ifstream is(path.data());
  25.     return static_cast<std::stringstream const&>(std::stringstream() << is.rdbuf()).str();
  26. }
  27.  
  28. namespace day17 {
  29.  
  30.     namespace a {
  31.  
  32.         using point = std::array<int, 3>;
  33.         using point_set = std::unordered_set<point, boost::hash<point>>;
  34.  
  35.         point_set step(const point_set& from) {
  36.             using namespace ranges;
  37.  
  38.             auto ret = point_set{};
  39.             auto done = point_set{};
  40.             auto q = std::vector<point>( from.begin(), from.end() );
  41.  
  42.             auto get_neighbours = [](point p) {
  43.                 static const auto offsets = views::cartesian_product(
  44.                         views::ints(-1, 2),
  45.                         views::ints(-1, 2),
  46.                         views::ints(-1, 2))
  47.                         | views::remove(std::tuple{ 0,0,0 })
  48.                         | views::transform([](auto t) { auto [x, y, z] = t; return point{ x,y,z }; })
  49.                         | to<std::vector>();
  50.  
  51.                 return offsets | views::transform([&](point offset) -> point {
  52.                     std::transform(p.begin(), p.end(), offset.begin(), offset.begin(), std::plus<>());
  53.                     return offset;
  54.                 });
  55.             };
  56.  
  57.             while (!q.empty()) {
  58.                 auto p = q.back(); q.pop_back();
  59.                 done.insert(p);
  60.                 auto neighbours = get_neighbours(p);
  61.                 auto active_neighbours = count_if(neighbours, [&](point a) { return from.count(a); });
  62.                 if (from.count(p)) {
  63.                     if (active_neighbours == 2 || active_neighbours == 3) {
  64.                         ret.insert(p);
  65.                     }
  66.                     copy(neighbours | views::filter([&](point a) { return !done.count(a); }), std::back_inserter(q));
  67.                 } else if (active_neighbours == 3) {
  68.                     ret.insert(p);
  69.                 }
  70.             }
  71.  
  72.             return ret;
  73.         }
  74.  
  75.         inline auto execute(std::string s) {
  76.             auto active = point_set{ };
  77.             auto iss = std::istringstream{ s };
  78.             auto line = std::string{ };
  79.             auto y = 0;
  80.             while (std::getline(iss, line)) {
  81.                 auto x = 0;
  82.                 for (auto c : line) {
  83.                     if (c == '#')
  84.                         active.insert({x,y,0});
  85.                     ++x;
  86.                 }
  87.                 ++y;
  88.             }
  89.  
  90.             for (int i = 0; i < 6; ++i) {
  91.                 active = step(std::move(active));
  92.             }
  93.             return active.size();
  94.         }
  95.  
  96.         inline void run() {
  97.             auto sample_result = 112;
  98.             assert(execute(read_file("day17.sample")) == sample_result);
  99.             std::cout << "day17a: " << execute(read_file("day17.txt")) << std::endl;
  100.         }
  101.     }
  102.  
  103.     namespace b {
  104.  
  105.         using point = std::array<int, 4>;
  106.         using point_set = std::unordered_set<point, boost::hash<point>>;
  107.  
  108.         point_set step(const point_set& from) {
  109.             using namespace ranges;
  110.  
  111.             auto ret = point_set{};;
  112.             auto done = point_set{};
  113.             auto q = std::vector<point>( from.begin(), from.end() );
  114.  
  115.             auto get_neighbours = [](point p) {
  116.                 static const auto offsets = views::cartesian_product(
  117.                         views::ints(-1, 2),
  118.                         views::ints(-1, 2),
  119.                         views::ints(-1, 2),
  120.                         views::ints(-1, 2))
  121.                         | views::remove(std::tuple{ 0,0,0,0 })
  122.                         | views::transform([](auto t) { auto [x, y, z, w] = t; return point{ x,y,z,w }; })
  123.                         | to<std::vector>();
  124.  
  125.                 return offsets | views::transform([&](point offset) -> point {
  126.                     std::transform(p.begin(), p.end(), offset.begin(), offset.begin(), std::plus<>());
  127.                     return offset;
  128.                 });
  129.             };
  130.  
  131.             while (!q.empty()) {
  132.                 auto p = q.back(); q.pop_back();
  133.                 done.insert(p);
  134.                 auto neighbours = get_neighbours(p);
  135.                 auto active_neighbours = count_if(neighbours, [&](point a) { return from.count(a); });
  136.                 if (from.count(p)) {
  137.                     if (active_neighbours == 2 || active_neighbours == 3) {
  138.                         ret.insert(p);
  139.                     }
  140.                     copy(neighbours | views::filter([&](point a) { return !done.count(a); }), std::back_inserter(q));
  141.                 } else if (active_neighbours == 3) {
  142.                     ret.insert(p);
  143.                 }
  144.             }
  145.  
  146.             return ret;
  147.         }
  148.  
  149.         inline auto execute(std::string s) {
  150.             auto active = point_set{};
  151.             auto iss = std::istringstream{ s };
  152.             auto line = std::string{};
  153.             auto y = 0;
  154.             while (std::getline(iss, line)) {
  155.                 auto x = 0;
  156.                 for (auto c : line) {
  157.                     if (c == '#')
  158.                         active.insert({x,y,0,0});
  159.                     ++x;
  160.                 }
  161.                 ++y;
  162.             }
  163.  
  164.             for (int i = 0; i < 6; ++i) {
  165.                 active = step(std::move(active));
  166.             }
  167.             return active.size();
  168.         }
  169.  
  170.         inline void run() {
  171.             auto sample_result = 848;
  172.             assert(execute(read_file("day17.sample")) == sample_result);
  173.             std::cout << "day17 sample" << execute(read_file("day17.sample")) << std::endl;
  174.             std::cout << "day17b: " << execute(read_file("day17.txt")) << std::endl;
  175.         }
  176.     }
  177. }
  178.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement