aboutsummaryrefslogtreecommitdiff
path: root/2021/day15/day15.cpp
blob: f829cd59be4aada1ab313a0f5d10bed4d00dae9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <queue>
#include <functional>
#include "../utils.h"

class Grid {
	public: Grid () { }
	int xytoi (int x, int y) { return x+ y*sizex; }
	int itox (int i) { return i % sizex; }
	int itoy (int i) { return i / sizex; }
	bool oob (int x, int y) {
		if (x < 0 || x > sizex-1) return true;
		if (y < 0 || y > sizey-1) return true;
		return false;
	}

	int sizex, sizey;
	std::vector<int> cells;

	std::vector<int> fw (int i) {
		int x = itox(i), y = itoy(i);
		std::vector<int> star;
		for (int t=-1; t<2; t++) {
			for (int s=-1; s<2; s++) {
				if (abs(s)+abs(t) == 1 && !oob(x+s, y+t)) {
					star.push_back(xytoi(x+s, y+t));
				}
			}
		}
		return star;
	}

	int astar (int istart, int iend) {
		std::map<int, int> cost;
		std::map<int, int> prev;
		cost[iend] = cells[iend];
		prev[iend] = iend;
		auto cmp = [&cost] (int a, int b) { return cost[a] > cost[b]; };
		std::priority_queue<int, std::vector<int>, decltype(cmp)> Q(cmp);
		Q.push(iend);

		while (Q.size() > 0) {
			int n = Q.top(); Q.pop();
			auto star = fw(n);
			int min = cost[prev[n]];
			for (int j : star) {
				if (prev.find(j) == prev.end()) {
					prev[j] = n;
					cost[j] = cost[prev[j]] + cells[j];
					Q.push(j);
				}
				if (min >= cost[j]) {
					prev[n] = j;
					cost[n] = cost[prev[n]] + cells[n];
					min = cost[j];
				}
			}
		}

		if (true) {
			for (int y=0; y<sizey; y++) {
				for (int x=0; x<sizex; x++) {
					int n = xytoi(x, y);
					int i = itox(prev[n]);
					int j = itoy(prev[n]);
					std::cout << cells[n];
				}
				std::cout << std::endl;
			}
		}

		return cost[istart] - cells[istart];
	}
};

Grid five (Grid grid) {
	Grid big;
	big.sizex = grid.sizex * 5;
	big.sizey = grid.sizey * 5;
	for (int j=0; j<5; j++) {
		for (int y=0; y<grid.sizey; y++) {
			for (int i=0; i<5; i++) {
				for (int x=0; x<grid.sizex; x++) {
					int k = grid.cells[grid.xytoi(x, y)]+(i+j);
					while (k > 9) k -= 9;
					big.cells.push_back(k);
				}
			}
		}
	}
	return big;
}

int main (int argc, char *argv[]) {
	std::string raw;
	std::getline(std::ifstream(argv[1]), raw, '\0');
	std::vector<std::string> lines;
	split(lines, raw, "\n");

	Grid grid;
	grid.sizey = 0;
	for (std::string line : lines) {
		if (line.size() == 0) continue;
		grid.sizex = 0;
		for (char c : line) {
			grid.cells.push_back(std::stoi(std::string { c }));
			grid.sizex ++;
		}
		grid.sizey ++;
	}

	if (argc > 2) grid = five(grid);

	int l = grid.astar(grid.xytoi(0, 0), grid.xytoi(grid.sizex-1, grid.sizey-1));
	std::cout << "min risk: " << l << std::endl;

	return 0;
}