This repository was archived by the owner on Jan 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathbotclean.py
More file actions
157 lines (122 loc) · 4.25 KB
/
botclean.py
File metadata and controls
157 lines (122 loc) · 4.25 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
from Queue import Queue
class Node(object):
def __init__(self, posx, posy, value):
self.x = posx
self.y = posy
self.value = value
self.state = None
def __repr__(self):
return self.value
class BreadthFirstSearchMixin(object):
QUEUED = 0
EXAMINED = 1
def setup_bfs(self, node):
''' Enqueue the root node before starting BFS. '''
self.q = Queue()
self.root = node
self._enqueue(node)
def _adjacent_nodes_iter(self, node):
''' Implement this method to define how to get the list of adjacent nodes. '''
raise Exception("Missing method implementation: _adjacent_nodes_iter")
def _enqueue(self, node):
self.q.put(node)
node.state = self.QUEUED
def _dequeue(self):
node = self.q.get()
node.state = self.EXAMINED
return node
def bfs_iter(self):
# Make sure we've enqueued the root.
assert self.root
while not self.q.empty():
# Grab a node to inspect.
node = self._dequeue()
# Examine it to see if that's what you're looking for.
yield node
# If not, enqueue adjacent nodes that have not yet been discovered.
for n in self._adjacent_nodes_iter(node):
if not n.state in [self.EXAMINED, self.QUEUED]:
self._enqueue(n)
class Grid(object):
def __init__(self, grid):
self.grid = grid
def __repr__(self):
return "\n".join([str(i) for i in self.grid]) + "\n"
def set(self, x, y, value):
self.grid[x][y] = value
def get(self, x, y):
return self.grid[x][y]
def iter_with_coord(self):
for x, row in enumerate(self.grid):
for y, item in enumerate(row):
yield (x, y, item)
class BFSGrid(Grid, BreadthFirstSearchMixin):
def __init__(self, grid):
super(eval(self.__class__.__name__), self).__init__(grid)
# Convert to a Node type so we can mark it as queued and examined.
for x, y, value in self.iter_with_coord():
self.set(x, y, Node(x, y, value))
def _adjacent_nodes_iter(self, node):
x = node.x
y = node.y
coord_to_try = [
(x - 1, y - 1),
(x - 1, y),
(x - 1, y + 1),
(x, y - 1),
(x, y + 1),
(x + 1, y - 1),
(x + 1, y),
(x + 1, y + 1),
]
# Filter out invalid coordinates.
coord_to_try = [(i, j) for i, j in coord_to_try if i >= 0 and j >= 0]
for i, j in coord_to_try:
try:
yield self.get(i, j)
except IndexError as _:
# Invalid node; we must be on a boundary of the grid.
pass
class Bot(object):
DUST = 'd'
def __init__(self, posx, posy, board):
self.x = posx
self.y = posy
self.board = BFSGrid(board)
def _get_direction_from(self, start, end):
''' Get the next move if we want to travel from `start` to `end`. '''
row_diff = start.x - end.x
col_diff = start.y - end.y
if not row_diff == 0:
if row_diff > 0:
move = 'UP'
else:
move = 'DOWN'
elif not col_diff == 0:
if col_diff > 0:
move = 'LEFT'
else:
move = 'RIGHT'
return move
def next_move(self):
move = None
# Clean the dust if we're on it.
current_node = self.board.get(self.x, self.y)
if current_node.value == self.DUST:
move = 'CLEAN'
# Otherwise, go looking for some dust.
if not move:
self.board.setup_bfs(current_node)
for i in self.board.bfs_iter():
if i.value == self.DUST:
move = self._get_direction_from(current_node, i)
break
return move
def next_move(posx, posy, board):
b = Bot(posx, posy, board)
print b.next_move()
# Tail starts here
if __name__ == "__main__":
pos = [int(i) for i in raw_input().strip().split()]
board = [[j for j in raw_input().strip()] for i in range(5)]
next_move(pos[0], pos[1], board)