8
8
#include < unordered_set>
9
9
#include < vector>
10
10
11
- using Position = std::pair<int , int >;
12
- using Direction = std::pair<int , int >;
11
+ // using Position = std::pair<int, int>;
12
+ // using Direction = std::pair<int, int>;
13
+
14
+ template <class T >
15
+ struct Position : std::pair<T, T> {
16
+ Position () {
17
+ this ->first = 0 ;
18
+ this ->second = 0 ;
19
+ }
20
+ Position (T x, T y) {
21
+ this ->first = x;
22
+ this ->second = y;
23
+ }
24
+ Position operator +(const Position &p2) {
25
+ return {this ->first + p2.first , this ->second + p2.second };
26
+ }
27
+ Position &operator +=(const Position &rhs) {
28
+ this ->first += rhs.first ;
29
+ this ->second += rhs.second ;
30
+ return *this ;
31
+ }
32
+ };
13
33
14
- template <>
15
- struct std ::hash<Position> {
16
- auto operator ()(const Position &v) const -> size_t {
34
+ template <class T >
35
+ using Direction = Position<T>;
36
+
37
+ template <class T >
38
+ struct std ::hash<Position<T>> {
39
+ auto operator ()(const Position<T> &v) const -> size_t {
17
40
return size_t (v.first ) << 32 | v.second ;
18
41
}
19
42
};
20
43
21
- template <>
22
- struct std ::hash<std::pair<Position, Direction >> {
23
- auto operator ()(const std::pair<Position, Direction> &v) const -> size_t {
24
- return std::hash<Position> ()(v.first ) ^ std::hash<Direction>()(v.second );
44
+ template <class T >
45
+ struct std ::hash<std::pair<Position<T>, Position<T> >> {
46
+ auto operator ()(const std::pair<Position<T> , Direction<T> > &v) const -> size_t {
47
+ return std::hash<Position<T>> ()(v.first ) ^ std::hash<Direction<T> >()(v.second );
25
48
}
26
49
};
27
50
51
+ template <class T >
28
52
struct Map {
29
53
Map () = delete ;
30
54
@@ -33,34 +57,34 @@ struct Map {
33
57
visited.insert (guard_position);
34
58
}
35
59
36
- [[nodiscard]] Position guard () const {
60
+ [[nodiscard]] auto guard () const -> Position<T> {
37
61
return guard_position;
38
62
}
39
63
40
- [[nodiscard]] auto & get_visited () {
64
+ [[nodiscard]] auto get_visited () -> auto & {
41
65
return visited;
42
66
}
43
67
44
- int get_visited_size () const {
68
+ [[nodiscard]] auto get_visited_size () const -> int {
45
69
return int (visited.size ());
46
70
}
47
71
48
- char get_location (const Position &position) const {
72
+ [[nodiscard]] auto get_location (const Position<T> &position) const -> char {
49
73
const auto &[col, row] = position;
50
74
if (is_inside (position))
51
75
return contents[row][col];
52
76
else
53
77
return ' \0 ' ;
54
78
}
55
79
56
- bool is_inside (const Position &position) const {
80
+ [[nodiscard]] auto is_inside (const Position<T> &position) const -> bool {
57
81
return ((position.first >= 0 ) && (position.first < int (contents.front ().size ()))) && ((position.second >= 0 ) && (position.second < int (contents.size ())));
58
82
}
59
83
60
84
private:
61
- std::vector<std::string> contents;
62
- Position guard_position;
63
- std::unordered_set<Position> visited;
85
+ std::vector<std::string> contents;
86
+ Position<T> guard_position;
87
+ std::unordered_set<Position<T> > visited;
64
88
65
89
void find_guard () {
66
90
int x{}, y{};
@@ -75,32 +99,30 @@ struct Map {
75
99
}
76
100
};
77
101
78
- Position operator +(const Position &p1, const Direction &p2) {
79
- return {p1.first + p2.first , p1.second + p2.second };
80
- }
81
-
82
- void turn (std::array<std::pair<int , int >, 4 > &directions) {
102
+ template <class T >
103
+ void turn (std::array<Direction<T>, 4 > &directions) {
83
104
std::ranges::rotate (directions, directions.end () - 1 );
84
105
}
85
106
86
- void print_position (const Position &p) {
107
+ void print_position (const auto &p) {
87
108
std::cout << " [" << p.first << " , " << p.second << " ]\n " ;
88
109
}
89
110
90
- std::array<Direction, 4 > init_directions () {
91
- std::array<Direction, 4 > directions{
111
+ template <class T >
112
+ auto init_directions () -> std::array<Direction<T>, 4> {
113
+ std::array<Direction<T>, 4 > directions{
92
114
{{0 , -1 }, {-1 , 0 }, {0 , 1 }, {1 , 0 }}
93
115
};
94
116
return directions;
95
117
}
96
118
97
- auto parse_instructions (const std::vector<std::string> &instructions) -> Map {
98
- auto map = Map{instructions};
119
+ auto parse_instructions (const std::vector<std::string> &instructions) -> Map<int> {
120
+ auto map = Map< int > {instructions};
99
121
return map;
100
122
}
101
123
102
- auto solve_part_1 (Map &map) -> int {
103
- auto directions = init_directions ();
124
+ auto solve_part_1 (Map< int > &map) -> int {
125
+ auto directions = init_directions< int > ();
104
126
auto guard_position = map.guard ();
105
127
auto &visited = map.get_visited ();
106
128
@@ -118,26 +140,29 @@ auto solve_part_1(Map &map) -> int {
118
140
return map.get_visited_size ();
119
141
}
120
142
121
- auto solve_part_2 (Map &map) -> int {
143
+ auto solve_part_2 (Map< int > &map) -> int {
122
144
auto guard_position = map.guard ();
123
145
auto &visited = map.get_visited ();
124
146
125
147
auto count = 0 ;
126
148
149
+ visited.erase (guard_position);
150
+
127
151
for (const auto &obstacle : visited) {
128
- auto directions = init_directions ();
152
+ auto directions = init_directions< int > ();
129
153
guard_position = map.guard ();
130
- std::unordered_set<std::pair<Position, Direction>> tracemap{
154
+ std::unordered_set<std::pair<Position< int > , Direction< int > >> tracemap{
131
155
{guard_position, directions.front ()}
132
156
};
133
157
134
- if (obstacle == guard_position)
135
- continue ;
158
+ // if (obstacle == guard_position)
159
+ // continue;
136
160
161
+ Position<int > next_position{};
137
162
tracemap.insert ({guard_position, directions.front ()});
138
163
while (true ) {
139
- Position next_position = guard_position + directions.front ();
140
- auto c = map.get_location (next_position);
164
+ next_position = guard_position + directions.front ();
165
+ auto c = map.get_location (next_position);
141
166
if (c == ' \0 ' ) {
142
167
break ;
143
168
} else if ((c == ' #' ) || (next_position == obstacle)) {
0 commit comments