day15b.cpp (3835B)
1 /* 2 The code here is not great, but I don't feel like cleaning it up 3 */ 4 5 #include <iostream> 6 #include <cstdint> 7 #include <algorithm> 8 #include <string> 9 #include <string_view> 10 #include <vector> 11 #include <set> 12 using namespace std; 13 14 class Direction { 15 public: 16 const int U, R; 17 18 Direction(char c) : 19 U{c == 'v' ? 1 : (c == '^' ? -1 : 0)}, 20 R{c == '>' ? 1 : (c == '<' ? -1 : 0)} {} 21 22 Direction(const int i, const int j) : U{i}, R{j} {} 23 24 Direction turnright() const { 25 return turn(-1, 0); 26 } 27 28 Direction turnleft() const { 29 return turn(1, 0); 30 } 31 32 bool operator<(const Direction& d) const { // For set<Direction> 33 return this->U < d.U || (this->U == d.U && this->R < d.R); 34 } 35 private: 36 Direction turn(int64_t sin, int64_t cos) const { 37 return Direction(cos * U - sin * R, sin * U + cos * R); 38 } 39 }; 40 41 class Position { 42 public: 43 int64_t i, j; 44 45 Position() : Position(0, 0) {} 46 47 Position(int64_t a, int64_t b) : i{a}, j{b} {} 48 49 Position step(const Direction d) const { 50 return Position(i+d.U, j+d.R); 51 } 52 }; 53 54 const Direction all_directions[] = { 55 Direction(1, 0), Direction(-1, 0), Direction(0, 1), Direction(0, -1) 56 }; 57 58 class Board { 59 public: 60 int64_t N, M; 61 Position robot; 62 63 Board(const vector<string>& lines) : 64 N{static_cast<int64_t>(lines.size())}, 65 M{static_cast<int64_t>(lines[0].size())}, 66 cells(M*N) 67 { 68 for (int64_t i = 0; i < N; i++) { 69 for (int64_t j = 0; j < M; j++) { 70 cells[M*i+j] = lines[i][j]; 71 if (lines[i][j] == '@') 72 robot = Position(i, j); 73 } 74 } 75 } 76 77 char& operator[](const Position p) { 78 if (const auto c = coord(p); c == -1) 79 return out_of_bound; 80 else 81 return cells[c]; 82 } 83 84 void move_robot(const Direction d) { 85 if (move(robot, d)) 86 robot = robot.step(d); 87 } 88 89 int64_t gps() { 90 int64_t tot = 0; 91 for (Position p(0, 0); p.i < N; p.i++) 92 for (p.j = 0; p.j < M; p.j++) 93 if ((*this)[p] == '[') 94 tot += 100*p.i + p.j; 95 return tot; 96 } 97 98 void print() { 99 for (Position p(0, 0); p.i < N; p.i++) { 100 for (p.j = 0; p.j < M; p.j++) 101 cout << (*this)[p]; 102 cout << endl; 103 } 104 } 105 private: 106 char out_of_bound = '$'; 107 108 vector<char> cells; 109 110 int64_t coord(const Position p) const { 111 auto [i, j] = p; 112 return i >= N || i < 0 || j >= M || j < 0 ? -1 : M * i + j; 113 } 114 115 bool move(Position p, Direction d) { 116 return d.U == 0 ? move_h(p, d) : move_v(p, d); 117 } 118 119 bool move_h(Position p, Direction d) { 120 auto q = p.step(d); 121 switch ((*this)[q]) { 122 case '.': 123 (*this)[q] = (*this)[p]; 124 (*this)[p] = '.'; 125 return true; 126 case '[': 127 case ']': 128 return move(q, d) ? move(p, d) : false; 129 default: 130 return false; 131 } 132 } 133 134 bool move_v(Position p, Direction d) { 135 if (!isfree_v(p, d)) 136 return false; 137 138 auto q = p.step(d); 139 if ((*this)[q] == '[') { 140 move_v(q, d); 141 move_v(q.step(Direction('>')), d); 142 } 143 if ((*this)[q] == ']') { 144 move_v(q, d); 145 move_v(q.step(Direction('<')), d); 146 } 147 (*this)[q] = (*this)[p]; 148 (*this)[p] = '.'; 149 return true; 150 } 151 152 bool isfree_v(Position p, Direction d) { 153 auto q = p.step(d); 154 switch ((*this)[q]) { 155 case '.': 156 return true; 157 case ']': 158 return isfree_v(q, d) && 159 isfree_v(q.step(Direction('<')), d); 160 case '[': 161 return isfree_v(q, d) && 162 isfree_v(q.step(Direction('>')), d); 163 default: 164 return false; 165 } 166 if ((*this)[q] == '.') 167 return true; 168 } 169 }; 170 171 int main() { 172 string line; 173 vector<string> lines; 174 175 for (getline(cin, line); line.size() > 0; getline(cin, line)) { 176 string wideline = ""; 177 for (const auto& c : line) { 178 switch (c) { 179 case 'O': 180 wideline += "[]"; 181 break; 182 case '@': 183 wideline += "@."; 184 break; 185 default: 186 wideline += c; 187 wideline += c; 188 break; 189 } 190 } 191 lines.push_back(wideline); 192 } 193 Board board(lines); 194 195 while (getline(cin, line)) 196 for (const auto& c : line) 197 board.move_robot(Direction(c)); 198 199 cout << board.gps() << endl; 200 201 return 0; 202 }