-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrobot_grid.cpp
More file actions
161 lines (143 loc) · 3.49 KB
/
robot_grid.cpp
File metadata and controls
161 lines (143 loc) · 3.49 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* Imagine a robot sitting on the upper left corner of a grid with H rows and W columns.
The robot can only move in two directions, right and down, but certain cells are "off limits"
such that the robot cannot step on them. Design an algorithm to find a path for the robot
from the top left to the bottom right */
#include <iostream>
#include <array>
#include <cstring>
#include <vector>
#define O true
#define X false
template <size_t W, size_t H>
struct Grid
{
typedef std::array<bool, H> Col;
typedef std::array<Col, W> Cols;
Cols cols;
Grid(const std::initializer_list<bool> &values)
{
size_t i = 0;
auto* data = values.begin();
for (size_t y = 0; y < H; y++) {
for (size_t x = 0; x < W; x++) {
cols[x][y] = data[i++];
}
}
}
Col &operator[](size_t i)
{
return cols[i];
}
const Col &operator[](size_t i) const
{
return cols[i];
}
};
struct Position
{
size_t x;
size_t y;
};
using Path = std::vector<Position>;
template <size_t W, size_t H>
bool findPath(const Grid<W, H> &grid, Path& path, const Position& pos = {0, 0})
{
path.emplace_back(pos);
auto rights = W - pos.x - 1;
auto downs = H - pos.y - 1;
if (rights == downs) {
if (rights == 0 && downs == 0) {
return true;
}
// fork
if (rights > 0 && grid[pos.x + 1][pos.y]) {
Path newPath;
// go right
if (findPath(grid, newPath, { pos.x + 1, pos.y })) {
// merge
path.insert(path.end(), newPath.begin(), newPath.end());
return true;
}
}
if (downs > 0 && grid[pos.x][pos.y + 1]) {
Path newPath;
// go down
if (findPath(grid, newPath, { pos.x, pos.y + 1 })) {
// merge
path.insert(path.end(), newPath.begin(), newPath.end());
return true;
}
}
}
else
{
size_t a, b;
if (rights > downs) {
a = 1; b = 0;
} else {
a = 0; b = 1;
}
Position nextPos{ pos.x + a, pos.y + b};
for (size_t i = 0; i < 2; ++i)
{
if (nextPos.x <= W && nextPos.y <= H && grid[nextPos.x][nextPos.y]) {
return findPath(grid, path, nextPos);
}
nextPos = { pos.x + b, pos.y + a };
}
}
return false;
}
void printPath(const Path& path) {
for (auto& pos : path) {
std::cout << "(" << pos.x + 1 << ", " << pos.y + 1 << ") ";
}
}
template <size_t W, size_t H>
void test(const char *name, const Grid<W, H> &grid)
{
std::cout << name << ": " << std::endl;
Path path;
if (findPath(grid, path)) {
printPath(path);
} else {
std::cout << "path not found";
}
std::cout << std::endl;
}
int main()
{
test("1x1",
Grid<1, 1>{{
O
}});
test(
"3x3, no obstacles",
Grid<3, 3>{{
O,O,O,
O,O,O,
O,O,O,
}});
test(
"3x3, center obstacle",
Grid<3, 3>{{
O,O,O,
O,X,O,
O,O,O,
}});
test(
"5x3, full cornering",
Grid<5, 3>{{
O,X,O,O,O,
O,X,O,O,O,
O,O,O,O,O,
}});
test(
"3x3, no path",
Grid<3, 3>{{
O,O,O,
O,O,O,
O,O,X,
}});
return 0;
}