Advertisement
kpvw

Day 23

Dec 23rd, 2022
932
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.59 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <vector>
  5. #include <set>
  6. #include <map>
  7. #include <array>
  8.  
  9. int main() {
  10.   std::ifstream input("input.txt");
  11.  
  12.   using Position = std::array<int, 2>;
  13.  
  14.   std::set<Position> elves;
  15.  
  16.   auto print_elves = [&elves]() {
  17.     int min_x = INT_MAX;
  18.     int max_x = INT_MIN;
  19.  
  20.     int min_y = INT_MAX;
  21.     int max_y = INT_MIN;
  22.  
  23.     for (auto& elf : elves) {
  24.       int x = elf[0];
  25.       int y = elf[1];
  26.  
  27.       if (x < min_x) { min_x = x; }
  28.       if (x > max_x) { max_x = x; }
  29.  
  30.       if (y < min_y) { min_y = y; }
  31.       if (y > max_y) { max_y = y; }
  32.     }
  33.  
  34.     for (int y = min_y; y <= max_y; y++) {
  35.       for (int x = min_x; x <= max_x; x++) {
  36.         if (!elves.contains({ x, y })) {
  37.           std::cout << '.';
  38.         }
  39.         else {
  40.           std::cout << '#';
  41.         }
  42.       }
  43.       std::cout << std::endl;
  44.     }
  45.     std::cout << std::endl;
  46.   };
  47.  
  48.   std::string line;
  49.   int y = 0;
  50.   while (std::getline(input, line)) {
  51.     int x = 0;
  52.     for (auto& c : line) {
  53.       if (c == '#') {
  54.         elves.insert({ x, y });
  55.       }
  56.       x++;
  57.     }
  58.     y++;
  59.   }
  60.   //print_elves();
  61.  
  62.   // Proposing moves
  63.  
  64.   constexpr uint8_t NORTH = 0;
  65.   constexpr uint8_t SOUTH = 1;
  66.   constexpr uint8_t WEST = 2;
  67.   constexpr uint8_t EAST = 3;
  68.   uint8_t first_direction = 0;
  69.   auto proposed_step = [&elves, &first_direction](const Position& elf) {
  70.     int x = elf[0];
  71.     int y = elf[1];
  72.  
  73.     bool should_move = false;
  74.     for (int dx = -1; dx <= 1; dx++) {
  75.       for (int dy = -1; dy <= 1; dy++) {
  76.         if (dx == dy && dy == 0) { continue; }
  77.         if (elves.contains({ x + dx, y + dy })) {
  78.           should_move = true;
  79.           break;
  80.         }
  81.       }
  82.     }
  83.     if (!should_move) {
  84.       return Position({ x, y });
  85.     }
  86.  
  87.     for (uint8_t i = 0; i < 4; i++) {
  88.       switch ((first_direction + i) % 4) {
  89.       case NORTH:
  90.         if (!elves.contains({ x + 1, y - 1 })
  91.           && !elves.contains({ x - 1, y - 1 })
  92.           && !elves.contains({ x, y - 1 })) {
  93.           return Position({ x, y - 1 });
  94.         }
  95.         else {
  96.           break;
  97.         }
  98.       case SOUTH:
  99.         if (!elves.contains({ x + 1, y + 1 })
  100.           && !elves.contains({ x - 1, y + 1 })
  101.           && !elves.contains({ x, y + 1 })) {
  102.           return Position({ x, y + 1 });
  103.         }
  104.         else {
  105.           break;
  106.         }
  107.       case WEST:
  108.         if (!elves.contains({ x - 1, y - 1 })
  109.           && !elves.contains({ x - 1, y + 1 })
  110.           && !elves.contains({ x - 1, y })) {
  111.           return Position({ x - 1, y });
  112.         }
  113.         else {
  114.           break;
  115.         }
  116.       case EAST:
  117.         if (!elves.contains({ x + 1, y - 1 })
  118.           && !elves.contains({ x + 1, y + 1 })
  119.           && !elves.contains({ x + 1, y })) {
  120.           return Position({ x + 1, y });
  121.         }
  122.         else {
  123.           break;
  124.         }
  125.       }
  126.     }
  127.     return Position({ x, y });
  128.   };
  129.  
  130.   // Map associating each elf with their proposed destination
  131.   std::map<Position, Position> proposed_moves;
  132.  
  133.   // Stores counts for how many elves have the position as a destination
  134.   std::map<Position, int> destination_counts;
  135.  
  136.   for (size_t i = 0; i < 10; i++) {
  137.     proposed_moves.clear();
  138.     destination_counts.clear();
  139.  
  140.     // Propose moves
  141.     for (auto& elf : elves) {
  142.       auto proposed_move = proposed_step(elf);
  143.       proposed_moves[elf] = proposed_move;
  144.       if (destination_counts.contains(proposed_move)) {
  145.         destination_counts[proposed_move]++;
  146.       }
  147.       else {
  148.         destination_counts[proposed_move] = 1;
  149.       }
  150.     }
  151.  
  152.     std::set<Position> new_elves;
  153.  
  154.     // Make moves
  155.     for (auto& elf : elves) {
  156.       auto& proposed_move = proposed_moves[elf];
  157.       if (destination_counts[proposed_move] == 1) {
  158.         new_elves.insert(proposed_move);
  159.       }
  160.       else {
  161.         new_elves.insert(elf);
  162.       }
  163.     }
  164.  
  165.     elves = new_elves;
  166.  
  167.     first_direction = (first_direction + 1) % 4;
  168.   }
  169.  
  170.   int min_x = INT_MAX;
  171.   int max_x = INT_MIN;
  172.  
  173.   int min_y = INT_MAX;
  174.   int max_y = INT_MIN;
  175.  
  176.   for (auto& elf : elves) {
  177.     int x = elf[0];
  178.     int y = elf[1];
  179.  
  180.     if (x < min_x) { min_x = x; }
  181.     if (x > max_x) { max_x = x; }
  182.  
  183.     if (y < min_y) { min_y = y; }
  184.     if (y > max_y) { max_y = y; }
  185.   }
  186.  
  187.   int empty_ground_count = 0;
  188.   for (int y = min_y; y <= max_y; y++) {
  189.     for (int x = min_x; x <= max_x; x++) {
  190.       if (!elves.contains({ x, y })) {
  191.         empty_ground_count++;
  192.       }
  193.       else {
  194.       }
  195.     }
  196.   }
  197.  
  198.   std::cout << "Part 1: " << empty_ground_count << std::endl;
  199.  
  200.   size_t i;
  201.   for (i = 10; i < INT_MAX; i++) {
  202.     proposed_moves.clear();
  203.     destination_counts.clear();
  204.  
  205.     // Propose moves
  206.     for (auto& elf : elves) {
  207.       auto proposed_move = proposed_step(elf);
  208.       proposed_moves[elf] = proposed_move;
  209.       if (destination_counts.contains(proposed_move)) {
  210.         destination_counts[proposed_move]++;
  211.       }
  212.       else {
  213.         destination_counts[proposed_move] = 1;
  214.       }
  215.     }
  216.  
  217.     std::set<Position> new_elves;
  218.  
  219.     bool elves_moved = false;
  220.     // Make moves
  221.     for (auto& elf : elves) {
  222.       auto& proposed_move = proposed_moves[elf];
  223.       if (destination_counts[proposed_move] == 1) {
  224.         new_elves.insert(proposed_move);
  225.         if (proposed_move != elf) { elves_moved = true; }
  226.       }
  227.       else {
  228.         new_elves.insert(elf);
  229.       }
  230.     }
  231.  
  232.     elves = new_elves;
  233.  
  234.     if (!elves_moved) {
  235.       break;
  236.     }
  237.  
  238.     first_direction = (first_direction + 1) % 4;
  239.   }
  240.  
  241.   std::cout << "Part 2: " << i+1 << std::endl;
  242. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement