aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

day15a.cpp (2708B)


      1 #include <iostream>
      2 #include <cstdint>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string_view>
      6 #include <vector>
      7 #include <set>
      8 using namespace std;
      9 
     10 class Direction {
     11 public:
     12 	const int U, R;
     13 
     14 	Direction(char c) :
     15 	    U{c == 'v' ? 1 : (c == '^' ? -1 : 0)},
     16 	    R{c == '>' ? 1 : (c == '<' ? -1 : 0)} {}
     17 
     18 	Direction(const int i, const int j) : U{i}, R{j} {}
     19 
     20 	Direction turnright() const {
     21 		return turn(-1, 0);
     22 	}
     23 
     24 	Direction turnleft() const {
     25 		return turn(1, 0);
     26 	}
     27 
     28 	bool operator<(const Direction& d) const { // For set<Direction>
     29 		return this->U < d.U || (this->U == d.U && this->R < d.R);
     30 	}
     31 private:
     32 	Direction turn(int64_t sin, int64_t cos) const {
     33 		return Direction(cos * U - sin * R, sin * U + cos * R);
     34 	}
     35 };
     36 
     37 class Position {
     38 public:
     39 	int64_t i, j;
     40 
     41 	Position() : Position(0, 0) {}
     42 
     43 	Position(int64_t a, int64_t b) : i{a}, j{b} {}
     44 
     45 	Position step(const Direction d) const {
     46 		return Position(i+d.U, j+d.R);
     47 	}
     48 };
     49 
     50 const Direction all_directions[] = {
     51 	Direction(1, 0), Direction(-1, 0), Direction(0, 1), Direction(0, -1)
     52 };
     53 
     54 class Board {
     55 public:
     56 	int64_t N, M;
     57 	Position robot;
     58 
     59 	Board(const vector<string>& lines) :
     60 	    N{static_cast<int64_t>(lines.size())},
     61 	    M{static_cast<int64_t>(lines[0].size())},
     62 	    cells(M*N)
     63 	{
     64 		for (int64_t i = 0; i < N; i++) {
     65 			for (int64_t j = 0; j < M; j++) {
     66 				cells[N*i+j] = lines[i][j];
     67 				if (lines[i][j] == '@')
     68 					robot = Position(i, j);
     69 			}
     70 		}
     71 	}
     72 
     73 	char& operator[](const Position p) {
     74 		if (const auto c = coord(p); c == -1)
     75 			return out_of_bound;
     76 		else
     77 			return cells[c];
     78 	}
     79 
     80 	void move_robot(const Direction d) {
     81 		if (move(robot, d))
     82 			robot = robot.step(d);
     83 	}
     84 
     85 	int64_t gps() {
     86 		int64_t tot = 0;
     87 		for (Position p(0, 0); p.i < N; p.i++)
     88 			for (p.j = 0; p.j < M; p.j++)
     89 				if ((*this)[p] == 'O')
     90 					tot += 100*p.i + p.j;
     91 		return tot;
     92 	}
     93 
     94 	void print() {
     95 		for (Position p(0, 0); p.i < N; p.i++) {
     96 			for (p.j = 0; p.j < M; p.j++)
     97 				cout << (*this)[p];
     98 			cout << endl;
     99 		}
    100 	}
    101 private:
    102 	char out_of_bound = '$';
    103 
    104 	vector<char> cells;
    105 
    106 	int64_t coord(const Position p) const {
    107 		auto [i, j] = p;
    108 		return i >= N || i < 0 || j >= M || j < 0 ? -1 : N * i + j;
    109 	}
    110 
    111 	bool move(Position p, Direction d) {
    112 		auto q = p.step(d);
    113 		switch ((*this)[q]) {
    114 		case '.':
    115 			(*this)[q] = (*this)[p];
    116 			(*this)[p] = '.';
    117 			return true;
    118 		case 'O':
    119 			return move(q, d) ? move(p, d) : false;
    120 		default:
    121 			return false;
    122 		}
    123 	}
    124 };
    125 
    126 int main() {
    127 	string line;
    128 	vector<string> lines;
    129 
    130 	for (getline(cin, line); line.size() > 0; getline(cin, line))
    131 		lines.push_back(line);
    132 	Board board(lines);
    133 
    134 	while (getline(cin, line))
    135 		for (const auto& c : line)
    136 			board.move_robot(Direction(c));
    137 
    138 	cout << board.gps() << endl;
    139 
    140 	return 0;
    141 }