aoc

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

day20b.cpp (2197B)


      1 #include <algorithm>
      2 #include <cstdint>
      3 #include <iostream>
      4 #include <map>
      5 #include <queue>
      6 #include <ranges>
      7 #include <set>
      8 #include <sstream>
      9 #include <string>
     10 #include <string_view>
     11 #include <vector>
     12 using namespace std;
     13 
     14 class Map {
     15 public:
     16 	int N, M, L;
     17 	int *cell;
     18 
     19 	Map(const vector<string>& lines) 
     20 	    : N{(int)lines.size()}, M{(int)lines[0].size()}, cell{new int[M*N]}
     21 	{
     22 		for (int i = 0; i < N; i++) {
     23 			for (int j = 0; j < N; j++) {
     24 				cell[M*i+j] = lines[i][j] == '#' ? -1 : 0;
     25 				if (lines[i][j] == 'S') {
     26 					is = i;
     27 					js = j;
     28 				}
     29 				if (lines[i][j] == 'E') {
     30 					ie = i;
     31 					je = j;
     32 				}
     33 			}
     34 		}
     35 		findpath();
     36 	}
     37 
     38 	~Map() {
     39 		delete[] cell;
     40 	}
     41 
     42 	int& operator()(int i, int j) {
     43 		if (i < 0 || i >= N || j < 0 || j >= M)
     44 			return out_of_bound;
     45 		return cell[M*i+j];
     46 	}
     47 
     48 	const int& operator()(int i, int j) const {
     49 		if (i < 0 || i >= N || j < 0 || j >= M)
     50 			return out_of_bound;
     51 		return cell[M*i+j];
     52 	}
     53 
     54 	int cheats(int x, int y, int k, int p) {
     55 		// Cheats <= p starting at x, y saving at least k picoseconds
     56 
     57 		int count = 0;
     58 		for (int i = 0; i < N; i++)
     59 			for (int j = 0; j < M; j++)
     60 				if ((*this)(i, j) != -1)
     61 					count += saved(i, j, x, y, p) >= k;
     62 
     63 		return count;
     64 	}
     65 private:
     66 	int is, js, ie, je;
     67 	int out_of_bound = -1;
     68 	vector<pair<int, int>> directions {{0,1}, {0,-1}, {1,0}, {-1,0}};
     69 
     70 	void findpath() {
     71 		int i, j, k;
     72 		for (i = is, j = js, k = 1; i != ie || j != je; step(i, j, k))
     73 			(*this)(i, j) = k;
     74 		(*this)(ie, je) = k;
     75 		L = k-1;
     76 	}
     77 
     78 	void step(int& i, int& j, int& k) {
     79 		k++;
     80 		for (auto p : directions) {
     81 			if ((*this)(i+p.first, j+p.second) == 0) {
     82 				i = i+p.first;
     83 				j = j+p.second;
     84 				return;
     85 			}
     86 		}
     87 		cout << "Error! at " << i << ", " << j << endl;
     88 	}
     89 
     90 	int saved(int i, int j, int x, int y, int p) {
     91 		if (int d = abs(i-x) + abs(j-y); d > p)
     92 			return 0;
     93 		else
     94 			return abs((*this)(i, j) - (*this)(x, y)) - d;
     95 	}
     96 };
     97 
     98 int main() {
     99 	string line;
    100 	vector<string> lines;
    101 	while (getline(cin, line))
    102 		lines.push_back(line);
    103 	Map m(lines);
    104 
    105 	int count = 0;
    106 	for (int i = 0; i < m.N; i++)
    107 		for (int j = 0; j < m.M; j++)
    108 			if (m(i, j) != -1)
    109 				count += m.cheats(i, j, 100, 20);
    110 
    111 	cout << count / 2 << endl;
    112 
    113 	return 0;
    114 }